Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenlib/intern/BLI_memarena.c
| Show All 32 Lines | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "BLI_memarena.h" | #include "BLI_memarena.h" | ||||
| #include "BLI_linklist.h" | #include "BLI_linklist.h" | ||||
| #include "BLI_threads.h" | |||||
| #include "BLI_strict_flags.h" | #include "BLI_strict_flags.h" | ||||
| #ifdef WITH_MEM_VALGRIND | #ifdef WITH_MEM_VALGRIND | ||||
| # include "valgrind/memcheck.h" | # include "valgrind/memcheck.h" | ||||
| #endif | #endif | ||||
| struct MemArena { | struct MemArena { | ||||
| unsigned char *curbuf; | unsigned char *curbuf; | ||||
| const char *name; | const char *name; | ||||
| LinkNode *bufs; | LinkNode *bufs; | ||||
| size_t bufsize, cursize; | size_t bufsize, cursize; | ||||
| size_t align; | size_t align; | ||||
| bool use_calloc; | bool use_calloc; | ||||
| SpinLock *spin_lock, spin_lock_; | |||||
| }; | }; | ||||
| MemArena *BLI_memarena_new(const size_t bufsize, const char *name) | MemArena *BLI_memarena_new(const size_t bufsize, const char *name) | ||||
| { | { | ||||
| MemArena *ma = MEM_callocN(sizeof(*ma), "memarena"); | MemArena *ma = MEM_callocN(sizeof(*ma), "memarena"); | ||||
| ma->bufsize = bufsize; | ma->bufsize = bufsize; | ||||
| ma->align = 8; | ma->align = 8; | ||||
| ma->name = name; | ma->name = name; | ||||
| #ifdef WITH_MEM_VALGRIND | #ifdef WITH_MEM_VALGRIND | ||||
| VALGRIND_CREATE_MEMPOOL(ma, 0, false); | VALGRIND_CREATE_MEMPOOL(ma, 0, false); | ||||
| #endif | #endif | ||||
| ma->spin_lock = NULL; | |||||
| return ma; | return ma; | ||||
| } | } | ||||
| void BLI_memarena_use_calloc(MemArena *ma) | void BLI_memarena_use_calloc(MemArena *ma) | ||||
| { | { | ||||
| ma->use_calloc = 1; | ma->use_calloc = 1; | ||||
| } | } | ||||
| void BLI_memarena_use_malloc(MemArena *ma) | void BLI_memarena_use_malloc(MemArena *ma) | ||||
| { | { | ||||
| ma->use_calloc = 0; | ma->use_calloc = 0; | ||||
| } | } | ||||
| void BLI_memarena_use_align(struct MemArena *ma, const size_t align) | void BLI_memarena_use_align(struct MemArena *ma, const size_t align) | ||||
| { | { | ||||
| /* align should be a power of two */ | /* align should be a power of two */ | ||||
| ma->align = align; | ma->align = align; | ||||
| } | } | ||||
| void BLI_memarena_set_threadsafe(MemArena *ma) | |||||
| { | |||||
| if (!ma->spin_lock) { | |||||
| BLI_spin_init(&ma->spin_lock_); | |||||
| ma->spin_lock = &ma->spin_lock_; | |||||
| } | |||||
| } | |||||
| void BLI_memarena_clear_threadsafe(MemArena *ma) | |||||
| { | |||||
| if (ma->spin_lock) { | |||||
| ma->spin_lock = NULL; | |||||
| BLI_spin_end(&ma->spin_lock_); | |||||
| } | |||||
| } | |||||
| void BLI_memarena_free(MemArena *ma) | void BLI_memarena_free(MemArena *ma) | ||||
| { | { | ||||
| BLI_linklist_freeN(ma->bufs); | BLI_linklist_freeN(ma->bufs); | ||||
| #ifdef WITH_MEM_VALGRIND | #ifdef WITH_MEM_VALGRIND | ||||
| VALGRIND_DESTROY_MEMPOOL(ma); | VALGRIND_DESTROY_MEMPOOL(ma); | ||||
| #endif | #endif | ||||
| BLI_memarena_clear_threadsafe(ma); | |||||
| MEM_freeN(ma); | MEM_freeN(ma); | ||||
| } | } | ||||
| /* amt must be power of two */ | /* amt must be power of two */ | ||||
| #define PADUP(num, amt) (((num) + ((amt) - 1)) & ~((amt) - 1)) | #define PADUP(num, amt) (((num) + ((amt) - 1)) & ~((amt) - 1)) | ||||
| /* align alloc'ed memory (needed if align > 8) */ | /* align alloc'ed memory (needed if align > 8) */ | ||||
| static void memarena_curbuf_align(MemArena *ma) | static void memarena_curbuf_align(MemArena *ma) | ||||
| { | { | ||||
| unsigned char *tmp; | unsigned char *tmp; | ||||
| tmp = (unsigned char *)PADUP((intptr_t)ma->curbuf, (int)ma->align); | tmp = (unsigned char *)PADUP((intptr_t)ma->curbuf, (int)ma->align); | ||||
| ma->cursize -= (size_t)(tmp - ma->curbuf); | ma->cursize -= (size_t)(tmp - ma->curbuf); | ||||
| ma->curbuf = tmp; | ma->curbuf = tmp; | ||||
| } | } | ||||
| void *BLI_memarena_alloc(MemArena *ma, size_t size) | void *BLI_memarena_alloc(MemArena *ma, size_t size) | ||||
| { | { | ||||
| void *ptr; | void *ptr; | ||||
| /* ensure proper alignment by rounding | /* ensure proper alignment by rounding | ||||
| * size up to multiple of 8 */ | * size up to multiple of 8 */ | ||||
| size = PADUP(size, ma->align); | size = PADUP(size, ma->align); | ||||
| if (ma->spin_lock) { | |||||
| BLI_spin_lock(ma->spin_lock); | |||||
| } | |||||
| if (UNLIKELY(size > ma->cursize)) { | if (UNLIKELY(size > ma->cursize)) { | ||||
| if (size > ma->bufsize - (ma->align - 1)) { | if (size > ma->bufsize - (ma->align - 1)) { | ||||
| ma->cursize = PADUP(size + 1, ma->align); | ma->cursize = PADUP(size + 1, ma->align); | ||||
| } | } | ||||
| else { | else { | ||||
| ma->cursize = ma->bufsize; | ma->cursize = ma->bufsize; | ||||
| } | } | ||||
| ma->curbuf = (ma->use_calloc ? MEM_callocN : MEM_mallocN)(ma->cursize, ma->name); | ma->curbuf = (ma->use_calloc ? MEM_callocN : MEM_mallocN)(ma->cursize, ma->name); | ||||
| BLI_linklist_prepend(&ma->bufs, ma->curbuf); | BLI_linklist_prepend(&ma->bufs, ma->curbuf); | ||||
| memarena_curbuf_align(ma); | memarena_curbuf_align(ma); | ||||
| } | } | ||||
| ptr = ma->curbuf; | ptr = ma->curbuf; | ||||
| ma->curbuf += size; | ma->curbuf += size; | ||||
| ma->cursize -= size; | ma->cursize -= size; | ||||
| #ifdef WITH_MEM_VALGRIND | #ifdef WITH_MEM_VALGRIND | ||||
| VALGRIND_MEMPOOL_ALLOC(ma, ptr, size); | VALGRIND_MEMPOOL_ALLOC(ma, ptr, size); | ||||
| #endif | #endif | ||||
| if (ma->spin_lock) { | |||||
| BLI_spin_unlock(ma->spin_lock); | |||||
| } | |||||
| return ptr; | return ptr; | ||||
| } | } | ||||
| void *BLI_memarena_calloc(MemArena *ma, size_t size) | void *BLI_memarena_calloc(MemArena *ma, size_t size) | ||||
| { | { | ||||
| void *ptr; | void *ptr; | ||||
| /* no need to use this function call if we're calloc'ing by default */ | /* no need to use this function call if we're calloc'ing by default */ | ||||
| ▲ Show 20 Lines • Show All 42 Lines • Show Last 20 Lines | |||||