Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 27 additions & 13 deletions include/rbs/util/rbs_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,33 @@

#include <stddef.h>

#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 <stdalign.h>
#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;
Expand All @@ -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
2 changes: 1 addition & 1 deletion src/location.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
31 changes: 26 additions & 5 deletions src/util/rbs_allocator.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,38 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#endif

#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun)
#define MAP_ANONYMOUS MAP_ANON
#include <fcntl.h>
#endif

struct rbs_allocator {
uintptr_t heap_ptr;
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;
Expand All @@ -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;
Expand Down