Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
default.c File Reference
#include <assert.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include "serene/rt/mm/interface.h"
#include "serene/utils.h"
Include dependency graph for default.c:

Go to the source code of this file.

Macros

#define MM_LOG(FMT, ...)

Functions

static bool is_block_id_free (const srn_mm_t *mm, uint16_t bit)
static void allocated_block_id (srn_mm_t *mm, uint16_t bit)
static void deallocated_block_id (srn_mm_t *mm, uint16_t bit)
static int find_a_free_block_id (const srn_mm_t *mm)
static srn_block_tget_block (const srn_mm_t *mm, srn_block_id_t block_id)
 An abstraction over ID->Block operation.
static void * stdlib_allocator (size_t size, size_t alignment)
 Just a proxy functions to the standard stdlib malloc/free later on if we decided to use mimalloc or something or even our own malloc, we can plug them in like this.
static void stdlib_releaser (void *ptr)
void * srn_mm_malloc (srn_mm_t *mm, size_t size)
 Generic allocations that do not participate in the block based pools.
void * srn_mm_reallocate (srn_mm_t *mm, void *ptr, size_t new_size)
void srn_mm_free (srn_mm_t *mm, void *ptr)
 Release a pointer previously returned by srn_mm_malloc or srn_mm_reallocate.
static size_t block_capacity (const srn_block_t *block)
 Return the size of the payload section of the block.
static size_t block_remaining (const srn_block_t *block)
 Return the number of unused payload bytes left in the block.
static void init_block (srn_mm_t *mm, srn_block_t *block)
static void * alloc_block_internal (srn_mm_t *mm)
 Allocate a block worth of memory using the memory provider.
static void destroy_chain (srn_mm_t *mm, srn_block_id_t root_id)
static void * alloc_in_block (srn_mm_t *mm, srn_block_t *root_block, size_t size, size_t alignment)
 This is the main allocation logic that allocates the space in the given block.
size_t srn_mm_get_os_page_size (void)
 Retutrns the OS page size.
srn_block_tsrn_mm_get_block (srn_mm_t *mm, srn_block_id_t block_id)
 Return the block object associated by the given block_id.
srn_mm_tsrn_mm_init (const srn_configuration_t *config)
 Initialize the memory manager, this function will panic on error.
void srn_mm_shutdown (srn_mm_t *mm)
 Shut down the memory manager and release the resources.
void * srn_mm_allocate_in_block_aligned (srn_mm_t *mm, srn_block_id_t block_id, size_t size, size_t alignment)
 Allocate memory on a block with the given block_id.
void * srn_mm_immortal_allocate_aligned (srn_mm_t *mm, size_t size, size_t alignment)
 Allocate memory on the importal block which will never gets freed.
void srn_unlock_memory_manager (srn_mm_t *mm)
 Unocks the memory manager.
void srn_lock_memory_manager (srn_mm_t *mm)
 Locks the memory manager.
srn_block_id_t srn_mm_allocate_block (srn_mm_t *mm)
 Allocate a new block in the memory manager and return its ID.
void srn_mm_release_block (srn_mm_t *mm, srn_block_id_t id)
 Release the given block id and free the memory for later allocations.

Variables

static srn_memory_provider_t stdlib_provider

Macro Definition Documentation

◆ MM_LOG

#define MM_LOG ( FMT,
... )

Definition at line 38 of file default.c.

Function Documentation

◆ alloc_block_internal()

void * alloc_block_internal ( srn_mm_t * mm)
inlinestatic

Allocate a block worth of memory using the memory provider.

This is an internal function and it will NOT allocate block_id nor track the block via the memory manager by default.

Definition at line 202 of file default.c.

202 {
203 PANIC_IF_NULL(mm);
204 srn_block_t *block =
206 PANIC_IF_NULL(block);
207 init_block(mm, block);
208 MM_TRACEPOINT(mm_block_new, (void *)block, (uint64_t)mm->block_size);
209 return block;
210}
static void init_block(srn_mm_t *mm, srn_block_t *block)
Definition default.c:190
#define MM_TRACEPOINT(...)
Definition interface.h:43
#define DEFAULT_BLOCK_ALIGNMENT
We strictly use 16 bytes alignment for blocks.
Definition interface.h:56
void *(* allocate)(size_t size, size_t alignment)
Definition interface.h:73
size_t block_size
Definition interface.h:125
srn_memory_provider_t * provider
An abstraction over a memory provider like the malloc/free pair.
Definition interface.h:120
#define PANIC_IF_NULL(ptr)
Definition utils.h:66
Here is the call graph for this function:
Here is the caller graph for this function:

