diff --git a/include/rbs/util/rbs_allocator.h b/include/rbs/util/rbs_allocator.h index b1a1904b20..c3356cfadd 100644 --- a/include/rbs/util/rbs_allocator.h +++ b/include/rbs/util/rbs_allocator.h @@ -3,19 +3,33 @@ #include -#ifndef alignof -#if defined(__GNUC__) || defined(__clang__) -#define alignof(type) __alignof__(type) +/* Include stdalign.h for C11 and later for alignof support */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#include +#endif + +/* + * Define a portable alignment macro that works across all supported environments + */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +/* C11 or later - use _Alignof directly (always available in C11+) */ +#define rbs_alignof(type) _Alignof(type) +#elif defined(__cplusplus) && __cplusplus >= 201103L +/* C++11 or later has alignof keyword */ +#define rbs_alignof(type) alignof(type) +#elif defined(__GNUC__) || defined(__clang__) +/* GCC and Clang provide __alignof__ */ +#define rbs_alignof(type) __alignof__(type) #elif defined(_MSC_VER) -#define alignof(type) __alignof(type) +/* MSVC provides __alignof */ +#define rbs_alignof(type) __alignof(type) #else -// Fallback using offset trick -#define alignof(type) offsetof( \ - struct { char c; type member; }, \ - member \ +/* Fallback using offset trick for other compilers */ +#define rbs_alignof(type) offsetof( \ + struct { char c; type member; }, \ + member \ ) #endif -#endif struct rbs_allocator; typedef struct rbs_allocator rbs_allocator_t; @@ -29,13 +43,13 @@ void *rbs_allocator_calloc_impl(rbs_allocator_t *, size_t count, size_t size, si void *rbs_allocator_realloc_impl(rbs_allocator_t *, void *ptr, size_t old_size, size_t new_size, size_t alignment); // Use this when allocating memory for a single instance of a type. -#define rbs_allocator_alloc(allocator, type) ((type *) rbs_allocator_malloc_impl((allocator), sizeof(type), alignof(type))) +#define rbs_allocator_alloc(allocator, type) ((type *) rbs_allocator_malloc_impl((allocator), sizeof(type), rbs_alignof(type))) // Use this when allocating memory that will be immediately written to in full. // Such as allocating strings -#define rbs_allocator_alloc_many(allocator, count, type) ((type *) rbs_allocator_malloc_many_impl((allocator), (count), sizeof(type), alignof(type))) +#define rbs_allocator_alloc_many(allocator, count, type) ((type *) rbs_allocator_malloc_many_impl((allocator), (count), sizeof(type), rbs_alignof(type))) // Use this when allocating memory that will NOT be immediately written to in full. // Such as allocating buffers -#define rbs_allocator_calloc(allocator, count, type) ((type *) rbs_allocator_calloc_impl((allocator), (count), sizeof(type), alignof(type))) -#define rbs_allocator_realloc(allocator, ptr, old_size, new_size, type) ((type *) rbs_allocator_realloc_impl((allocator), (ptr), (old_size), (new_size), alignof(type))) +#define rbs_allocator_calloc(allocator, count, type) ((type *) rbs_allocator_calloc_impl((allocator), (count), sizeof(type), rbs_alignof(type))) +#define rbs_allocator_realloc(allocator, ptr, old_size, new_size, type) ((type *) rbs_allocator_realloc_impl((allocator), (ptr), (old_size), (new_size), rbs_alignof(type))) #endif diff --git a/src/location.c b/src/location.c index d3d60b4f23..ad75a4ad0d 100644 --- a/src/location.c +++ b/src/location.c @@ -8,7 +8,7 @@ void rbs_loc_alloc_children(rbs_allocator_t *allocator, rbs_location_t *loc, size_t capacity) { rbs_assert(capacity <= sizeof(rbs_loc_entry_bitmap) * 8, "Capacity %zu is too large. Max is %zu", capacity, sizeof(rbs_loc_entry_bitmap) * 8); - loc->children = rbs_allocator_malloc_impl(allocator, RBS_LOC_CHILDREN_SIZE(capacity), alignof(rbs_loc_children)); + loc->children = rbs_allocator_malloc_impl(allocator, RBS_LOC_CHILDREN_SIZE(capacity), rbs_alignof(rbs_loc_children)); loc->children->len = 0; loc->children->required_p = 0; diff --git a/src/util/rbs_allocator.c b/src/util/rbs_allocator.c index 1bacc6164e..0d53031b9b 100644 --- a/src/util/rbs_allocator.c +++ b/src/util/rbs_allocator.c @@ -20,10 +20,7 @@ #include #include #include -#endif - -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun) -#define MAP_ANONYMOUS MAP_ANON +#include #endif struct rbs_allocator { @@ -31,6 +28,30 @@ struct rbs_allocator { uintptr_t size; }; +static void *portable_mmap_anon(size_t size) { +#ifdef _WIN32 + /* Windows doesn't use this function - VirtualAlloc is used instead */ + return NULL; +#else + void *ptr; + +#if defined(MAP_ANONYMOUS) + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +#elif defined(MAP_ANON) + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); +#else + /* Fallback to /dev/zero for systems without anonymous mapping */ + int fd = open("/dev/zero", O_RDWR); + rbs_assert(fd != -1, "open('/dev/zero') failed"); + + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + close(fd); /* Can close fd after mapping */ +#endif + + return ptr; +#endif +} + static size_t get_system_page_size(void) { #ifdef _WIN32 SYSTEM_INFO si; @@ -48,7 +69,7 @@ static void *map_memory(size_t size) { LPVOID result = VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); rbs_assert(result != NULL, "VirtualAlloc failed"); #else - void *result = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + void *result = portable_mmap_anon(size); rbs_assert(result != MAP_FAILED, "mmap failed"); #endif return result;