diff options
Diffstat (limited to 'src/common/mempool.c')
-rw-r--r-- | src/common/mempool.c | 899 |
1 files changed, 454 insertions, 445 deletions
diff --git a/src/common/mempool.c b/src/common/mempool.c index 35b03034d..62db7b9e3 100644 --- a/src/common/mempool.c +++ b/src/common/mempool.c @@ -30,9 +30,9 @@ #include "../common/malloc.h" #include "../common/mutex.h" -#define ALIGN16 ra_align(16) +#define ALIGN16 ra_align(16) #define ALIGN_TO(x, a) (x + ( a - ( x % a) ) ) -#define ALIGN_TO_16(x) ALIGN_TO(x, 16) +#define ALIGN_TO_16(x) ALIGN_TO(x, 16) #undef MEMPOOL_DEBUG #define MEMPOOLASSERT @@ -40,523 +40,532 @@ #define NODE_TO_DATA(x) ( ((char*)x) + sizeof(struct node) ) #define DATA_TO_NODE(x) ( (struct node*)(((char*)x) - sizeof(struct node)) ) -struct ra_align(16) node{ - void *next; - void *segment; +struct ra_align(16) node { + void *next; + void *segment; #ifdef MEMPOOLASSERT - bool used; - uint64 magic; - #define NODE_MAGIC 0xBEEF00EAEACAFE07ll + bool used; + uint64 magic; +#define NODE_MAGIC 0xBEEF00EAEACAFE07ll #endif }; // The Pointer to this struct is the base address of the segment itself. -struct pool_segment{ - mempool pool; // pool, this segment belongs to - struct pool_segment *next; - int64 num_nodes_total; - int64 num_bytes; +struct pool_segment { + mempool pool; // pool, this segment belongs to + struct pool_segment *next; + int64 num_nodes_total; + int64 num_bytes; }; -struct mempool{ - // Settings - char *name; - uint64 elem_size; - uint64 elem_realloc_step; - int64 elem_realloc_thresh; - - // Callbacks that get called for every node that gets allocated - // Example usage: initialization of mutex/lock for each node. - memPoolOnNodeAllocationProc onalloc; - memPoolOnNodeDeallocationProc ondealloc; - - // Locks - SPIN_LOCK segmentLock; - SPIN_LOCK nodeLock; - - - // Internal - struct pool_segment *segments; - struct node *free_list; - - volatile int64 num_nodes_total; - volatile int64 num_nodes_free; - - volatile int64 num_segments; - volatile int64 num_bytes_total; - - volatile int64 peak_nodes_used; // Peak Node Usage - volatile int64 num_realloc_events; // Number of reallocations done. (allocate additional nodes) - - // list (used for global management such as allocator..) - struct mempool *next; +struct mempool { + // Settings + char *name; + uint64 elem_size; + uint64 elem_realloc_step; + int64 elem_realloc_thresh; + + // Callbacks that get called for every node that gets allocated + // Example usage: initialization of mutex/lock for each node. + memPoolOnNodeAllocationProc onalloc; + memPoolOnNodeDeallocationProc ondealloc; + + // Locks + SPIN_LOCK segmentLock; + SPIN_LOCK nodeLock; + + + // Internal + struct pool_segment *segments; + struct node *free_list; + + volatile int64 num_nodes_total; + volatile int64 num_nodes_free; + + volatile int64 num_segments; + volatile int64 num_bytes_total; + + volatile int64 peak_nodes_used; // Peak Node Usage + volatile int64 num_realloc_events; // Number of reallocations done. (allocate additional nodes) + + // list (used for global management such as allocator..) + struct mempool *next; } ra_align(8); // Dont touch the alignment, otherwise interlocked functions are broken .. -/// +/// // Implementation: // static void segment_allocate_add(mempool p, uint64 count); static SPIN_LOCK l_mempoolListLock; -static mempool l_mempoolList = NULL; +static mempool l_mempoolList = NULL; static rAthread l_async_thread = NULL; -static ramutex l_async_lock = NULL; -static racond l_async_cond = NULL; +static ramutex l_async_lock = NULL; +static racond l_async_cond = NULL; static volatile int32 l_async_terminate = 0; -static void *mempool_async_allocator(void *x){ - mempool p; - - - while(1){ - if(l_async_terminate > 0) - break; - - EnterSpinLock(&l_mempoolListLock); - - for(p = l_mempoolList; p != NULL; p = p->next){ - - if(p->num_nodes_free < p->elem_realloc_thresh){ - // add new segment. - segment_allocate_add(p, p->elem_realloc_step); - // increase stats counter - InterlockedIncrement64(&p->num_realloc_events); - } - - } - - LeaveSpinLock(&l_mempoolListLock); - - ramutex_lock( l_async_lock ); - racond_wait( l_async_cond, l_async_lock, -1 ); - ramutex_unlock( l_async_lock ); - } - - - return NULL; +static void *mempool_async_allocator(void *x) +{ + mempool p; + + + while (1) { + if (l_async_terminate > 0) + break; + + EnterSpinLock(&l_mempoolListLock); + + for (p = l_mempoolList; p != NULL; p = p->next) { + + if (p->num_nodes_free < p->elem_realloc_thresh) { + // add new segment. + segment_allocate_add(p, p->elem_realloc_step); + // increase stats counter + InterlockedIncrement64(&p->num_realloc_events); + } + + } + + LeaveSpinLock(&l_mempoolListLock); + + ramutex_lock(l_async_lock); + racond_wait(l_async_cond, l_async_lock, -1); + ramutex_unlock(l_async_lock); + } + + + return NULL; }//end: mempool_async_allocator() -void mempool_init(){ - - if(sizeof(struct node)%16 != 0 ){ - ShowFatalError("mempool_init: struct node alignment failure. %u != multiple of 16\n", sizeof(struct node)); - exit(EXIT_FAILURE); - } - - // Global List start - InitializeSpinLock(&l_mempoolListLock); - l_mempoolList = NULL; - - // Initialize mutex + stuff needed for async allocator worker. - l_async_terminate = 0; - l_async_lock = ramutex_create(); - l_async_cond = racond_create(); - - l_async_thread = rathread_createEx(mempool_async_allocator, NULL, 1024*1024, RAT_PRIO_NORMAL); - if(l_async_thread == NULL){ - ShowFatalError("mempool_init: cannot spawn Async Allocator Thread.\n"); - exit(EXIT_FAILURE); - } +void mempool_init() +{ + + if (sizeof(struct node)%16 != 0) { + ShowFatalError("mempool_init: struct node alignment failure. %u != multiple of 16\n", sizeof(struct node)); + exit(EXIT_FAILURE); + } + + // Global List start + InitializeSpinLock(&l_mempoolListLock); + l_mempoolList = NULL; + + // Initialize mutex + stuff needed for async allocator worker. + l_async_terminate = 0; + l_async_lock = ramutex_create(); + l_async_cond = racond_create(); + + l_async_thread = rathread_createEx(mempool_async_allocator, NULL, 1024*1024, RAT_PRIO_NORMAL); + if (l_async_thread == NULL) { + ShowFatalError("mempool_init: cannot spawn Async Allocator Thread.\n"); + exit(EXIT_FAILURE); + } }//end: mempool_init() -void mempool_final(){ - mempool p, pn; - - ShowStatus("Mempool: Terminating async. allocation worker and remaining pools.\n"); - - // Terminate worker / wait until its terminated. - InterlockedIncrement(&l_async_terminate); - racond_signal(l_async_cond); - rathread_wait(l_async_thread, NULL); - - // Destroy cond var and mutex. - racond_destroy( l_async_cond ); - ramutex_destroy( l_async_lock ); - - // Free remaining mempools - // ((bugged code! this should halppen, every mempool should - // be freed by the subsystem that has allocated it.) - // - EnterSpinLock(&l_mempoolListLock); - p = l_mempoolList; - while(1){ - if(p == NULL) - break; - - pn = p->next; - - ShowWarning("Mempool [%s] was not properly destroyed - forcing destroy.\n", p->name); - mempool_destroy(p); - - p = pn; - } - LeaveSpinLock(&l_mempoolListLock); - +void mempool_final() +{ + mempool p, pn; + + ShowStatus("Mempool: Terminating async. allocation worker and remaining pools.\n"); + + // Terminate worker / wait until its terminated. + InterlockedIncrement(&l_async_terminate); + racond_signal(l_async_cond); + rathread_wait(l_async_thread, NULL); + + // Destroy cond var and mutex. + racond_destroy(l_async_cond); + ramutex_destroy(l_async_lock); + + // Free remaining mempools + // ((bugged code! this should halppen, every mempool should + // be freed by the subsystem that has allocated it.) + // + EnterSpinLock(&l_mempoolListLock); + p = l_mempoolList; + while (1) { + if (p == NULL) + break; + + pn = p->next; + + ShowWarning("Mempool [%s] was not properly destroyed - forcing destroy.\n", p->name); + mempool_destroy(p); + + p = pn; + } + LeaveSpinLock(&l_mempoolListLock); + }//end: mempool_final() -static void segment_allocate_add(mempool p, uint64 count){ - - // Required Memory: - // sz( segment ) - // count * sz( real_node_size ) - // - // where real node size is: - // ALIGN_TO_16( sz( node ) ) + p->elem_size - // so the nodes usable address is nodebase + ALIGN_TO_16(sz(node)) - // - size_t total_sz; - struct pool_segment *seg = NULL; - struct node *nodeList = NULL; - struct node *node = NULL; - char *ptr = NULL; - uint64 i; - - total_sz = ALIGN_TO_16( sizeof(struct pool_segment) ) - + ( (size_t)count * (sizeof(struct node) + (size_t)p->elem_size) ) ; +static void segment_allocate_add(mempool p, uint64 count) +{ + + // Required Memory: + // sz( segment ) + // count * sz( real_node_size ) + // + // where real node size is: + // ALIGN_TO_16( sz( node ) ) + p->elem_size + // so the nodes usable address is nodebase + ALIGN_TO_16(sz(node)) + // + size_t total_sz; + struct pool_segment *seg = NULL; + struct node *nodeList = NULL; + struct node *node = NULL; + char *ptr = NULL; + uint64 i; + + total_sz = ALIGN_TO_16(sizeof(struct pool_segment)) + + ((size_t)count * (sizeof(struct node) + (size_t)p->elem_size)) ; #ifdef MEMPOOL_DEBUG - ShowDebug("Mempool [%s] Segment AllocateAdd (num: %u, total size: %0.2fMiB)\n", p->name, count, (float)total_sz/1024.f/1024.f); + ShowDebug("Mempool [%s] Segment AllocateAdd (num: %u, total size: %0.2fMiB)\n", p->name, count, (float)total_sz/1024.f/1024.f); #endif - // allocate! (spin forever until weve got the memory.) - i=0; - while(1){ - ptr = (char*)aMalloc(total_sz); - if(ptr != NULL) break; - - i++; // increase failcount. - if(!(i & 7)){ - ShowWarning("Mempool [%s] Segment AllocateAdd => System seems to be Out of Memory (%0.2f MiB). Try #%u\n", (float)total_sz/1024.f/1024.f, i); + // allocate! (spin forever until weve got the memory.) + i=0; + while (1) { + ptr = (char *)aMalloc(total_sz); + if (ptr != NULL) break; + + i++; // increase failcount. + if (!(i & 7)) { + ShowWarning("Mempool [%s] Segment AllocateAdd => System seems to be Out of Memory (%0.2f MiB). Try #%u\n", (float)total_sz/1024.f/1024.f, i); #ifdef WIN32 - Sleep(1000); + Sleep(1000); #else - sleep(1); + sleep(1); #endif - }else{ - rathread_yield(); /// allow/force vuln. ctxswitch - } - }//endwhile: allocation spinloop. - - // Clear Memory. - memset(ptr, 0x00, total_sz); - - // Initialize segment struct. - seg = (struct pool_segment*)ptr; - ptr += ALIGN_TO_16(sizeof(struct pool_segment)); - - seg->pool = p; - seg->num_nodes_total = count; - seg->num_bytes = total_sz; - - - // Initialze nodes! - nodeList = NULL; - for(i = 0; i < count; i++){ - node = (struct node*)ptr; - ptr += sizeof(struct node); - ptr += p->elem_size; - - node->segment = seg; + } else { + rathread_yield(); /// allow/force vuln. ctxswitch + } + }//endwhile: allocation spinloop. + + // Clear Memory. + memset(ptr, 0x00, total_sz); + + // Initialize segment struct. + seg = (struct pool_segment *)ptr; + ptr += ALIGN_TO_16(sizeof(struct pool_segment)); + + seg->pool = p; + seg->num_nodes_total = count; + seg->num_bytes = total_sz; + + + // Initialze nodes! + nodeList = NULL; + for (i = 0; i < count; i++) { + node = (struct node *)ptr; + ptr += sizeof(struct node); + ptr += p->elem_size; + + node->segment = seg; #ifdef MEMPOOLASSERT - node->used = false; - node->magic = NODE_MAGIC; + node->used = false; + node->magic = NODE_MAGIC; #endif - if(p->onalloc != NULL) p->onalloc( NODE_TO_DATA(node) ); - - node->next = nodeList; - nodeList = node; - } - - - - // Link in Segment. - EnterSpinLock(&p->segmentLock); - seg->next = p->segments; - p->segments = seg; - LeaveSpinLock(&p->segmentLock); - - // Link in Nodes - EnterSpinLock(&p->nodeLock); - nodeList->next = p->free_list; - p->free_list = nodeList; - LeaveSpinLock(&p->nodeLock); - - - // Increase Stats: - InterlockedExchangeAdd64(&p->num_nodes_total, count); - InterlockedExchangeAdd64(&p->num_nodes_free, count); - InterlockedIncrement64(&p->num_segments); - InterlockedExchangeAdd64(&p->num_bytes_total, total_sz); - + if (p->onalloc != NULL) p->onalloc(NODE_TO_DATA(node)); + + node->next = nodeList; + nodeList = node; + } + + + + // Link in Segment. + EnterSpinLock(&p->segmentLock); + seg->next = p->segments; + p->segments = seg; + LeaveSpinLock(&p->segmentLock); + + // Link in Nodes + EnterSpinLock(&p->nodeLock); + nodeList->next = p->free_list; + p->free_list = nodeList; + LeaveSpinLock(&p->nodeLock); + + + // Increase Stats: + InterlockedExchangeAdd64(&p->num_nodes_total, count); + InterlockedExchangeAdd64(&p->num_nodes_free, count); + InterlockedIncrement64(&p->num_segments); + InterlockedExchangeAdd64(&p->num_bytes_total, total_sz); + }//end: segment_allocate_add() mempool mempool_create(const char *name, - uint64 elem_size, - uint64 initial_count, - uint64 realloc_count, - memPoolOnNodeAllocationProc onNodeAlloc, - memPoolOnNodeDeallocationProc onNodeDealloc){ - //.. - uint64 realloc_thresh; - mempool pool; - pool = (mempool)aCalloc( 1, sizeof(struct mempool) ); - - if(pool == NULL){ - ShowFatalError("mempool_create: Failed to allocate %u bytes memory.\n", sizeof(struct mempool) ); - exit(EXIT_FAILURE); - } - - // Check minimum initial count / realloc count requirements. - if(initial_count < 50) - initial_count = 50; - if(realloc_count < 50) - realloc_count = 50; - - // Set Reallocation threshold to 5% of realloc_count, at least 10. - realloc_thresh = (realloc_count/100)*5; // - if(realloc_thresh < 10) - realloc_thresh = 10; - - // Initialize members.. - pool->name = aStrdup(name); - pool->elem_size = ALIGN_TO_16(elem_size); - pool->elem_realloc_step = realloc_count; - pool->elem_realloc_thresh = realloc_thresh; - pool->onalloc = onNodeAlloc; - pool->ondealloc = onNodeDealloc; - - InitializeSpinLock(&pool->segmentLock); - InitializeSpinLock(&pool->nodeLock); - - // Initial Statistic values: - pool->num_nodes_total = 0; - pool->num_nodes_free = 0; - pool->num_segments = 0; - pool->num_bytes_total = 0; - pool->peak_nodes_used = 0; - pool->num_realloc_events = 0; - - // + uint64 elem_size, + uint64 initial_count, + uint64 realloc_count, + memPoolOnNodeAllocationProc onNodeAlloc, + memPoolOnNodeDeallocationProc onNodeDealloc) +{ + //.. + uint64 realloc_thresh; + mempool pool; + pool = (mempool)aCalloc(1, sizeof(struct mempool)); + + if (pool == NULL) { + ShowFatalError("mempool_create: Failed to allocate %u bytes memory.\n", sizeof(struct mempool)); + exit(EXIT_FAILURE); + } + + // Check minimum initial count / realloc count requirements. + if (initial_count < 50) + initial_count = 50; + if (realloc_count < 50) + realloc_count = 50; + + // Set Reallocation threshold to 5% of realloc_count, at least 10. + realloc_thresh = (realloc_count/100)*5; // + if (realloc_thresh < 10) + realloc_thresh = 10; + + // Initialize members.. + pool->name = aStrdup(name); + pool->elem_size = ALIGN_TO_16(elem_size); + pool->elem_realloc_step = realloc_count; + pool->elem_realloc_thresh = realloc_thresh; + pool->onalloc = onNodeAlloc; + pool->ondealloc = onNodeDealloc; + + InitializeSpinLock(&pool->segmentLock); + InitializeSpinLock(&pool->nodeLock); + + // Initial Statistic values: + pool->num_nodes_total = 0; + pool->num_nodes_free = 0; + pool->num_segments = 0; + pool->num_bytes_total = 0; + pool->peak_nodes_used = 0; + pool->num_realloc_events = 0; + + // #ifdef MEMPOOL_DEBUG - ShowDebug("Mempool [%s] Init (ElemSize: %u, Initial Count: %u, Realloc Count: %u)\n", pool->name, pool->elem_size, initial_count, pool->elem_realloc_step); + ShowDebug("Mempool [%s] Init (ElemSize: %u, Initial Count: %u, Realloc Count: %u)\n", pool->name, pool->elem_size, initial_count, pool->elem_realloc_step); #endif - // Allocate first segment directly :) - segment_allocate_add(pool, initial_count); - + // Allocate first segment directly :) + segment_allocate_add(pool, initial_count); + + + // Add Pool to the global pool list + EnterSpinLock(&l_mempoolListLock); + pool->next = l_mempoolList; + l_mempoolList = pool; + LeaveSpinLock(&l_mempoolListLock); - // Add Pool to the global pool list - EnterSpinLock(&l_mempoolListLock); - pool->next = l_mempoolList; - l_mempoolList = pool; - LeaveSpinLock(&l_mempoolListLock); - - return pool; + return pool; }//end: mempool_create() -void mempool_destroy(mempool p){ - struct pool_segment *seg, *segnext; - struct node *niter; - mempool piter, pprev; - char *ptr; - int64 i; +void mempool_destroy(mempool p) +{ + struct pool_segment *seg, *segnext; + struct node *niter; + mempool piter, pprev; + char *ptr; + int64 i; #ifdef MEMPOOL_DEBUG ShowDebug("Mempool [%s] Destroy\n", p->name); #endif - - // Unlink from global list. - EnterSpinLock(&l_mempoolListLock); - piter = l_mempoolList; - pprev = l_mempoolList; - while(1){ - if(piter == NULL) - break; - - - if(piter == p){ - // unlink from list, - // - if(pprev == l_mempoolList){ - // this (p) is list begin. so set next as head. - l_mempoolList = p->next; - }else{ - // replace prevs next wuth our next. - pprev->next = p->next; - } - break; - } - - pprev = piter; - piter = piter->next; - } - - p->next = NULL; - LeaveSpinLock(&l_mempoolListLock); - - - // Get both locks. - EnterSpinLock(&p->segmentLock); - EnterSpinLock(&p->nodeLock); - - - if(p->num_nodes_free != p->num_nodes_total) - ShowWarning("Mempool [%s] Destroy - %u nodes are not freed properly!\n", p->name, (p->num_nodes_total - p->num_nodes_free) ); - - // Free All Segments (this will also free all nodes) - // The segment pointer is the base pointer to the whole segment. - seg = p->segments; - while(1){ - if(seg == NULL) - break; - - segnext = seg->next; - - // .. - if(p->ondealloc != NULL){ - // walk over the segment, and call dealloc callback! - ptr = (char*)seg; - ptr += ALIGN_TO_16(sizeof(struct pool_segment)); - for(i = 0; i < seg->num_nodes_total; i++){ - niter = (struct node*)ptr; - ptr += sizeof(struct node); - ptr += p->elem_size; + + // Unlink from global list. + EnterSpinLock(&l_mempoolListLock); + piter = l_mempoolList; + pprev = l_mempoolList; + while (1) { + if (piter == NULL) + break; + + + if (piter == p) { + // unlink from list, + // + if (pprev == l_mempoolList) { + // this (p) is list begin. so set next as head. + l_mempoolList = p->next; + } else { + // replace prevs next wuth our next. + pprev->next = p->next; + } + break; + } + + pprev = piter; + piter = piter->next; + } + + p->next = NULL; + LeaveSpinLock(&l_mempoolListLock); + + + // Get both locks. + EnterSpinLock(&p->segmentLock); + EnterSpinLock(&p->nodeLock); + + + if (p->num_nodes_free != p->num_nodes_total) + ShowWarning("Mempool [%s] Destroy - %u nodes are not freed properly!\n", p->name, (p->num_nodes_total - p->num_nodes_free)); + + // Free All Segments (this will also free all nodes) + // The segment pointer is the base pointer to the whole segment. + seg = p->segments; + while (1) { + if (seg == NULL) + break; + + segnext = seg->next; + + // .. + if (p->ondealloc != NULL) { + // walk over the segment, and call dealloc callback! + ptr = (char *)seg; + ptr += ALIGN_TO_16(sizeof(struct pool_segment)); + for (i = 0; i < seg->num_nodes_total; i++) { + niter = (struct node *)ptr; + ptr += sizeof(struct node); + ptr += p->elem_size; #ifdef MEMPOOLASSERT - if(niter->magic != NODE_MAGIC){ - ShowError("Mempool [%s] Destroy - walk over segment - node %p invalid magic!\n", p->name, niter); - continue; - } + if (niter->magic != NODE_MAGIC) { + ShowError("Mempool [%s] Destroy - walk over segment - node %p invalid magic!\n", p->name, niter); + continue; + } #endif - - p->ondealloc( NODE_TO_DATA(niter) ); - - - } - }//endif: ondealloc callback? - - // simple .. - aFree(seg); - - seg = segnext; - } - - // Clear node ptr - p->free_list = NULL; - InterlockedExchange64(&p->num_nodes_free, 0); - InterlockedExchange64(&p->num_nodes_total, 0); - InterlockedExchange64(&p->num_segments, 0); - InterlockedExchange64(&p->num_bytes_total, 0); - - LeaveSpinLock(&p->nodeLock); - LeaveSpinLock(&p->segmentLock); - - // Free pool itself :D - aFree(p->name); - aFree(p); + + p->ondealloc(NODE_TO_DATA(niter)); + + + } + }//endif: ondealloc callback? + + // simple .. + aFree(seg); + + seg = segnext; + } + + // Clear node ptr + p->free_list = NULL; + InterlockedExchange64(&p->num_nodes_free, 0); + InterlockedExchange64(&p->num_nodes_total, 0); + InterlockedExchange64(&p->num_segments, 0); + InterlockedExchange64(&p->num_bytes_total, 0); + + LeaveSpinLock(&p->nodeLock); + LeaveSpinLock(&p->segmentLock); + + // Free pool itself :D + aFree(p->name); + aFree(p); }//end: mempool_destroy() -void *mempool_node_get(mempool p){ - struct node *node; - int64 num_used; - - if(p->num_nodes_free < p->elem_realloc_thresh) - racond_signal(l_async_cond); - - while(1){ - - EnterSpinLock(&p->nodeLock); - - node = p->free_list; - if(node != NULL) - p->free_list = node->next; - - LeaveSpinLock(&p->nodeLock); - - if(node != NULL) - break; - - rathread_yield(); - } - - InterlockedDecrement64(&p->num_nodes_free); - - // Update peak value - num_used = (p->num_nodes_total - p->num_nodes_free); - if(num_used > p->peak_nodes_used){ - InterlockedExchange64(&p->peak_nodes_used, num_used); - } - +void *mempool_node_get(mempool p) +{ + struct node *node; + int64 num_used; + + if (p->num_nodes_free < p->elem_realloc_thresh) + racond_signal(l_async_cond); + + while (1) { + + EnterSpinLock(&p->nodeLock); + + node = p->free_list; + if (node != NULL) + p->free_list = node->next; + + LeaveSpinLock(&p->nodeLock); + + if (node != NULL) + break; + + rathread_yield(); + } + + InterlockedDecrement64(&p->num_nodes_free); + + // Update peak value + num_used = (p->num_nodes_total - p->num_nodes_free); + if (num_used > p->peak_nodes_used) { + InterlockedExchange64(&p->peak_nodes_used, num_used); + } + #ifdef MEMPOOLASSERT - node->used = true; + node->used = true; #endif - return NODE_TO_DATA(node); + return NODE_TO_DATA(node); }//end: mempool_node_get() -void mempool_node_put(mempool p, void *data){ - struct node *node; - - node = DATA_TO_NODE(data); +void mempool_node_put(mempool p, void *data) +{ + struct node *node; + + node = DATA_TO_NODE(data); #ifdef MEMPOOLASSERT - if(node->magic != NODE_MAGIC){ - ShowError("Mempool [%s] node_put failed, given address (%p) has invalid magic.\n", p->name, data); - return; // lost, - } - - { - struct pool_segment *node_seg = node->segment; - if(node_seg->pool != p){ - ShowError("Mempool [%s] node_put faild, given node (data address %p) doesnt belongs to this pool. ( Node Origin is [%s] )\n", p->name, data, node_seg->pool); - return; - } - } - - // reset used flag. - node->used = false; + if (node->magic != NODE_MAGIC) { + ShowError("Mempool [%s] node_put failed, given address (%p) has invalid magic.\n", p->name, data); + return; // lost, + } + + { + struct pool_segment *node_seg = node->segment; + if (node_seg->pool != p) { + ShowError("Mempool [%s] node_put faild, given node (data address %p) doesnt belongs to this pool. ( Node Origin is [%s] )\n", p->name, data, node_seg->pool); + return; + } + } + + // reset used flag. + node->used = false; #endif - // - EnterSpinLock(&p->nodeLock); - node->next = p->free_list; - p->free_list = node; - LeaveSpinLock(&p->nodeLock); - - InterlockedIncrement64(&p->num_nodes_free); + // + EnterSpinLock(&p->nodeLock); + node->next = p->free_list; + p->free_list = node; + LeaveSpinLock(&p->nodeLock); + + InterlockedIncrement64(&p->num_nodes_free); }//end: mempool_node_put() -mempool_stats mempool_get_stats(mempool pool){ - mempool_stats stats; - - // initialize all with zeros - memset(&stats, 0x00, sizeof(mempool_stats)); - - stats.num_nodes_total = pool->num_nodes_total; - stats.num_nodes_free = pool->num_nodes_free; - stats.num_nodes_used = (stats.num_nodes_total - stats.num_nodes_free); - stats.num_segments = pool->num_segments; - stats.num_realloc_events= pool->num_realloc_events; - stats.peak_nodes_used = pool->peak_nodes_used; - stats.num_bytes_total = pool->num_bytes_total; - - // Pushing such a large block over the stack as return value isnt nice - // but lazy :) and should be okay in this case (Stats / Debug..) - // if you dont like it - feel free and refactor it. - return stats; +mempool_stats mempool_get_stats(mempool pool) +{ + mempool_stats stats; + + // initialize all with zeros + memset(&stats, 0x00, sizeof(mempool_stats)); + + stats.num_nodes_total = pool->num_nodes_total; + stats.num_nodes_free = pool->num_nodes_free; + stats.num_nodes_used = (stats.num_nodes_total - stats.num_nodes_free); + stats.num_segments = pool->num_segments; + stats.num_realloc_events= pool->num_realloc_events; + stats.peak_nodes_used = pool->peak_nodes_used; + stats.num_bytes_total = pool->num_bytes_total; + + // Pushing such a large block over the stack as return value isnt nice + // but lazy :) and should be okay in this case (Stats / Debug..) + // if you dont like it - feel free and refactor it. + return stats; }//end: mempool_get_stats() |