◆ alloc_in_block()

void * alloc_in_block ( srn_mm_t * mm,
srn_block_t * root_block,
size_t size,
size_t alignment )
inlinestatic

This is the main allocation logic that allocates the space in the given block.

Other public functions have to use this fuction to operate. The caller must hold the chain's lock for the whole call.

Definition at line 252 of file default.c.

252 {
253 PANIC_IF(
254 alignment == 0 || (alignment & (alignment - 1)) != 0,
255 "'alignment' must be a nonzero power of two"
256 );
257
258 if (size > block_capacity(root_block) || alignment > block_capacity(root_block)) {
259 // Since all the blocks in a block chain have the same size,
260 // if user is asking for an allocation larger than the block size,
261 // there is no way we can find it in this chain, so a larger block
262 // size is required
263 TODO("We need to allocate a larger block");
264 }
265 MM_LOG("Allocating %zu with %zu alignment", size, alignment);
266
267 MM_LOG("Root block: %p", (void *)root_block);
268 srn_block_t *target_block = root_block;
269 MM_LOG("Walking the block chain");
270 for (;;) {
271 MM_LOG("Next block: %p", (void *)target_block);
272
273 // Align the absolute address, not the offset. The payload base is only
274 // guaranteed DEFAULT_BLOCK_ALIGNMENT, so offset arithmetic alone returns
275 // misaligned pointers for larger alignments.
276 uintptr_t base = (uintptr_t)target_block->base;
277 uintptr_t aligned =
278 (base + target_block->offset + (alignment - 1)) & ~((uintptr_t)alignment - 1);
279 size_t aligned_offset = (size_t)(aligned - base);
280 size_t capacity = block_capacity(target_block);
281
282 MM_LOG("Calculated aligned offset 0x%zx", aligned_offset);
283
284 if (aligned_offset + size > capacity) {
285 MM_LOG("We can't allocate in this block");
286 if (target_block->next != nullptr) {
287 // let's try the next block in the chain
288 target_block = target_block->next;
289 continue;
290 }
291 // We need to create a new block for this chain.
292 MM_LOG("We have to allocate a new block");
293
295 target_block->next = b;
296 target_block = b;
297 MM_TRACEPOINT(mm_chain_grow, (void *)root_block, (void *)b);
298 MM_LOG("New block: %p", (void *)target_block);
299 continue;
300 }
301 MM_LOG("We have found enough space");
302
303 void *ptr = (void *)aligned;
304 target_block->offset = aligned_offset + size;
305
306 return ptr;
307 }
308}
static void * alloc_block_internal(srn_mm_t *mm)
Allocate a block worth of memory using the memory provider.
Definition default.c:202
#define MM_LOG(FMT,...)
Definition default.c:38
static size_t block_capacity(const srn_block_t *block)
Return the size of the payload section of the block.
Definition default.c:178
uint8_t base[]
Where the data area starts.
Definition interface.h:92
size_t offset
Offset from the base.
Definition interface.h:88
struct srn_block_t * next
when the block does not have space to allocate a request, we will allocate a new block and point to i...
Definition interface.h:80
#define PANIC_IF(cond, msg)
Definition utils.h:59
#define TODO(msg)
Definition utils.h:54
Here is the call graph for this function:
Here is the caller graph for this function:

◆ allocated_block_id()

void allocated_block_id ( srn_mm_t * mm,
uint16_t bit )
inlinestatic

Definition at line 56 of file default.c.

56 {
57 PANIC_IF(bit >= 256, "Bit position is out of block_bitmap boundaries.");
58
59 // divide by 64, which 64-bit word
60 uint64_t index = bit >> 6U;
61 // remainder, which bit in that word
62 unsigned offset = bit & 63U;
63
64 mm->block_bitmap[index] |= (1ULL << offset);
65}
uint64_t block_bitmap[4]
This is a 256bit bitmap we treat it as a whole.
Definition interface.h:124
Here is the caller graph for this function:

◆ block_capacity()

size_t block_capacity ( const srn_block_t * block)
inlinestatic

Return the size of the payload section of the block.

Definition at line 178 of file default.c.

178 {
179 return block->size - offsetof(srn_block_t, base);
180}
size_t size
This is the TOTAL size of the block, header + payloud.
Definition interface.h:85
Here is the caller graph for this function:

◆ block_remaining()

size_t block_remaining ( const srn_block_t * block)
inlinestatic

