Пример #1
0
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
}
Пример #2
0
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);
    }
  }
}
Пример #3
0
// 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;
}
Пример #4
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);
}
Пример #5
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);
}