int do_init(int argc, char **argv){ rAthread *t[THRC]; int j, i; int ok; ShowStatus("==========\n"); ShowStatus("TEST: %u Runs, (%u Threads)\n", LOOPS, THRC); ShowStatus("This can take a while\n"); ShowStatus("\n\n"); ok =0; for(j = 0; j < LOOPS; j++){ val = 0; done_threads = 0; InitializeSpinLock(&lock); for(i =0; i < THRC; i++){ t[i] = rathread_createEx( worker, NULL, 1024*512, RAT_PRIO_NORMAL); } while(1){ if(InterlockedCompareExchange(&done_threads, THRC, THRC) == THRC) break; rathread_yield(); } FinalizeSpinLock(&lock); // Everything fine? if(val != (THRC*PERINC) ){ printf("FAILED! (Result: %u, Expected: %u)\n", val, (THRC*PERINC) ); }else{ printf("OK! (Result: %u, Expected: %u)\n", val, (THRC*PERINC) ); ok++; } } if(ok != LOOPS){ ShowFatalError("Test failed.\n"); exit(1); }else{ ShowStatus("Test passed.\n"); exit(0); } return 0; }//end: do_init()
netbuf netbuffer_get(sysint sz) { sysint i; netbuf nb = NULL; // Search an appropriate pool for(i = 0; i < l_nPools; i++) { if(sz <= l_poolElemSize[i]) { // match nb = (netbuf)mempool_node_get(l_pool[i]); nb->pool = i; break; } } // No Bufferpool found that mets there quirements?.. (thats bad..) if(nb == NULL) { ShowWarning(read_message("Source.netbuffer_get"), sz); ShowWarning(read_message("Source.netbuffer_get2")); InterlockedIncrement(&l_nEmergencyAllocations); // .. better to check (netbuf struct provides 32 byte bufferspace itself. if(sz < 32) sz = 32; // allocate memory using malloc .. while(1) { nb = (netbuf) aMalloc((sizeof(struct netbuf) + sz - 32)); if(nb != NULL) { memset(nb, 0x00, (sizeof(struct netbuf) + sz - 32)); // zero memory! (to enforce commit @ os.) nb->pool = -1; // emergency alloc. break; } rathread_yield(); }// spin allocation. } nb->refcnt = 1; // Initial refcount is 1 return nb; }//end: netbuffer_get()
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; #endif return NODE_TO_DATA(node); }//end: mempool_node_get()
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(read_message("Source.common.mempool_debug"), 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(read_message("Source.common.mempool_debug2"), (float)total_sz/1024.f/1024.f, i); #ifdef WIN32 Sleep(1000); #else 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; #ifdef MEMPOOLASSERT 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); }//end: segment_allocate_add()