static th_block_h* th_findFree(tinyheap* heap, unsigned int bsize, th_block_h* block) { th_block_h* bcand = block; TH_ASSERT_PAR_MALLOC(bcand); #if TH_CHECK_BOUNDARY unsigned int testlen = 0; #endif #if TH_PICK_STRAT_BEST_FIT || TH_PICK_STRAT_GOOD_ENOUGH_FIT unsigned int minD = heap->len; th_block_h* minDBlock = 0; #endif do { #if TH_CHECK_BOUNDARY TH_ASSERT(bcand->next > 0); #endif if (bcand->free && bcand->next >= bsize) { // found one #if TH_PICK_STRAT_FIRST return bcand; #endif #if TH_PICK_STRAT_BEST_FIT || TH_PICK_STRAT_GOOD_ENOUGH_FIT unsigned int d = bcand->next - bsize; #if TH_PICK_STRAT_BEST_FIT if (d <= 0) #endif #if TH_PICK_STRAT_GOOD_ENOUGH_FIT if (d <= TH_GOOD_ENOUGH_DELTA) #endif { return bcand; } else if (d < minD) { minD = d; minDBlock = bcand; } #endif } #if TH_COUNT_SEARCH_CYCLES heap->count++; #endif // next block #if TH_CHECK_BOUNDARY testlen += bcand->next; TH_ASSERT(testlen <= heap->len); #endif bcand = th_next(heap, bcand); if (bcand == 0) { // wrap bcand = heap->p; } TH_ASSERT_PAR_MALLOC(bcand); } while (bcand != block); #if TH_PICK_STRAT_FIRST return 0; #endif #if TH_PICK_STRAT_BEST_FIT || TH_PICK_STRAT_GOOD_ENOUGH_FIT return minDBlock; #endif }
static void th_internalAlloc(tinyheap* heap, unsigned int bsize, th_block_h* block) { unsigned int fullblocksize = block->next; block->free = 0; block->next = bsize; TH_CALC_PARITY(block); th_block_h* nblock = th_next(heap, block); #if TH_CALC_FREE heap->free -= bsize; #endif TH_ON_MALLOCED((void*)block + sizeof(th_block_h), block->next * TH_BLOCKSIZE - sizeof(th_block_h)); // split block if free is larger than requested if ((nblock - heap->p)/TH_BLOCKSIZE < heap->len && fullblocksize > bsize) { nblock->free = 1; nblock->next = fullblocksize - bsize; nblock->prev = bsize; TH_CALC_PARITY(nblock); #if TH_SEEK_STRAT_MIN_MAX if (nblock->next <= TH_BLOCK_MEDIAN) { if (heap->smallFree == 0 || !heap->smallFree->free) { heap->smallFree = nblock; } } else { if (heap->bigFree == 0 || !heap->bigFree->free) { heap->bigFree = nblock; } } #endif #if TH_SEEK_STRAT_LAST_FREE heap->lastFree = nblock; #endif TH_ON_SPLITFREED((void*)nblock + sizeof(th_block_h), nblock->next * TH_BLOCKSIZE - sizeof(th_block_h)); nblock = th_next(heap, nblock); if (nblock != 0) { nblock->prev = fullblocksize - bsize; TH_CALC_PARITY(nblock); } } }
// thread creation int th_fork(th_t *thread, void *(*start_routine)(void*), void *arg) { if (thread == 0 || start_routine == 0) return -1; entry_section(); th_start(); th_data *td = thread->u; td->param = arg; td->func = start_routine; thread->tid = th_it; threads[th_it] = thread; makecontext(&thread->uct, th_caller, 0); rq_push(th_it); th_next(); exit_section(); return 0; }
void th_dump(tinyheap* heap) { #if TH_SEEK_STRAT_MIN_MAX //heap->smallFree = 0; //heap->bigFree = 0; #endif #if TH_SEEK_STRAT_LAST_FREE //heap->lastFree = 0; #endif TH_PRINTF("heap data:%p size:%i blocksize:%i addr.bits:%i\n", heap->p, heap->len * TH_BLOCKSIZE, TH_BLOCKSIZE, TH_ADDRESSING_BITS); #if TH_CALC_FREE TH_PRINTF("heap free:%i\n", heap->free * TH_BLOCKSIZE); #endif #if TH_USE_PARITY TH_PRINTF("heap PARITY check enable, check "); #if TH_PARITY_CHECK_LEVEL == TH_PARITY_CHECK_DURING_FREE TH_PRINTF("during free\n"); #endif #if TH_PARITY_CHECK_LEVEL == TH_PARITY_CHECK_DURING_MALLOC TH_PRINTF("during malloc\n"); #endif #if TH_PARITY_CHECK_LEVEL == TH_PARITY_CHECK_ALL TH_PRINTF("always\n"); #endif #endif #if TH_SEEK_STRAT_MIN_MAX TH_PRINTF("heap seek stra:MIN_MAX smallFree:%p bigFree:%p med:%i\n", heap->smallFree, heap->bigFree, TH_BLOCK_MEDIAN * TH_BLOCKSIZE); #endif #if TH_SEEK_STRAT_LAST_FREE TH_PRINTF("heap seek stra:LAST_FREE lastFree:%p\n", heap->lastFree); #endif #if TH_SEEK_STRAT_NONE TH_PRINTF("heap seek stra:NONE\n"); #endif #if TH_PICK_STRAT_FIRST TH_PRINTF("heap pick stra:FIRST FOUND\n"); #endif #if TH_PICK_STRAT_BEST_FIT TH_PRINTF("heap pick stra:BEST FIT\n"); #endif #if TH_PICK_STRAT_GOOD_ENOUGH_FIT TH_PRINTF("heap pick stra:GOOD ENOUGH +-%i\n", TH_GOOD_ENOUGH_DELTA*TH_BLOCKSIZE); #endif TH_PRINTF("heap traverse:\n"); th_block_h* block = heap->p; TH_ASSERT_PAR_MALLOC(block); do { TH_PRINTF(" %p %s prv:%08i nxt:%08i len:%08i ", block, block->free ? "FREE" : "BUSY", block->prev, block->next, block->next * TH_BLOCKSIZE + TH_ALIGNMENT); #if TH_USE_PARITY TH_PRINTF("%s", th_checkParity(block) ? "OK" : "BAD"); #endif TH_PRINTF("\n "); { int len = block->next * TH_BLOCKSIZE; if (len > 16) len = 16; char *d = (char*)((void*)block + sizeof(th_block_h)); while (len--) { TH_PRINTF("%02x ", *d++); } } TH_PRINTF("\n"); // next block block = th_next(heap, block); } while (block != 0); }
void th_free(tinyheap* heap, void* p) { th_block_h* block = (th_block_h*)(p - sizeof(th_block_h) - TH_ALIGNMENT); TH_ASSERT_PAR_FREE(block); TH_ASSERT_FREE_FREED(block); TH_LOCK(heap); #if TH_CALC_FREE heap->free += block->next; #endif th_block_h* nblock = th_next(heap, block); // next block th_block_h* pblock = th_prev(heap, block); // prev block // check next block, if not this is last if (nblock != 0) { TH_ASSERT_PAR_FREE(nblock); if (nblock->free) { // next was free, so bang this and next together block->next += nblock->next; #if TH_SEEK_STRAT_MIN_MAX if (nblock == heap->smallFree) heap->smallFree = 0; if (nblock == heap->bigFree) heap->bigFree = 0; #endif #if TH_SEEK_STRAT_LAST_FREE if (nblock == heap->lastFree) heap->lastFree = 0; #endif nblock = th_next(heap, nblock); // nblock is now next next block } } // check previous block, if not this is first if (pblock != 0 && pblock->free) { // prev was free, so bang previous and this together TH_ASSERT_PAR_FREE(pblock); pblock->next += block->next; TH_CALC_PARITY(pblock); #if TH_SEEK_STRAT_MIN_MAX if (block == heap->smallFree) heap->smallFree = 0; if (block == heap->bigFree) heap->bigFree = 0; #endif #if TH_SEEK_STRAT_LAST_FREE if (block == heap->lastFree) heap->lastFree = 0; #endif block = pblock; // current block is now previous } else { // previous wasn't free, so mark this one free now block->free = 1; TH_CALC_PARITY(block); } #if TH_SEEK_STRAT_MIN_MAX if (block->next <= TH_BLOCK_MEDIAN) { if (heap->smallFree == 0 || !heap->smallFree->free) { heap->smallFree = block; } } else { if (heap->bigFree == 0 || !heap->bigFree->free) { heap->bigFree = block; } } #endif #if TH_SEEK_STRAT_LAST_FREE heap->lastFree = block; #endif TH_ON_FREED((void*)block + sizeof(th_block_h), block->next * TH_BLOCKSIZE - sizeof(th_block_h)); // if block after this exists (might be next next if next was merged), update prev ptr if (nblock != 0) { TH_ASSERT_PAR_FREE(nblock); // might be doubled checked if there is a next ALLOCATED block nblock->prev = block->next; TH_CALC_PARITY(nblock); } TH_UNLOCK(heap); }