Return the number of unused payload bytes left in the block.

Definition at line 186 of file default.c.

186 {
187 return block_capacity(block) - block->offset;
188}
Here is the call graph for this function:

◆ deallocated_block_id()

void deallocated_block_id ( srn_mm_t * mm,
uint16_t bit )
inlinestatic

Definition at line 67 of file default.c.

67 {
68 PANIC_IF(bit >= 256, "Bit position is out of block_bitmap boundaries.");
69
70 uint64_t index = bit >> 6U;
71 unsigned offset = bit & 63U;
72 uint64_t mask = ~(1ULL << offset);
73 mm->block_bitmap[index] &= mask;
74}
Here is the caller graph for this function:

◆ destroy_chain()

void destroy_chain ( srn_mm_t * mm,
srn_block_id_t root_id )
inlinestatic

Definition at line 212 of file default.c.

212 {
214
215 // The liveness check happens under the manager lock, so two racing
216 // releases of the same id cannot both pass it and double free the chain.
217 if (is_block_id_free(mm, root_id)) {
219 return;
220 }
221
222 // Holding the chain lock closes the race against an allocation walking
223 // this chain, the walk either finishes before the free, or starts after
224 // the slot is nulled and panics on the dead id.
225 srn_spinlock_t *chain_lock = &mm->chain_locks[root_id];
226 srn_spinlock_lock(chain_lock);
227
228 srn_block_t *block = get_block(mm, root_id);
229 size_t freed = 0;
230 while (block != nullptr) {
231 srn_block_t *tmp = block;
232 block = tmp->next;
233
234 mm->provider->release(tmp);
235 freed++;
236 }
237
238 mm->blocks[root_id] = nullptr;
239 mm->block_count--;
240 deallocated_block_id(mm, root_id);
241 MM_TRACEPOINT(mm_chain_free, (uint64_t)root_id, (uint64_t)freed);
242 srn_spinlock_unlock(chain_lock);
244}
static srn_block_t * get_block(const srn_mm_t *mm, srn_block_id_t block_id)
An abstraction over ID->Block operation.
Definition default.c:109
static void deallocated_block_id(srn_mm_t *mm, uint16_t bit)
Definition default.c:67
void srn_lock_memory_manager(srn_mm_t *mm)
Locks the memory manager.
Definition default.c:436
void srn_unlock_memory_manager(srn_mm_t *mm)
Unocks the memory manager.
Definition default.c:434
static bool is_block_id_free(const srn_mm_t *mm, uint16_t bit)
Definition default.c:45
void(* release)(void *p)
Definition interface.h:74
srn_block_t * blocks[MAX_NUMBER_OF_BLOCKS]
Definition interface.h:129
size_t block_count
Number of live chains.
Definition interface.h:128
srn_spinlock_t chain_locks[MAX_NUMBER_OF_BLOCKS]
One lock per chain, keyed by block id.
Definition interface.h:134
static void srn_spinlock_lock(srn_spinlock_t *lock)
Definition utils.h:285
static void srn_spinlock_unlock(srn_spinlock_t *lock)
Definition utils.h:276
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_a_free_block_id()

int find_a_free_block_id ( const srn_mm_t * mm)
inlinestatic

Definition at line 76 of file default.c.

76 {
77#if defined(__GNUC__) || defined(__clang__)
78 for (int i = 0; i < 4; i++) {
79 uint64_t word = mm->block_bitmap[i];
80
81 if (~word) {
82 // invert, then find first 1 bit
83 int bit = __builtin_ctzll(~word);
84 return (i * 64) + bit;
85 }
86 }
87 return -1;
88#else
89 // Fallback
90 for (int i = 0; i < 4; i++) {
91 uint64_t word = mm->block_bitmap[i];
92 if (word != ~0ULL) {
93 uint64_t mask = ~word;
94 int bit = 0;
95 while ((mask & 1ULL) == 0) {
96 mask >>= 1;
97 bit++;
98 }
99 return (i * 64) + bit;
100 }
101 }
102 return -1;
103#endif
104}
Here is the caller graph for this function:

◆ get_block()

srn_block_t * get_block ( const srn_mm_t * mm,
srn_block_id_t block_id )
inlinestatic

An abstraction over ID->Block operation.

Definition at line 109 of file default.c.

