libmemalloc
v4.0.00
Modern Memory Allocator
|
Core memory management components for libmemalloc. More...
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include "libmemalloc.h"
#include "logs.h"
Macros | |
#define | _GNU_SOURCE |
Enable GNU extensions on POSIX systems. | |
#define | LOG_LEVEL LOG_LEVEL_NONE |
Logging verbosity threshold for this module. | |
#define | __UNUSED |
#define | __GC_HOT |
Marks garbage-collector functions as “hot” (performance critical). | |
#define | __GC_COLD |
Marks garbage-collector functions as “cold” (infrequently used). | |
#define | DEFAULT_NUM_BINS (uint8_t)(10U) |
Default number of size classes (bins) for free lists. | |
#define | CACHE_LINE_SIZE (uint8_t)(64U) |
Size of the CPU cache line in bytes. | |
#define | BYTES_PER_CLASS (uint8_t)(128U) |
Fixed byte allocation per classification unit. | |
#define | MMAP_THRESHOLD (size_t)(128U * 1024U) |
Threshold size for using mmap-based allocation. | |
#define | MIN_BLOCK_SIZE (size_t)(sizeof(block_header_t) + ARCH_ALIGNMENT) |
Defines the minimum memory block size. | |
#define | NR_OBJS (uint16_t)(1000U) |
Number of iterations used to scale GC sleep duration. | |
#define | LIKELY(x) (__builtin_expect(!!(x), 1)) |
Compiler hint for likely branch prediction. | |
#define | UNLIKELY(x) (__builtin_expect(!!(x), 0)) |
Compiler hint for unlikely branch prediction. | |
Typedefs | |
typedef int(* | find_fn_t) (mem_allocator_t *const, const size_t, block_header_t **) |
Type for functions that locate a suitable free block. | |
Functions | |
void * | MEM_sbrk (const intptr_t increment) |
Invokes sbrk-like behavior by moving the program break. | |
static int | MEM_getSizeClass (mem_allocator_t *const allocator, const size_t size) |
Calculates the size class index for a requested memory size. | |
static int | MEM_validateBlock (mem_allocator_t *const allocator, block_header_t *const block) |
Validates the integrity and boundaries of a memory block. | |
static int | MEM_insertFreeBlock (mem_allocator_t *const allocator, block_header_t *const block) |
Inserts a block into the appropriate free list based on its size. | |
static int | MEM_removeFreeBlock (mem_allocator_t *const allocator, block_header_t *const block) |
Removes a block from its free list. | |
static int | MEM_findFirstFit (mem_allocator_t *const allocator, const size_t size, block_header_t **fit_block) |
Searches for the first suitable free memory block in size‐class lists. | |
static int | MEM_findNextFit (mem_allocator_t *const allocator, const size_t size, block_header_t **fit_block) |
Searches for the next suitable free memory block using the NEXT_FIT strategy starting from the last allocated position. | |
static int | MEM_findBestFit (mem_allocator_t *const allocator, const size_t size, block_header_t **best_fit) |
Searches for the smallest suitable free memory block in size‐class lists (BEST_FIT). | |
static int | MEM_splitBlock (mem_allocator_t *const allocator, block_header_t *const block, const size_t req_size) |
Splits a memory block into allocated and free portions. | |
static int | MEM_mergeBlocks (mem_allocator_t *const allocator, block_header_t *block) |
Merges adjacent free memory blocks. | |
static void * | MEM_growUserHeap (mem_allocator_t *const allocator, const intptr_t inc) |
Expands the user heap by a specified increment. | |
static int * | MEM_mapAlloc (mem_allocator_t *const allocator, const size_t total_size) |
Allocates a page-aligned memory region via mmap and registers it in the allocator’s mmap list for later freeing. | |
static int | MEM_mapFree (mem_allocator_t *const allocator, void *const addr) |
Unmaps a previously mapped memory region and removes its metadata entry from the allocator’s mmap list. | |
static void * | MEM_allocatorMalloc (mem_allocator_t *const allocator, const size_t size, const char *const file, const int line, const char *const var_name, const allocation_strategy_t strategy) __LIBMEMALLOC_MALLOC |
Allocates memory using the specified strategy. | |
static void * | MEM_allocatorRealloc (mem_allocator_t *const allocator, void *const ptr, const size_t new_size, const char *const file, const int line, const char *const var_name, const allocation_strategy_t strategy) __LIBMEMALLOC_REALLOC |
Reallocates memory with safety checks. | |
static void * | MEM_allocatorCalloc (mem_allocator_t *const allocator, const size_t size, const char *const file, const int line, const char *const var_name, const allocation_strategy_t strategy) __LIBMEMALLOC_MALLOC |
Allocates and zero‐initializes memory. | |
static int | MEM_allocatorFree (mem_allocator_t *const allocator, void *const ptr, const char *const file, const int line, const char *const var_name) |
Releases allocated memory back to the heap. | |
static bool | MEM_stackGrowsDown (void) |
Determine at runtime whether the stack grows downward. | |
static int | MEM_stackBounds (const pthread_t id, mem_allocator_t *const allocator) |
Query and record the bounding addresses of a thread’s stack. | |
static void * | MEM_gcThreadFunc (void *arg) |
Dedicated thread loop driving mark-and-sweep iterations. | |
static int | MEM_setInitialMarks (mem_allocator_t *const allocator) |
Reset “marked” flags across all allocated regions. | |
static int | MEM_gcMark (mem_allocator_t *const allocator) |
Mark all live blocks reachable from the stack. | |
static int | MEM_gcSweep (mem_allocator_t *const allocator) |
Reclaim any unmarked blocks from heap and mmap regions. | |
static int | MEM_runGc (mem_allocator_t *const allocator) |
Start or signal the GC thread to perform a collection cycle. | |
static int | MEM_stopGc (mem_allocator_t *const allocator) |
Stop the GC thread and perform a final collection. | |
void * | MEM_memset (void *const source, const int value, const size_t size) |
Fills a memory block with a specified byte value using optimized operations. | |
void * | MEM_memcpy (void *const dest, const void *src, const size_t size) |
Copies a memory block between buffers using optimized operations. | |
int | MEM_allocatorInit (mem_allocator_t *const allocator) |
Initializes the memory allocator and its internal structures. | |
void * | MEM_allocMallocFirstFit (mem_allocator_t *const allocator, const size_t size, const char *const var) |
Allocates memory using the FIRST_FIT strategy. | |
void * | MEM_allocMallocBestFit (mem_allocator_t *const allocator, const size_t size, const char *const var) |
Allocates memory using the BEST_FIT strategy. | |
void * | MEM_allocMallocNextFit (mem_allocator_t *const allocator, const size_t size, const char *const var) |
Allocates memory using the NEXT_FIT strategy. | |
void * | MEM_allocMalloc (mem_allocator_t *const allocator, const size_t size, const char *const var, const allocation_strategy_t strategy) |
Allocates memory using the specified strategy. | |
void * | MEM_allocCalloc (mem_allocator_t *const allocator, const size_t size, const char *const var, const allocation_strategy_t strategy) |
Allocates and zero‐initializes memory using the specified strategy. | |
void * | MEM_allocRealloc (mem_allocator_t *const allocator, void *const ptr, const size_t new_size, const char *const var, const allocation_strategy_t strategy) |
Reallocates memory with safety checks using the specified strategy. | |
int | MEM_allocFree (mem_allocator_t *const allocator, void *const ptr, const char *const var) |
Releases allocated memory back to the heap. | |
int | MEM_enableGc (mem_allocator_t *const allocator) |
Start or signal the garbage collector thread. | |
int | MEM_disableGc (mem_allocator_t *const allocator) |
Stop the garbage collector thread and perform a final collection. | |
Core memory management components for libmemalloc.
Implements memory allocator with advanced features:
#define __GC_COLD |
Marks garbage-collector functions as “cold” (infrequently used).
When supported by the compiler (GCC/Clang), expands to attribute((cold)), informing the optimizer that the annotated function is unlikely to execute frequently and may be placed out-of-line to reduce code size in hot paths. Otherwise, expands to nothing.
#define __GC_HOT |
Marks garbage-collector functions as “hot” (performance critical).
When supported by the compiler (GCC/Clang), expands to attribute((hot)), informing the optimizer that the annotated function is on a performance-critical path and should be optimized accordingly. Otherwise, expands to nothing.
#define __UNUSED |
#define _GNU_SOURCE |
Enable GNU extensions on POSIX systems.
P R I V A T E P R E - I N C L U D E D E F I N E S
Defining _GNU_SOURCE before including any headers activates GNU-specific library features and extensions in glibc and other GNU-compatible C libraries. This enables additional APIs beyond the standard C/POSIX specifications, such as nonstandard functions, constants, and structures.
#define BYTES_PER_CLASS (uint8_t)(128U) |
Fixed byte allocation per classification unit.
Defines the number of bytes assigned to each classification category. Ensures memory alignment and efficient block processing in data structures.
#define CACHE_LINE_SIZE (uint8_t)(64U) |
Size of the CPU cache line in bytes.
This constant defines the cache-line size used for prefetching and alignment optimizations, ensuring memory accesses align to hardware cache boundaries for maximum performance and correctness on platforms with strict alignment requirements.
#define DEFAULT_NUM_BINS (uint8_t)(10U) |
Default number of size classes (bins) for free lists.
Defines how many size categories (bins) the allocator will maintain for managing free memory blocks. This value affects allocation speed and fragmentation behavior.
#define LIKELY | ( | x | ) | (__builtin_expect(!!(x), 1)) |
Compiler hint for likely branch prediction.
[in] | x | Condition that is likely to be true. |
Helps the compiler optimize branch prediction by indicating the condition is expected to be true.
#define LOG_LEVEL LOG_LEVEL_NONE |
Logging verbosity threshold for this module.
Sets the minimum severity of log messages that will be compiled into this translation unit. Only log calls at or below the specified level are enabled:
#define MIN_BLOCK_SIZE (size_t)(sizeof(block_header_t) + ARCH_ALIGNMENT) |
Defines the minimum memory block size.
Ensures each memory block is large enough to hold a block header and alignment padding.
#define MMAP_THRESHOLD (size_t)(128U * 1024U) |
Threshold size for using mmap-based allocation.
When a requested allocation size meets or exceeds this value (128 KiB), the allocator will switch from using the heap (brk/sbrk) to using mmap for more efficient large-block handling and to reduce heap fragmentation.
#define NR_OBJS (uint16_t)(1000U) |
Number of iterations used to scale GC sleep duration.
Specifies the multiplier applied to the base GC interval (in milliseconds) to compute the actual sleep time between successive garbage-collection cycles: sleep_time = gc_interval_ms * NR_OBJS
#define UNLIKELY | ( | x | ) | (__builtin_expect(!!(x), 0)) |
Compiler hint for unlikely branch prediction.
[in] | x | Condition that is unlikely to be true. |
Helps the compiler optimize branch prediction by indicating the condition is expected to be false.
find_fn_t |
Type for functions that locate a suitable free block.
[in] | allocator | Memory allocator context in which to search. |
[in] | size | Total size requested (including header and canary). |
[out] | block | Address of pointer to store the found block header. |
|
static |
Allocates and zero‐initializes memory.
This function behaves like calloc(), allocating at least size
bytes of zeroed memory via MEM_allocatorMalloc() and then setting all bytes to zero. It records debugging metadata (source file, line, variable name) and uses the given strategy
for allocation.
[in] | allocator | Pointer to the mem_allocator_t context. |
[in] | size | Number of bytes to allocate. |
[in] | file | Source file name for debugging metadata. |
[in] | line | Source line number for debugging metadata. |
[in] | var_name | Variable name for tracking. |
[in] | strategy | Allocation strategy to use. |
ptr | Valid pointer to size bytes of zeroed memory. |
-EINVAL | allocator is NULL or size is zero. |
-ENOMEM | Out of memory: allocation failed. |
-EIO | I/O error for large mmap‐based allocations. |
|
static |
Releases allocated memory back to the heap.
This function frees a pointer previously returned by MEM_allocatorMalloc(). It supports both heap‐based and mmap‐based allocations:
[in] | allocator | Memory allocator context. |
[in] | ptr | Pointer to memory to free. |
[in] | file | Source file name for debugging metadata. |
[in] | line | Source line number for debugging metadata. |
[in] | var_name | Variable name for tracking. |
EXIT_SUCCESS | Memory freed (and heap possibly shrunk) successfully. |
-EINVAL | allocator or ptr is NULL, ptr not found in allocator , or double free detected. |
-ENOMEM | munmap() failed when freeing an mmap region. |
-EFAULT | Block lies outside heap and mmap regions. |
-EPROTO | Header canary mismatch (block corrupted). |
-EOVERFLOW | Data canary mismatch (buffer overrun detected). |
-EFBIG | Block size extends past heap end. |
rer<0 | Errors returned by MEM_validateBlock(), MEM_removeFreeBlock(), MEM_mergeBlocks(), or MEM_insertFreeBlock(). |
|
static |
Allocates memory using the specified strategy.
This function attempts to allocate at least size
bytes of user data by choosing between heap‐based allocation (via free‐lists and optional heap growth) or mmap (for large requests > MMAP_THRESHOLD). It uses the given strategy
(FIRST_FIT, NEXT_FIT, BEST_FIT) to locate a free block, grows the heap if necessary, splits a larger block to fit exactly, and records debugging metadata (source file, line, variable name). For mmap allocations it rounds up to page size and tracks the region in the allocator.
[in] | allocator | Memory allocator context. |
[in] | size | Number of bytes requested. |
[in] | file | Source file name for debugging metadata. |
[in] | line | Source line number for debugging metadata. |
[in] | var_name | Variable name for tracking. |
[in] | strategy | Allocation strategy. |
ptr | Valid user pointer on success. |
-EINVAL | allocator is NULL or size is zero. |
-ENOMEM | Out of memory: heap grow failed, no free block found, or internal metadata allocation (e.g. mmap_t node) failed. |
-EIO | mmap() I/O error for large allocations. |
|
static |
Reallocates memory with safety checks.
This function resizes an existing allocation to new_size
bytes:
ptr
is NULL, behaves like malloc().strategy
, copies the lesser of old and new sizes, frees the old block, and returns the new pointer.[in] | allocator | Memory allocator context. |
[in] | ptr | Pointer to the block to resize, or NULL to allocate. |
[in] | new_size | New requested size in bytes. |
[in] | file | Source file name for debugging metadata. |
[in] | line | Source line number for debugging metadata. |
[in] | var_name | Variable name for tracking. |
[in] | strategy | Allocation strategy to use. |
ptr
) on success; an error-encoded pointer (via PTR_ERR()) on failure.ptr | Valid pointer to a block of at least new_size bytes. |
-EINVAL | allocator is NULL, new_size is zero. |
-ENOMEM | Out of memory (allocation or free failure). |
-EIO | I/O error for large mmap-based allocations. |
|
static |
Searches for the smallest suitable free memory block in size‐class lists (BEST_FIT).
This function computes the starting size class for the requested size
via MEM_getSizeClass(), then scans each free‐list from that class upward. It validates each candidate with MEM_validateBlock() and tracks the smallest free block that is large enough. Once a block in any class is chosen, the search stops.
[in] | allocator | Pointer to the allocator context. |
[in] | size | Requested allocation size in bytes. |
[out] | best_fit | On success, set to the pointer of the free block. |
EXIT_SUCCESS | Suitable block found successfully. |
-EINVAL | allocator or best_fit is NULL. |
-ENOMEM | Size calculation failed or no suitable block found. |
|
static |
Searches for the first suitable free memory block in size‐class lists.
This function computes the starting size class for the requested size
via MEM_getSizeClass(), then scans each free‐list from that class upward. For each candidate block, it calls MEM_validateBlock() to ensure integrity, and returns the first block that is marked free and large enough. The found block pointer is stored in fit_block
.
[in] | allocator | Pointer to the allocator context. |
[in] | siz | Requested allocation size in bytes. |
[out] | fit_block | On success, set to the pointer of a suitable free block. |
EXIT_SUCCESS | Suitable block found successfully. |
-EINVAL | allocator or fit_block are NULL; |
-ENOMEM | Siz calculation failed or no suitable block found. |
|
static |
Searches for the next suitable free memory block using the NEXT_FIT strategy starting from the last allocated position.
This function attempts to find a free block of at least size
bytes by scanning the heap starting at allocator->last_allocated. If last_allocated is NULL, not free, or corrupted, it falls back to First-Fit. It wraps around to the heap start if needed, stopping once it returns to the start.
[in] | allocator | Pointer to the allocator context. |
[in] | size | Requested allocation size in bytes. |
[out] | fit_block | Pointer to store the address of the found block. |
EXIT_SUCCESS | Suitable block found and fit_block set. |
-EINVAL | allocator or fit_block is NULL. |
-ENOMEM | No suitable block found in heap. |
|
static |
Mark all live blocks reachable from the stack.
This function performs the marking phase of garbage collection by:
[in] | allocator | Memory allocator context. |
EXIT_SUCCESS | All reachable blocks marked successfully. |
-EINVAL | allocator is NULL. |
ret<0 | Error code returned by MEM_stackBounds(), MEM_validateBlock(), or other internal calls. |
|
static |
Reclaim any unmarked blocks from heap and mmap regions.
This function performs the “sweep” phase of garbage collection:
[in] | allocator | Memory allocator context. |
EXIT_SUCCESS | All unreachable blocks reclaimed successfully. |
-EINVAL | allocator is NULL. |
ret<0 | Errors returned by MEM_allocatorFree(), munmap(), or internal validation functions. |
|
static |
Dedicated thread loop driving mark-and-sweep iterations.
This function runs as the GC worker thread. It locks gc_lock and waits on gc_cond until either gc_running or gc_exit is set. On wakeup, if gc_exit is true, it breaks and exits the loop; otherwise it unlocks and performs one full GC cycle by calling MEM_gcMark() and MEM_gcSweep(), then sleeps for gc_interval_ms before re-acquiring the lock and waiting again. On exit it ensures gc_lock is released.
[in] | arg | Pointer to the mem_allocator_t context. |
NULL | Clean exit after gc_exit. |
-EINVAL | arg is NULL. |
ret<0 | cond errors, or MEM_gcMark() / MEM_gcSweep() failures. |
|
static |
Calculates the size class index for a requested memory size.
This function determines which size class the given allocation request belongs to by dividing the requested size
by BYTES_PER_CLASS (rounding up). If the computed index exceeds the maximum available class, it will be clamped to the highest class and a warning emitted.
[in] | allocator | Pointer to the allocator context. |
[in] | size | Requested memory size in bytes (must be > 0). |
ret>0 | Valid size class index. |
-EINVAL | allocator is NULL, or size is zero. |
|
static |
Expands the user heap by a specified increment.
This function moves the program break by inc
bytes via MEM_sbrk(), zeroes the newly allocated region, updates the allocator’s heap_end, and initializes a block_header_t at the start of the new region to record its size, mark it as allocated, and set its free flag to false.
[in] | allocator | Pointer to the allocator context. |
[in] | inc | Signed number of bytes to grow (or shrink) the heap. |
(ret>=0) | Previous heap end address (new region start). |
-EINVAL | allocator is NULL. |
-ENOMEM | Heap expansion failed (out of memory). |
|
static |
Inserts a block into the appropriate free list based on its size.
This function computes the size class index for the given block
by calling MEM_getSizeClass(), then pushes the block onto the head of that free list within the allocator. It updates both forward and backward links to maintain the doubly‐linked list of free blocks.
[in] | allocator | Pointer to the allocator context. |
[in] | block | Pointer to the block header to insert. |
EXIT_SUCCESS | block successfully inserted. |
-EINVAL | allocator or block is NULL. |
-ENOMEM | Size class calculation failed (request too large). |
|
static |
Allocates a page-aligned memory region via mmap and registers it in the allocator’s mmap list for later freeing.
This function rounds up total_size
to a multiple of the system page size, invokes mmap() to obtain an anonymous read/write region, then allocates an mmap_t metadata node via MEM_allocatorMalloc() and links it into allocator->mmap_list. It initializes a block_header_t and trailing canary in the mapped region to integrate with the allocator’s debugging and GC.
[in] | allocator | Pointer to the memory allocator context. |
[in] | total_size | Number of bytes requested. |
ret!=MAP_FAILED | Address of the mapped region. |
-EINVAL | allocator is NULL. |
-EIO | mmap() failed. |
-ENOMEM | Allocation of mmap_t metadata failed. |
|
static |
Unmaps a previously mapped memory region and removes its metadata entry from the allocator’s mmap list.
This function searches the allocator’s mmap_list for an entry matching addr
, calls munmap() to unmap the region, unlinks the corresponding mmap_t metadata node, and frees it via MEM_allocatorFree(). Errors during munmap are returned; if metadata freeing fails, an error is logged but success is returned.
[in] | allocator | Memory allocator context. |
[in] | addr | Address of the memory region to unmap. |
EXIT_SUCCESS | Region unmapped and metadata entry removed. |
-EINVAL | allocator / addr is NULL, or not found in list. |
-ENOMEM | munmap() failed to unmap the region. |
|
static |
Merges adjacent free memory blocks.
This function removes the specified block
from its free list, then checks its immediate neighbor blocks in memory. If the next block is free and valid, it unlinks and combines it with block
, updating size, links, and trailing canary. It then checks the previous block; if it is also free and valid, it merges block
into the previous block. Finally, the resulting merged block is reinserted into the appropriate free list.
[in] | allocator | Pointer to the allocator context. |
[in] | block | Pointer to the free block header to merge. |
EXIT_SUCCESS | Blocks merged (or single block reinserted) successfully. |
-EINVAL | allocator or block is NULL. |
ret<0 | Returned by MEM_removeFreeBlock(), MEM_validateBlock(), MEM_insertFreeBlock(), or munmap() in inner calls indicating the specific failure. |
|
static |
Removes a block from its free list.
This function unlinks the specified block
from the free list corresponding to its size class within the allocator. It computes the size‐class index via MEM_getSizeClass(), validates parameters, then adjusts the neighboring blocks’ fl_next and fl_prev pointers (or the list head) to remove block
. The block’s own fl_next and fl_prev are then cleared.
[in] | allocator | Memory allocator context. |
[in] | block | Block header to remove. |
EXIT_SUCCESS | Block removed successfully. |
-EINVAL | allocator or block is NULL. |
-ENOMEM | Size‐class calculation failed. |
|
static |
Start or signal the GC thread to perform a collection cycle.
This function saves the caller’s thread ID as main_thread, locks gc_lock, and if the GC thread has not been started, sets gc_running and gc_exit flags and spawns MEM_gcThreadFunc(); otherwise it sets gc_running and signals gc_cond to wake the existing thread. Finally it unlocks gc_lock.
[in] | allocator | Pointer to the mem_allocator_t context. |
EXIT_SUCCESS | GC thread started or signaled successfully. |
-EINVAL | allocator is NULL. |
ret<0 | Error code returned by pthread_create(). |
void * MEM_sbrk | ( | const intptr_t | increment | ) |
Invokes sbrk-like behavior by moving the program break.
This function reads the current program break, attempts to move it by the signed offset increment
via sbrk(), and returns the original break on success. If any call to sbrk() or reading the break fails, it encodes the negative errno into a pointer via PTR_ERR.
[in] | increment | Signed offset in bytes to move the program break: positive to grow, negative to shrink. |
ret>-1 | Previous break on success. |
-ENOMEM | Failed to read or adjust the break. |
|
static |
Reset “marked” flags across all allocated regions.
This function prepares for a new garbage-collection cycle by clearing the mark flag on every heap block and every mmap’d block payload. It scans the heap from allocator->heap_start + metadata_size up to allocator->heap_end, resetting each valid block’s marked flag (and skipping malformed blocks to avoid infinite loops). It then iterates allocator->mmap_list, clearing the mark on each payload block while preserving the metadata header’s mark so the allocator’s own bookkeeping regions are never freed.
[in] | allocator | Memory allocator context. |
EXIT_SUCCESS | All marks cleared and metadata marks preserved. |
-EINVAL | allocator is NULL. |
|
static |
Splits a memory block into allocated and free portions.
This function takes an existing free block
and a requested allocation size req_size
, and divides the block into:
[in] | allocator | Pointer to the mem_allocator_t context. |
[in] | block | Pointer to the block_header_t to split. |
[in] | req_size | Requested allocation size in bytes. |
EXIT_SUCCESS | Block split (or fully allocated) successfully. |
-EINVAL | nvalid allocator or block pointer. |
-EPROTO | Header canary mismatch (block corrupted). |
-EOVERFLOW | Data canary mismatch (buffer overflow detected). |
-EFBIG | Block’s size would extend past heap end. |
-EFAULT | Block lies outside heap or mmap regions. |
-ENOMEM | Failed to insert the new free remainder block. |
|
static |
Query and record the bounding addresses of a thread’s stack.
This function retrieves the stack base address, total stack size, and guard size for the specified thread, then computes the usable stack bounds within the allocator object, taking into account whether the stack grows up or down in memory.
[in] | id | The thread identifier whose stack to inspect. |
[in] | allocator | Pointer to the allocator object where stack_bottom and stack_top will be stored. |
EXIT_SUCCESS | Stack bounds successfully recorded. |
-EINVAL | allocator was NULL. |
ret>0 | Error code from one of the pthread or system calls |
|
static |
Determine at runtime whether the stack grows downward.
This function places two volatile local variables on the stack and compares their addresses to infer the growth direction:
true | Stack grows downward (newer frames at lower addresses) |
false | Stack grows upward (newer frames at higher addresses) |
|
static |
Stop the GC thread and perform a final collection.
This function clears gc_running and sets gc_exit, signals gc_cond to wake the GC thread if it’s running, then joins it. After the thread exits, it runs one final MEM_gcMark() + MEM_gcSweep() on the caller thread to reclaim any remaining garbage, then clears gc_thread_started.
[in] | allocator | Pointer to the mem_allocator_t context. |
EXIT_SUCCESS | GC thread stopped and final collection done. |
-EINVAL | allocator is NULL. |
ret<0 | Error code from pthread MEM_gcMark(), or MEM_gcSweep(). |
|
static |
Validates the integrity and boundaries of a memory block.
This function ensures that the specified block
lies within the allocator’s heap or one of its mmap regions, that its header canary matches the expected magic value to detect metadata corruption, that its data canary is intact to catch buffer overruns, and that the block’s size does not extend past the heap’s end. On any failure, an appropriate negative errno is returned.
[in] | allocator | Pointer to the allocator context. |
[in] | block | Pointer to the block header to validate. |
EXIT_SUCCESS | block is valid. |
-EINVAL | allocator or block pointer is NULL. |
-EFAULT | block lies outside heap and mmap regions. |
-EPROTO | block canary does not match expected value. |
-EFBIG | block size causes it to extend past heap end. |
-EOVERFLOW | block canary indicates buffer overflow. |