1
Fork 0

Consolidate wasi alloc with unix alloc.

This commit is contained in:
Eric Huss 2020-08-20 11:00:41 -07:00
parent 5a4098ed0f
commit cfb955da6f
3 changed files with 45 additions and 111 deletions

View file

@ -52,46 +52,48 @@ unsafe impl GlobalAlloc for System {
} }
} }
#[cfg(any( cfg_if::cfg_if! {
target_os = "android", if #[cfg(any(
target_os = "illumos", target_os = "android",
target_os = "redox", target_os = "illumos",
target_os = "solaris" target_os = "redox",
))] target_os = "solaris"
#[inline] ))] {
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { #[inline]
// On android we currently target API level 9 which unfortunately unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
// doesn't have the `posix_memalign` API used below. Instead we use // On android we currently target API level 9 which unfortunately
// `memalign`, but this unfortunately has the property on some systems // doesn't have the `posix_memalign` API used below. Instead we use
// where the memory returned cannot be deallocated by `free`! // `memalign`, but this unfortunately has the property on some systems
// // where the memory returned cannot be deallocated by `free`!
// Upon closer inspection, however, this appears to work just fine with //
// Android, so for this platform we should be fine to call `memalign` // Upon closer inspection, however, this appears to work just fine with
// (which is present in API level 9). Some helpful references could // Android, so for this platform we should be fine to call `memalign`
// possibly be chromium using memalign [1], attempts at documenting that // (which is present in API level 9). Some helpful references could
// memalign + free is ok [2] [3], or the current source of chromium // possibly be chromium using memalign [1], attempts at documenting that
// which still uses memalign on android [4]. // memalign + free is ok [2] [3], or the current source of chromium
// // which still uses memalign on android [4].
// [1]: https://codereview.chromium.org/10796020/ //
// [2]: https://code.google.com/p/android/issues/detail?id=35391 // [1]: https://codereview.chromium.org/10796020/
// [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579 // [2]: https://code.google.com/p/android/issues/detail?id=35391
// [4]: https://chromium.googlesource.com/chromium/src/base/+/master/ // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579
// /memory/aligned_memory.cc // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/
libc::memalign(layout.align(), layout.size()) as *mut u8 // /memory/aligned_memory.cc
} libc::memalign(layout.align(), layout.size()) as *mut u8
}
#[cfg(not(any( } else if #[cfg(target_os = "wasi")] {
target_os = "android", #[inline]
target_os = "illumos", unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
target_os = "redox", libc::aligned_alloc(layout.align(), layout.size()) as *mut u8
target_os = "solaris" }
)))] } else {
#[inline] #[inline]
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
let mut out = ptr::null_mut(); let mut out = ptr::null_mut();
// posix_memalign requires that the alignment be a multiple of `sizeof(void*)`. // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
// Since these are all powers of 2, we can just use max. // Since these are all powers of 2, we can just use max.
let align = layout.align().max(crate::mem::size_of::<usize>()); let align = layout.align().max(crate::mem::size_of::<usize>());
let ret = libc::posix_memalign(&mut out, align, layout.size()); let ret = libc::posix_memalign(&mut out, align, layout.size());
if ret != 0 { ptr::null_mut() } else { out as *mut u8 } if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
}
}
} }

View file

@ -1,69 +0,0 @@
#![deny(unsafe_op_in_unsafe_fn)]
use crate::alloc::{GlobalAlloc, Layout, System};
use crate::ptr;
use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN};
// SAFETY: All methods implemented follow the contract rules defined
// in `GlobalAlloc`.
#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
// SAFETY: `libc::malloc` is guaranteed to be safe, it will allocate
// `layout.size()` bytes of memory and return a pointer to it
unsafe { libc::malloc(layout.size()) as *mut u8 }
} else {
// SAFETY: `libc::aligned_alloc` is guaranteed to be safe if
// `layout.size()` is a multiple of `layout.align()`. This
// constraint can be satisfied if `pad_to_align` is called,
// which creates a layout by rounding the size of this layout up
// to a multiple of the layout's alignment
let aligned_layout = layout.pad_to_align();
unsafe { libc::aligned_alloc(aligned_layout.align(), aligned_layout.size()) as *mut u8 }
}
}
#[inline]
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
// SAFETY: `libc::calloc` is safe as long that `layout.size() * 1`
// would not result in integer overflow which cannot happen,
// multiplying by one never overflows
unsafe { libc::calloc(layout.size(), 1) as *mut u8 }
} else {
// SAFETY: The safety contract for `alloc` must be upheld by the caller
let ptr = unsafe { self.alloc(layout.clone()) };
if !ptr.is_null() {
// SAFETY: in the case of the `ptr` being not null
// it will be properly aligned and a valid ptr
// which satisfies `ptr::write_bytes` safety constrains
unsafe { ptr::write_bytes(ptr, 0, layout.size()) };
}
ptr
}
}
#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
// SAFETY: `libc::free` is guaranteed to be safe if `ptr` is allocated
// by this allocator or if `ptr` is NULL
unsafe { libc::free(ptr as *mut libc::c_void) }
}
#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
// SAFETY: `libc::realloc` is safe if `ptr` is allocated by this
// allocator or NULL
// - If `new_size` is 0 and `ptr` is not NULL, it will act as `libc::free`
// - If `new_size` is not 0 and `ptr` is NULL, it will act as `libc::malloc`
// - Else, it will resize the block accordingly
unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 }
} else {
// SAFETY: The safety contract for `realloc_fallback` must be upheld by the caller
unsafe { realloc_fallback(self, ptr, layout, new_size) }
}
}
}

View file

@ -17,6 +17,7 @@
use crate::io as std_io; use crate::io as std_io;
use crate::mem; use crate::mem;
#[path = "../unix/alloc.rs"]
pub mod alloc; pub mod alloc;
pub mod args; pub mod args;
#[path = "../unsupported/cmath.rs"] #[path = "../unsupported/cmath.rs"]