109 {
110 // Ids are reused, so the array slot decides liveness, a released or never
111 // allocated id holds a nullptr.
112 if (block_id < MAX_NUMBER_OF_BLOCKS) {
113 return mm->blocks[block_id];
114 }
115 return nullptr;
116}
#define MAX_NUMBER_OF_BLOCKS
array of blocks is enough for us, we can tweak the size as we see fit.
Definition interface.h:53
Here is the caller graph for this function:

◆ init_block()

void init_block ( srn_mm_t * mm,
srn_block_t * block )
inlinestatic

Definition at line 190 of file default.c.

190 {
191 PANIC_IF_NULL(mm);
192 block->next = nullptr;
193 block->size = mm->block_size;
194 block->offset = 0;
195}
Here is the caller graph for this function:

◆ is_block_id_free()

bool is_block_id_free ( const srn_mm_t * mm,
uint16_t bit )
inlinestatic

Definition at line 45 of file default.c.

45 {
46 PANIC_IF(bit >= 256, "Bit position is out of block_bitmap boundaries.");
47
48 // divide by 64, which 64-bit word
49 uint64_t index = bit >> 6U;
50 // remainder, which bit in that word
51 unsigned offset = bit & 63U;
52
53 return ((mm->block_bitmap[index] >> offset) & 1ULL) == 0;
54}
Here is the caller graph for this function:

◆ srn_lock_memory_manager()

void srn_lock_memory_manager ( srn_mm_t * mm)

Locks the memory manager.

We have to lock the memory manager when allocating blocks. TODO(lxsameer): Do we need to support thread local blocks?

Definition at line 436 of file default.c.

436{ srn_spinlock_lock(&mm->lock); }
srn_spinlock_t lock
This spinlock is here to protect the srn_mm_t when allocating/deallocating new blocks.
Definition interface.h:117
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_mm_allocate_block()

srn_block_id_t srn_mm_allocate_block ( srn_mm_t * mm)
nodiscard

Allocate a new block in the memory manager and return its ID.

The client code can use the ID to allocate memory on the block and when it's done, just use the same ID to release the block

Definition at line 438 of file default.c.

438 {
440 // Ids are reused after release, so exhaustion means every id is live
441 // right now, not that this many allocations ever happened.
442 int index = find_a_free_block_id(mm);
443 PANIC_IF(index == -1, "Out of memory: all block ids are in use");
445
446 mm->block_count++;
447 PANIC_IF(
448 !is_block_id_free(mm, (uint16_t)index),
449 "Miscalculated the block id. It is not free. This is a bug!"
450 );
451 allocated_block_id(mm, (uint16_t)index);
452 mm->blocks[(srn_block_id_t)index] = block;
453
455
456#if SERENE_DEBUG
457 mm->stats.total_blocks++;
458 mm->stats.total_os_allocations++;
459#endif
460 return (srn_block_id_t)index;
461}
size_t srn_block_id_t
The block id is effectively just an index in the blocks array in srn_mm_t.
Definition context.h:38
static int find_a_free_block_id(const srn_mm_t *mm)
Definition default.c:76
static void allocated_block_id(srn_mm_t *mm, uint16_t bit)
Definition default.c:56
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_mm_allocate_in_block_aligned()

void * srn_mm_allocate_in_block_aligned ( srn_mm_t * mm,
srn_block_id_t block_id,
size_t size,
size_t alignment )
nodiscard

Allocate memory on a block with the given block_id.

Definition at line 406 of file default.c.

408 {
409 MM_LOG("Allocating %zu bytes with %zu bytes alignment in block: %zu", size, alignment, block_id);
410 PANIC_IF(block_id >= MAX_NUMBER_OF_BLOCKS, "Block id out of range");
411
412 // The id resolves to a block only under the chain lock, so a release
413 // cannot free the chain out from under this walk.
414 srn_spinlock_t *chain_lock = &mm->chain_locks[block_id];
415 srn_spinlock_lock(chain_lock);
416
417 srn_block_t *block = get_block(mm, block_id);
418 PANIC_IF_NULL(block);
419
420 void *ptr = alloc_in_block(mm, block, size, alignment);
421 srn_spinlock_unlock(chain_lock);
422 MM_TRACEPOINT(mm_alloc, (uint64_t)block_id, (uint64_t)size, ptr);
423 return ptr;
424}
static void * alloc_in_block(srn_mm_t *mm, srn_block_t *root_block, size_t size, size_t alignment)
This is the main allocation logic that allocates the space in the given block.
Definition default.c:252
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_mm_free()

void srn_mm_free ( srn_mm_t * mm,
void * ptr )

Release a pointer previously returned by srn_mm_malloc or srn_mm_reallocate.

