From b3f36faf872fba449d3e76451ff7fd149edf77ac Mon Sep 17 00:00:00 2001 From: Peter Limkilde Svendsen Date: Tue, 11 Feb 2025 21:13:05 +0100 Subject: [PATCH] Add pvalloc() --- include/{ => bits}/malloc.h | 4 +- src/header/malloc/cbindgen.toml | 10 +++++ src/header/malloc/mod.rs | 39 ++++++++++++++++++ src/header/mod.rs | 1 + .../expected/bins_dynamic/stdlib/alloc.stdout | 4 ++ .../expected/bins_static/stdlib/alloc.stdout | 4 ++ tests/stdlib/alloc.c | 40 ++++++++++++++++++- 7 files changed, 99 insertions(+), 3 deletions(-) rename include/{ => bits}/malloc.h (90%) create mode 100644 src/header/malloc/cbindgen.toml create mode 100644 src/header/malloc/mod.rs diff --git a/include/malloc.h b/include/bits/malloc.h similarity index 90% rename from include/malloc.h rename to include/bits/malloc.h index 9826495495..ba2ec6b820 100644 --- a/include/malloc.h +++ b/include/bits/malloc.h @@ -1,5 +1,5 @@ -#ifndef _MALLOC_H -#define _MALLOC_H +#ifndef _BITS_MALLOC_H +#define _BITS_MALLOC_H #include diff --git a/src/header/malloc/cbindgen.toml b/src/header/malloc/cbindgen.toml new file mode 100644 index 0000000000..6e2a0c9bf3 --- /dev/null +++ b/src/header/malloc/cbindgen.toml @@ -0,0 +1,10 @@ +sys_includes = ["features.h", "stddef.h"] +include_guard = "_RELIBC_MALLOC_H" +trailer = "#include " +language = "C" +style = "Type" +no_includes = true +cpp_compat = true + +[enum] +prefix_with_name = true diff --git a/src/header/malloc/mod.rs b/src/header/malloc/mod.rs new file mode 100644 index 0000000000..0a45be8b4e --- /dev/null +++ b/src/header/malloc/mod.rs @@ -0,0 +1,39 @@ +//! `malloc.h` implementation. +//! +//! Non-POSIX, see . + +use crate::{ + header::errno::*, + platform::{self, types::*, Pal, Sys, ERRNO}, +}; +use core::ptr; + +/// See . +#[deprecated] +#[no_mangle] +pub unsafe extern "C" fn pvalloc(size: size_t) -> *mut c_void { + let page_size = Sys::getpagesize(); + // Find the smallest multiple of the page size in which the requested size + // will fit. The result of the division will always be less than or equal + // to size_t::MAX - 1, and the num_pages calculation will therefore never + // overflow. + let num_pages = if size != 0 { + (size - 1) / page_size + 1 + } else { + 0 + }; + + match num_pages.checked_mul(page_size) { + Some(alloc_size) => { + let ptr = platform::alloc_align(alloc_size, page_size); + if ptr.is_null() { + platform::ERRNO.set(ENOMEM); + } + ptr + } + None => { + platform::ERRNO.set(ENOMEM); + ptr::null_mut() + } + } +} diff --git a/src/header/mod.rs b/src/header/mod.rs index bfd85d5eea..79944ef285 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -35,6 +35,7 @@ pub mod langinfo; pub mod libgen; pub mod limits; pub mod locale; +pub mod malloc; // math.h implemented in C pub mod monetary; // TODO: mqueue.h diff --git a/tests/expected/bins_dynamic/stdlib/alloc.stdout b/tests/expected/bins_dynamic/stdlib/alloc.stdout index 02ecd20189..d5bc92dc00 100644 --- a/tests/expected/bins_dynamic/stdlib/alloc.stdout +++ b/tests/expected/bins_dynamic/stdlib/alloc.stdout @@ -24,3 +24,7 @@ posix_memalign (alignment 0): pointer: (nil), error value: 22 = Invalid argument posix_memalign (non-power-of-two multiple of sizeof(void *)): pointer: (nil), error value: 22 = Invalid argument posix_memalign (size 0): (OK) posix_memalign (SIZE_MAX): pointer: (nil), error value: 12 = Out of memory +pvalloc (size 0): (OK) +pvalloc: pointer: (alignment OK), error value: 0 = Success +pvalloc (2 pages): pointer: (alignment OK), error value: 0 = Success +pvalloc (SIZE_MAX): pointer: (nil), error value: 12 = Out of memory diff --git a/tests/expected/bins_static/stdlib/alloc.stdout b/tests/expected/bins_static/stdlib/alloc.stdout index 02ecd20189..d5bc92dc00 100644 --- a/tests/expected/bins_static/stdlib/alloc.stdout +++ b/tests/expected/bins_static/stdlib/alloc.stdout @@ -24,3 +24,7 @@ posix_memalign (alignment 0): pointer: (nil), error value: 22 = Invalid argument posix_memalign (non-power-of-two multiple of sizeof(void *)): pointer: (nil), error value: 22 = Invalid argument posix_memalign (size 0): (OK) posix_memalign (SIZE_MAX): pointer: (nil), error value: 12 = Out of memory +pvalloc (size 0): (OK) +pvalloc: pointer: (alignment OK), error value: 0 = Success +pvalloc (2 pages): pointer: (alignment OK), error value: 0 = Success +pvalloc (SIZE_MAX): pointer: (nil), error value: 12 = Out of memory diff --git a/tests/stdlib/alloc.c b/tests/stdlib/alloc.c index 2342de14d1..2e51c144c6 100644 --- a/tests/stdlib/alloc.c +++ b/tests/stdlib/alloc.c @@ -1,4 +1,4 @@ -#include +#include /* for pvalloc() */ #include #include #include @@ -299,5 +299,43 @@ int main(void) { test_cannot_alloc(ptr_posix_memalign_maxsize, posix_memalign_maxsize_return); free(ptr_posix_memalign_maxsize); + errno = 0; + char * ptr_pvalloc_size0 = (char *)pvalloc(zero_size); + int pvalloc_size0_errno = errno; + printf("pvalloc (size 0): "); + test_size_zero(ptr_pvalloc_size0, page_size, pvalloc_size0_errno); + free(ptr_pvalloc_size0); + + errno = 0; + char * ptr_pvalloc = (char *)pvalloc(sample_alloc_size); + int pvalloc_errno = errno; + printf("pvalloc: "); + test_valid_aligned(ptr_pvalloc, page_size, pvalloc_errno); + /* Check that the alloc size is rounded up to nearest page-size + * multiple */ + for(i = 0; i < page_size; i++) { + ptr_pvalloc[i] = (char)i; + } + free(ptr_pvalloc); + + errno = 0; + char * ptr_pvalloc_multipage = (char *)pvalloc(page_size + 1); + int pvalloc_multipage_errno = errno; + printf("pvalloc (2 pages): "); + test_valid_aligned(ptr_pvalloc_multipage, page_size, pvalloc_multipage_errno); + /* Check that the alloc size is rounded up to nearest page-size + * multiple */ + for(i = 0; i < 2*page_size; i++) { + ptr_pvalloc_multipage[i] = (char)i; + } + free(ptr_pvalloc_multipage); + + errno = 0; + char * ptr_pvalloc_maxsize = (char *)pvalloc(max_size); + int pvalloc_maxsize_errno = errno; + printf("pvalloc (SIZE_MAX): "); + test_cannot_alloc(ptr_pvalloc_maxsize, pvalloc_maxsize_errno); + free(ptr_pvalloc_maxsize); + #pragma GCC diagnostic pop }