diff --git a/src/header/stdlib/mod.rs b/src/header/stdlib/mod.rs index eb157f70fc0e41584b6c8ebe1e9bea0e46db9e95..b1170693b6bf85749d61da9923ecac17bce9ef24 100644 --- a/src/header/stdlib/mod.rs +++ b/src/header/stdlib/mod.rs @@ -1,7 +1,7 @@ //! stdlib implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/stdlib.h.html -use core::{intrinsics, iter, mem, ptr, slice}; use core::convert::TryFrom; +use core::{intrinsics, iter, mem, ptr, slice}; use rand::distributions::{Alphanumeric, Distribution, Uniform}; use rand::prng::XorShiftRng; use rand::rngs::JitterRng; @@ -582,6 +582,31 @@ pub extern "C" fn nrand48(xsubi: [c_ushort; 3]) -> c_long { unimplemented!(); } +#[no_mangle] +pub unsafe extern "C" fn posix_memalign( + memptr: *mut *mut c_void, + alignment: size_t, + size: size_t, +) -> c_int { + const void_ptr_size: usize = mem::size_of::<*mut c_void>(); + + /* Check that alignment is: + * a) a multiple of sizeof(void *) + * b) a power-of-two multiple of sizeof(void *). Integer division as + * below gives the correct result once a) is ensured. */ + if alignment % void_ptr_size == 0 && (alignment / void_ptr_size).is_power_of_two() { + let ptr = platform::alloc_align(size, alignment); + if !ptr.is_null() { + *memptr = ptr; + 0 + } else { + ENOMEM + } + } else { + EINVAL + } +} + // #[no_mangle] pub extern "C" fn ptsname(fildes: c_int) -> *mut c_char { unimplemented!(); diff --git a/tests/stdlib/alloc.c b/tests/stdlib/alloc.c index 4089262fad5c88bd62c37babde91a978bca2bcce..c2353fdefa57908b41879c1a52fc1e633f1dad09 100644 --- a/tests/stdlib/alloc.c +++ b/tests/stdlib/alloc.c @@ -12,10 +12,13 @@ int main(void) { size_t sample_realloc_size = sample_alloc_size + 1; /* ensure values are mapped to variables */ + size_t zero = 0; size_t max_size = SIZE_MAX; size_t aligned_alloc_alignment = 128; size_t aligned_alloc_goodsize = 256; size_t aligned_alloc_badsize = 257; + size_t nonpow2_mul_voidptr_size = 3*sizeof(void *); + size_t pow2_mul_voidptr_size = 4*sizeof(void *); int i; @@ -139,4 +142,74 @@ int main(void) { printf("valloc (SIZE_MAX) : %p, errno: %d = %s\n", ptr_valloc_maxsize, valloc_maxsize_errno, strerror(valloc_maxsize_errno)); + + errno = 0; + void * ptr_posix_memalign = NULL; + int posix_memalign_return = posix_memalign(&ptr_posix_memalign, pow2_mul_voidptr_size, sample_alloc_size); + int posix_memalign_errno = errno; + printf("posix_memalign:\n"); + printf(" %p, return value: %d = %s,\n", + ptr_posix_memalign, + posix_memalign_return, strerror(posix_memalign_return)); + /* strerror() can only be called once in a printf call for correct + * results */ + printf(" errno: %d = %s\n", + posix_memalign_errno, + strerror(posix_memalign_errno)); + + errno = 0; + void * ptr_posix_memalign_align0 = NULL; + int posix_memalign_align0_return = posix_memalign(&ptr_posix_memalign_align0, zero, sample_alloc_size); + int posix_memalign_align0_errno = errno; + printf("posix_memalign (alignment 0):\n"); + printf(" %p, return value: %d = %s,\n", + ptr_posix_memalign_align0, + posix_memalign_align0_return, + strerror(posix_memalign_align0_return)); + + printf(" errno: %d = %s\n", + posix_memalign_align0_errno, + strerror(posix_memalign_align0_errno)); + + errno = 0; + void * ptr_posix_memalign_nonpow2mul = NULL; + int posix_memalign_nonpow2mul_return = posix_memalign(&ptr_posix_memalign_nonpow2mul, nonpow2_mul_voidptr_size, sample_alloc_size); + int posix_memalign_nonpow2mul_errno = errno; + printf("posix_memalign (non-power-of-two multiple of sizeof(void *)):\n"); + printf(" %p, return value: %d = %s,\n", + ptr_posix_memalign_nonpow2mul, + posix_memalign_nonpow2mul_return, + strerror(posix_memalign_nonpow2mul_return)); + + printf(" errno: %d = %s\n", + posix_memalign_nonpow2mul_errno, + strerror(posix_memalign_nonpow2mul_errno)); + + errno = 0; + void * ptr_posix_memalign_size0 = NULL; + int posix_memalign_size0_return = posix_memalign(&ptr_posix_memalign_size0, pow2_mul_voidptr_size, zero); + int posix_memalign_size0_errno = errno; + printf("posix_memalign (size 0):\n"); + printf(" %p, return value: %d = %s,\n", + ptr_posix_memalign_size0, + posix_memalign_size0_return, + strerror(posix_memalign_size0_return)); + + printf(" errno: %d = %s\n", + posix_memalign_size0_errno, + strerror(posix_memalign_size0_errno)); + + errno = 0; + void * ptr_posix_memalign_maxsize = NULL; + int posix_memalign_maxsize_return = posix_memalign(&ptr_posix_memalign_maxsize, pow2_mul_voidptr_size, max_size); + int posix_memalign_maxsize_errno = errno; + printf("posix_memalign (SIZE_MAX):\n"); + printf(" %p, return value: %d = %s,\n", + ptr_posix_memalign_maxsize, + posix_memalign_maxsize_return, + strerror(posix_memalign_maxsize_return)); + + printf(" errno: %d = %s\n", + posix_memalign_maxsize_errno, + strerror(posix_memalign_maxsize_errno)); }