ptr may be nullptr, in which case the call is a no-op.

Definition at line 169 of file default.c.

169 {
170 UNUSED(mm);
171 MM_TRACEPOINT(mm_free, ptr);
172 free(ptr);
173}
#define UNUSED(x)
Definition utils.h:45
Here is the caller graph for this function:

◆ srn_mm_get_block()

srn_block_t * srn_mm_get_block ( srn_mm_t * mm,
srn_block_id_t block_id )

Return the block object associated by the given block_id.

Definition at line 328 of file default.c.

328 {
329 return get_block(mm, block_id);
330}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_mm_get_os_page_size()

size_t srn_mm_get_os_page_size ( void )

Retutrns the OS page size.

Definition at line 313 of file default.c.

313 {
314#if defined(_WIN32)
315 SYSTEM_INFO si;
316 GetSystemInfo(&si);
317 return (size_t)si.dwPageSize;
318#elif defined(__unix__) || defined(__APPLE__)
319 long sz = sysconf(_SC_PAGESIZE);
320 return (sz > 0) ? (size_t)sz : FALLBACK_PAGE_SIZE;
321#elif defined(__wasm__)
322 return WASM_PAGE_SIZE;
323#else
324 return FALLBACK_PAGE_SIZE;
325#endif
326}
#define FALLBACK_PAGE_SIZE
Definition interface.h:45
Here is the caller graph for this function:

◆ srn_mm_immortal_allocate_aligned()

void * srn_mm_immortal_allocate_aligned ( srn_mm_t * mm,
size_t size,
size_t alignment )
nodiscard

Allocate memory on the importal block which will never gets freed.

Definition at line 426 of file default.c.

426 {
428 void *ptr = alloc_in_block(mm, mm->immortal_block, size, alignment);
430 MM_TRACEPOINT(mm_immortal_alloc, (uint64_t)size, ptr);
431 return ptr;
432}
srn_block_t * immortal_block
Immortal block is a chain of blocks which will never die.
Definition interface.h:142
srn_spinlock_t immortal_lock
The immortal chain has no block id, so it gets its own chain lock.
Definition interface.h:137
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_mm_init()

srn_mm_t * srn_mm_init ( const srn_configuration_t * config)

Initialize the memory manager, this function will panic on error.

config provides the knobs the manager reads at init (mm.block_size_magnitude, the block size is 1 << magnitude); a null config means "use the defaults". The config is read only during the call, so the caller may pass a stack value and reuse it for srn_engine_make.

Definition at line 332 of file default.c.

332 {
333 if (config != nullptr) {
334 srn_config_validate(config);
335 }
336
337 srn_mm_t *mm = malloc(sizeof(srn_mm_t));
338 PANIC_IF_NULL(mm);
339
341 memset(mm->block_bitmap, 0, sizeof(mm->block_bitmap));
342
343 // The block size is the one knob the manager reads at init. It comes as a
344 // magnitude, so the size is a power of two and a whole number of pages by
345 // construction, with nothing to round.
346 const size_t magnitude =
348
349 mm->block_count = 0;
350 mm->block_size = (size_t)1 << magnitude;
351 memset((void *)mm->blocks, 0, sizeof(mm->blocks));
352
353 PANIC_IF(
354 mm->block_size <= sizeof(srn_block_t),
355 "Wrong block size. Configure mm.block_size_magnitude to a larger number"
356 );
357 // srn_config_validate only sees a caller provided config, so the default
358 // path is checked here too. The page size is only known at run time.
359 PANIC_IF(
360 mm->block_size % srn_mm_get_os_page_size() != 0, "Block size must be a whole number of OS pages"
361 );
362
364 for (size_t i = 0; i < MAX_NUMBER_OF_BLOCKS; i++) {
366 }
368
369 srn_block_t *immortal =
371 PANIC_IF_NULL(immortal);
372 init_block(mm, immortal);
373 mm->immortal_block = immortal;
374
375#if SERENE_DEBUG
376 mm->stats.allocated_pages = 0;
377 mm->stats.total_allocations = 0;
378 mm->stats.total_os_allocations = 0;
379 mm->stats.total_blocks = 0;
380#endif
381 return mm;
382}
void srn_config_validate(const srn_configuration_t *config)
A configuration with every field set to its default.
#define SRN_CONFIG_DEFAULT_BLOCK_SIZE_MAGNITUDE
Magnitude of one memory-manager block.
static srn_memory_provider_t stdlib_provider
Definition default.c:144
size_t srn_mm_get_os_page_size(void)
Retutrns the OS page size.
Definition default.c:313
srn_mm_config_t mm
size_t block_size_magnitude
Magnitude of one block the arena hands out from.
Main memory manager structure that will own all the allocated blocks and data.
Definition interface.h:110
static void srn_spinlock_init(srn_spinlock_t *lock)
Definition utils.h:280
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_mm_malloc()

void * srn_mm_malloc ( srn_mm_t * mm,
size_t size )
nodiscard

Generic allocations that do not participate in the block based pools.

Equivalent to malloc/realloc/free. Routed through the memory manager so the backend can later be swapped without touching callers. mm is reserved for future per manager routing and is currently unused inside the implementation.

Definition at line 155 of file default.c.

155 {
156 UNUSED(mm);
157 void *ptr = malloc(size);
158 MM_TRACEPOINT(mm_malloc, (uint64_t)size, ptr);
159 return ptr;
160}
Here is the caller graph for this function:

◆ srn_mm_reallocate()

void * srn_mm_reallocate ( srn_mm_t * mm,
void * ptr,
size_t new_size )
nodiscard

Definition at line 162 of file default.c.

162 {
163 UNUSED(mm);
164 void *out = realloc(ptr, new_size);
165 MM_TRACEPOINT(mm_realloc, ptr, (uint64_t)new_size, out);
166 return out;
167}
Here is the caller graph for this function:

◆ srn_mm_release_block()

void srn_mm_release_block ( srn_mm_t * mm,
srn_block_id_t id )

Release the given block id and free the memory for later allocations.

Definition at line 463 of file default.c.

463 {
464 PANIC_IF_NULL(mm);
465 destroy_chain(mm, id);
466}
static void destroy_chain(srn_mm_t *mm, srn_block_id_t root_id)
Definition default.c:212
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_mm_shutdown()

void srn_mm_shutdown ( srn_mm_t * mm)

Shut down the memory manager and release the resources.

Will panic on error. Technically it should be the final piece of clean up that we call. Note: Shutdown is not thread safe at has to execute on the main thread.

Definition at line 384 of file default.c.

384 {
385 PANIC_IF_NULL(mm);
386 assert(mm->provider != nullptr);
387
388 for (size_t i = 0; i < MAX_NUMBER_OF_BLOCKS; i++) {
389 if (mm->blocks[i] != nullptr) {
390 destroy_chain(mm, i);
391 }
392 }
393
394 srn_block_t *block = mm->immortal_block;
395
396 while (block != nullptr) {
397 srn_block_t *tmp = block;
398 block = tmp->next;
399
400 mm->provider->release(tmp);
401 }
402
403 mm->provider->release(mm);
404}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_unlock_memory_manager()

void srn_unlock_memory_manager ( srn_mm_t * mm)

Unocks the memory manager.

Definition at line 434 of file default.c.

434{ srn_spinlock_unlock(&mm->lock); }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ stdlib_allocator()

void * stdlib_allocator ( size_t size,
size_t alignment )
static

Just a proxy functions to the standard stdlib malloc/free later on if we decided to use mimalloc or something or even our own malloc, we can plug them in like this.

Definition at line 123 of file default.c.

123 {
124 PANIC_IF(size % alignment != 0, "'size' should be a multiple of alignment");
125
126#if defined(_WIN32)
127 return _aligned_malloc(size, alignment);
128#else
129 // C11 standard. It stills bothers me why microsoft is not doing it.
130 return aligned_alloc(alignment, size);
131#endif
132}

◆ stdlib_releaser()

void stdlib_releaser ( void * ptr)
static

Definition at line 134 of file default.c.

134 {
135#if defined(_WIN32)
136 // _aligned_malloc memory must go back through _aligned_free; plain free
137 // corrupts the CRT heap.
138 _aligned_free(ptr);
139#else
140 free(ptr);
141#endif
142}

Variable Documentation

◆ stdlib_provider

srn_memory_provider_t stdlib_provider
static
Initial value:
= {
.allocate = &stdlib_allocator,
.release = &stdlib_releaser,
}
static void stdlib_releaser(void *ptr)
Definition default.c:134
static void * stdlib_allocator(size_t size, size_t alignment)
Just a proxy functions to the standard stdlib malloc/free later on if we decided to use mimalloc or s...
Definition default.c:123

Definition at line 144 of file default.c.

144 {
145 .allocate = &stdlib_allocator,
146 .release = &stdlib_releaser,
147};