static void qjoin(qarena_t *arena) { void *p = arena+1; void *end = (char *)arena + arena->size; while (p && p < end) { if (NX(p) < end && ISFREE(p) && ISFREE(NX(p))) { SZ(p) += BSZ(NX(p)); } else { p = NX(p); } } }
PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch) { int mask,startofs,endofs; TMemBlock *p; if (!heap || align2 < 0 || size <= 0) return NULL; mask = (1 << align2)-1; startofs = 0; p = (TMemBlock *)heap; while (p) { if (ISFREE(p)) { startofs = (p->ofs + mask) & ~mask; if ( startofs < startSearch ) { startofs = startSearch; } endofs = startofs+size; if (endofs <= (p->ofs+p->size)) break; } p = p->next; } if (!p) return NULL; p = SliceBlock(p,startofs,size,0,mask+1); p->heap = heap; return p; }
/**************************** * remove block from free list * the block might still be under construction, so no check_block() */ static void rem_free( tMemHdr *const tr ) { register tMemHdr *t0 = tr->prev_list; register tMemHdr *t1 = tr->next_list; assert( head_mem != NULL ); /* the cache exists */ assert( tr->magic == MAGIC ); assert( ISFREE(tr) ); assert( tr->next_mem == NULL || tr->next_mem->prev_mem == tr); assert( tr->prev_mem == NULL || tr->prev_mem->next_mem == tr); if( t1 != NULL ) { assert( tr->size >= t1->size ); /* decreasing size */ t1->prev_list = t0; } /* if */ if( t0 != NULL ) { assert( tr->size <= t0->size ); /* decreasing size */ t0->next_list = t1; } else { head_free = t1; } /* if */ assert( tr->next_mem == NULL || tr->next_mem->prev_mem == tr); assert( tr->prev_mem == NULL || tr->prev_mem->next_mem == tr); } /* rem_free() */
int _RTLENTRY _EXPFUNC _rtl_heapwalk(_HEAPINFO * __entry) { HEAP *h; BLOCKHDR *bh; if (IS_BIG_BLOCK(__entry)) /* We won't attempt to walk BIG Blocks */ return _HEAPEND; _lock_heap(); if (__entry->_pentry == NULL) { h = _firstHeap; bh = FIRSTBLOCK(h); } else { h = (HEAP *) __entry->_pentry; bh = (BLOCKHDR *) __entry->__pentry; } while (h) { if (__memBogusAddr(h)) return _HEAPBADPTR; while (HDR2PTR(bh) != ((char *) h + h->cSize)) { if (__memBogusAddr(bh)) return _HEAPBADPTR; __entry->_useflag = (ISFREE(bh) == 0); __entry->_size = SIZE(bh); bh = NEXT(bh); __entry->_pentry = (void *) h; __entry->__pentry = (void *) bh; _unlock_heap(); return _HEAPOK; } h = h->nextHeap; if (h) bh = FIRSTBLOCK(h); } _unlock_heap(); return _HEAPEND; }
int mmReserveMem(memHeap_t *heap, int offset,int size) { int endofs; TMemBlock *p; if (!heap || size <= 0) return -1; endofs = offset+size; p = (TMemBlock *)heap; while (p && p->ofs <= offset) { if (ISFREE(p) && endofs <= (p->ofs+p->size)) { SliceBlock(p,offset,size,1,1); return 0; } p = p->next; } return -1; }
/**************************** * add block to free list * check_block() is called when block added to free list */ static void add_free( tMemHdr *const tr ) { register tMemHdr *t0; register tMemHdr *t1; assert( tr != NULL ); assert( tr->magic == MAGIC ); assert( ISFREE(tr) ); /** find where to put tr into free list **/ t0 = NULL; t1 = head_free; while( t1 != NULL && t1->size > tr->size ) { assert( t1->next_list == NULL || t1->next_list->prev_list == t1 ); assert( t1->prev_list == t0 ); t0 = t1; t1 = t1->next_list; assert( t0 != NULL ); } /* while */ tr->next_list = t1; tr->prev_list = t0; if( t1 != NULL ) { t1->prev_list = tr; } /* if */ if( t0 == NULL ) { /* the free list is empty, or this is the largest block */ head_free = tr; } else { t0->next_list = tr; } /* if */ assert( head_free != NULL ); assert( t1 == NULL || t1->next_list == NULL || t1->next_list->prev_list == t1 ); assert( t1 == NULL || t1->prev_list == NULL || t1->prev_list->next_list == t1 ); assert( tr->next_list == NULL || tr->next_list->prev_list == tr ); assert( tr->prev_list == NULL || tr->prev_list->next_list == tr ); assert( check_block( tr ) ); } /* add_free() */
static void angel_FreeToPool(int n) { angel_TaskQueueItem *my_tqi = &angel_TQ_Pool[n]; angel_TaskQueueItem *tqi, *l_tqi; if (ISFREE(n)) LogError(LOG_SERLOCK, ( "Attempt to deallocate free block %d.\n", n)); FREE(n); /* Now we find it on the queue and remove it */ for (tqi = angel_TaskQueueHead, l_tqi = NULL; (tqi != my_tqi && tqi != NULL);) { l_tqi = tqi; tqi = tqi->next; } if (tqi == NULL) { LogError(LOG_SERLOCK, ( "Block could not be dequeued (%d).\n", n)); return; } #ifdef DO_TRACE LogTrace(LOG_SERLOCK, "SFreePool: %d\n", n); #endif if (l_tqi == NULL) angel_TaskQueueHead = my_tqi->next; else l_tqi->next = my_tqi->next; my_tqi->next = NULL; }
void *qalloc(qarena_t *arena, unsigned size) { void *p = arena+1; void *end = (char *)arena + arena->size; void *n = NULL; size = RNDSZ(size); while (p && p < end) { if (!ISFREE(p) || BSZ(p) < size) { p = NX(p); continue; } if (BSZ(p) > size) { n = (char*)p + size; SZ(n) = SZ(p) - size; SZ(p) = size; } ALLOC(p); return UPTR(p); } return NULL; }
void CHeap1::Free( void* mem ) { Node* Tofree = (Node*)( (char*)mem - sizeof(Node) ); mem = NULL; if ( !CheckNode( Tofree ) ) { // This is not a vilide node, something wrong return; } // because sentinel is always exsit as a free node, so any node in freelist will at least has one p*Free != NULL #define ISFREE( node ) ( CheckNode( node ) && node->pPrevFree != NULL || node->pNextFree != NULL ) Node* Prev = Tofree->pPrevMem; Node* Next = Tofree->pNextMem; Node* node = Tofree; if ( Prev == pSentinel ) { if ( ISFREE( Next ) ) { node->pPrevFree = Next->pPrevFree; node->pNextFree = Next->pNextFree; Next->pPrevFree->pNextFree = node; if ( Next->pNextFree ) Next->pNextFree->pPrevFree = node; node->pNextMem = Next->pNextMem; if ( Next->pNextMem <= pHeapEnd ) node->pNextMem->pPrevMem = node; } else { Tofree->pNextFree = pSentinel->pNextFree; Tofree->pPrevFree = pSentinel; if ( pSentinel->pNextFree ) pSentinel->pNextFree->pPrevFree = Tofree; pSentinel->pNextFree = Tofree; } return; } if ( ISFREE( Prev ) && ISFREE( Next ) ) { // Prev and Next both in FreeList Next->pPrevFree->pNextFree = Next->pNextFree; if ( Next->pNextFree ) Next->pNextFree->pPrevFree = Next->pPrevFree; Prev->pNextMem = Next->pNextMem; if ( Next->pNextMem <= pHeapEnd ) Next->pNextMem->pPrevMem = Prev; } else if ( ISFREE( Prev ) ) { Prev->pNextMem = node->pNextMem; if ( node->pNextMem <= pHeapEnd ) node->pNextMem->pPrevMem = Prev; } else if ( ISFREE( Next ) ) { node->pPrevFree = Next->pPrevFree; node->pNextFree = Next->pNextFree; Next->pPrevFree->pNextFree = node; if ( Next->pNextFree ) Next->pNextFree->pPrevFree = node; node->pNextMem = Next->pNextMem; if ( Next->pNextMem <= pHeapEnd ) node->pNextMem->pPrevMem = node; } else { // merge failed Tofree->pNextFree = pSentinel->pNextFree; Tofree->pPrevFree = pSentinel; if ( pSentinel->pNextFree ) pSentinel->pNextFree->pPrevFree = Tofree; pSentinel->pNextFree = Tofree; } return; #undef ISFREE }
static int angel_AllocateFromPool(angel_TaskPriority pri, bool new_task, bool yielded) { int i; for (i = 0; i < POOLSIZE; i++) { if (ISFREE(i)) { angel_TaskQueueItem *my_tqi = &angel_TQ_Pool[i]; angel_TaskQueueItem *tqi, *l_tqi; #ifdef DO_TRACE LogTrace(LOG_SERLOCK, "SAllocPool: %d-p%d-n%d\n", i, pri, new_task); #endif ALLOC(i); /* Set up the priorities */ my_tqi->pri = pri; my_tqi->new_task = new_task; /* And insert the item into the queue. * which first involves finding a task of same priority and * inserting this task before it if not new, or after it if new. */ /* if new or yielded, ensure it goes after any exisiting entry at pri */ if (new_task || yielded) pri = (angel_TaskPriority) (pri - 1); for (tqi = angel_TaskQueueHead, l_tqi = NULL; (tqi != NULL) && (tqi->pri > pri);) { l_tqi = tqi; tqi = tqi->next; } /* We may have reached the end of the list, or we may not have */ my_tqi->next = tqi; if (l_tqi == NULL) angel_TaskQueueHead = my_tqi; else l_tqi->next = my_tqi; /* LogInfo(LOG_SERLOCK, ( "Allocated RegBlock %d\n",i)); */ return i; } } LogError(LOG_SERLOCK, ( "AllocateFromPool: No free RegBlock\n")); #if DEBUG == 1 /* * for (i = 0; i < POOLSIZE; i++) *{ * angel_TaskQueueItem *my_tqi = &angel_TQ_Pool[i]; * * LogWarning(LOG_SERLOCK, ( "Task %d: Pri=%d, New=%d, PC=%8x, PSR=%08x\n", * i, my_tqi->pri, my_tqi->new_task, * my_tqi->rb.r[15], my_tqi->rb.cpsr)); *} */ #endif return -1; }
/********************************************* * create new block of requested size by removing oldest memory blocks * block contents are not initialised * size is rounded up to exact nr longs * base for removed blocks is set to NULL * *pbase := adr of block, * or null if cache is unable to supply enough memory * return null */ void find_mem( uint32 rq_size, void **const base ) { register tMemHdr *tr; register tMemHdr *t0; register tMemHdr *t1; assert( head_mem != NULL ); /* there must be a cache !! */ assert( base != NULL ); assert( rq_size <= ((rq_size+3)&~3) ); assert( rq_size+4 > ((rq_size+3)&~3) ); rq_size = (rq_size+3)&~3; if(( rq_size > total_size) ) { /* request fails - it is too large for cache */ dprintf(( "requested mem (%ld) larger than cache size (%ld)\n", rq_size, total_size )); *base = NULL; return; } /* if */ /** loop to remove old data until there is enough free space for current request **/ dprintf(( "rq_size is %ld\n", (long)rq_size )); assert( head_free != NULL || total_free == 0 ); /* note the special case when total free == 0 (so head_free == NULL) ** and rq_size is 0. */ while( rq_size > total_free || total_free == 0 ) { dprintf(("need to remove lru data block(%ld), size (%ld)\n", (long)head_data->data[0], (long)head_data->size )); assert( head_data != NULL || rq_size <= total_free ); assert( total_free + total_used + (nr_blocks-1)*sizeof(tMemHdr) == total_size ); assert( head_data->prev_list == NULL ); release_block( head_data ); /* remove lru data block */ assert( head_data != NULL || rq_size <= total_free ); assert( head_data != NULL || total_used == 0 ); assert( head_data == NULL || head_data->prev_list == NULL); } /* while */ assert( total_free >= rq_size ); assert( head_free != NULL ); /********************************************************** * there is now enough space in the cache to fulfil the request * but it may need to be gathered together into one block * move all data blocks down to the start of the cache * this leaves one free block at the end of the cache **********************************************************/ if( head_free->size < rq_size ) { register uint32 *free_p; /** free space pointer **/ /* the memory is fragmented, so move all data down memory ** to concentrate the free mem into one block at the end ** note: fragmented ==> at least one data block & 2 free blocks */ #ifdef TEST conc++; dprintf(( "concentrating data...(this is the %ldth time)\n", conc )); #endif assert( head_data != NULL ); t1 = head_mem; while( ISDATA(t1) ) { assert( check_block(t1) ); assert( t1->next_mem != NULL ); /* there are at least two free blocks following */ t1 = t1->next_mem; } /* while */ assert( ISFREE(t1) ); free_p = (uint32*)t1; /* the first free area */ t0 = t1->prev_mem; /* the last data block so far, or NULL */ assert( t0 == NULL || check_block(t0) ); assert( t0 == NULL || ISDATA(t0) ); assert( t0 == NULL || (uint32*)free_p == (uint32*)(t0->next_mem) ); /** loop to copy data blocks down ** t1 scans thru mem blocks, ** t0 follows one behind, it is the latest concentrated block **/ do { assert( t1->magic == MAGIC ); /* t1->prev?? may have been overwritten */ if( ISDATA(t1) ) { register int32 i = t1->size + sizeof(tMemHdr); /* nr bytes to move */ register uint32 *s1 = (uint32*)t1; /* src address */ /**** ** move data block at t1 down to free_p, ** adjust t0 = new conc'd data block, adjust t1 *****/ assert( t0 == NULL || (uint32*)free_p == (uint32*)(t0->next_mem) ); tr = (tMemHdr*) free_p; /* relocate block pointer */ assert( tr != NULL ); assert( tr < t1 ); /* there is a gap between end of t0 & start of t1 */ t1 = t1->next_mem; /* data at t1 will be overwritten if data size > gap too free_p */ assert( (i&3) == 0 ); /* data & header both exact nr longs */ i >>= 2; /* nr longs */ while( --i >= 0 ) { /* copy header & data of block */ *free_p++ = *s1++; } /* if */ /* note: free_p now points to new free area, at end of tr */ assert( (uint32)tr->data + tr->size == (uint32)free_p ); *tr->pbase = tr->data; tr->next_mem = (tMemHdr*)free_p; /* adjust links */ tr->prev_mem = t0; assert( (t0 == NULL && tr == head_mem) || t0->next_mem == tr ); if( tr->next_list != NULL ) { tr->next_list->prev_list = tr; } else { tail_data = tr; } /* if */ if( tr->prev_list != NULL ) { tr->prev_list->next_list = tr; } else { head_data = tr; } /* if */ t0 = tr; assert( ISDATA(t0) ); assert( check_block(t0) ); assert( t0->prev_mem == NULL || t0->prev_mem->next_mem == t0); } else { nr_blocks--; /* removed a free block */ total_free += sizeof(tMemHdr); t1 = t1->next_mem; } /* if */ } while( t1 != NULL ); assert( t0 != NULL ); /** now create one free block at the end of the cache */ t1 = head_free = t0->next_mem; assert( head_free == (tMemHdr*)free_p ); t1->next_mem = t1->next_list = t1->prev_list = NULL; t1->prev_mem = t0; total_free -= sizeof(tMemHdr); assert( total_free == (uint32)head_mem + total_size - (uint32)t1); t1->size = total_free; t1->pbase = NULL; #ifndef NDEBUG t1->magic = MAGIC; t1->data[0] = -2; #endif nr_blocks++; assert( total_free + total_used + (nr_blocks-1)*sizeof(tMemHdr) == total_size ); } /* if */
/************************************************************* * move a block of memory from the data chain to the free chain * merge with next & previous blocks if possible */ static void release_block( register tMemHdr *tr ) { register tMemHdr *t0; register tMemHdr *t1; assert( tr == NULL || tr->next_mem == NULL || tr->next_mem->prev_mem == tr ); assert( tr == NULL || tr->prev_mem == NULL || tr->prev_mem->next_mem == tr ); assert( tr == NULL || tr->next_list == NULL || tr->next_list->prev_list == tr ); assert( tr == NULL || tr->prev_list == NULL || tr->prev_list->next_list == tr ); assert( check_block(tr) ); assert( ISDATA(tr) ); total_free += tr->size; total_used -= tr->size; *tr->pbase = NULL; /* tell application this block has been released */ tr->pbase = NULL; /* flag this block as free */ t0 = tr->prev_list; t1 = tr->next_list; if( t0 == NULL ) { head_data = t1; } else { t0->next_list = t1; } /* if */ if( t1 == NULL ) { tail_data = t0; } else { t1->prev_list = t0; } /* if */ /** block removed from data chain, now try merge with next, previous **/ t1 = tr->next_mem; if( t1 != NULL && ISFREE(t1) ) { /** we can absorb the next mem block **/ #ifdef TEST merged_next++; dprintf(( "merging block(%ld, size %ld) & following(%ld, size %ld)\n", (long)tr->data[0], (long)tr->size, (long)tr->next_mem->data[0], (long)tr->next_mem->size )); #endif rem_free( t1 ); /** remove next from free list **/ /** remove tr->next_mem from memory list **/ tr->size += t1->size + sizeof(tMemHdr); tr->next_mem = t0 = t1->next_mem; if( t0 != NULL ) { t0->prev_mem = tr; } /* if */ assert( tr->next_mem == NULL || tr->next_mem->prev_mem == tr ); assert( tr->next_mem == NULL || (uint32)tr + sizeof(tMemHdr) + tr->size == (uint32)tr->next_mem ); dprintf(( "size of merged block is %ld\n", (long)tr->size )); total_free += sizeof( tMemHdr ); nr_blocks--; } /* if */ assert( total_free + total_used + (nr_blocks-1)*sizeof(tMemHdr) == total_size ); t0 = tr->prev_mem; if( t0 != NULL && ISFREE(t0) ) { /** we can merge into the prev mem block **/ #ifdef TEST dprintf(( "merging block(%ld, size %ld) & previous(%ld, size %ld)\n", (long)tr->data[0], (long)tr->size, (long)tr->prev_mem->data[0], (long)tr->prev_mem->size )); merged_prev++; #endif rem_free( t0 ); /** remove prev from free list **/ /** remove tr from memory list **/ t1 = t0->next_mem = tr->next_mem; if( t1 != NULL ) { t1->prev_mem = t0; } /* if */ assert( t0->next_mem == NULL || t0->next_mem->prev_mem == t0 ); assert( t1 == NULL || t1->prev_mem->next_mem == t1 ); t0->size += tr->size + sizeof( tMemHdr ); total_free += sizeof( tMemHdr ); nr_blocks--; tr = t0; /* tr is adr of merged block */ dprintf(( "size of merged block is %ld\n", (long)tr->size )); assert( tr->next_mem == NULL || (uint32)tr + sizeof(tMemHdr) + tr->size == (uint32)tr->next_mem ); assert( tr->next_mem == NULL || tr->next_mem->prev_mem == tr); } /* if */ assert( total_free + total_used + (nr_blocks-1)*sizeof(tMemHdr) == total_size ); add_free( tr ); assert( check_cache() ); } /* release_block() */
static int check_cache( void ) { int result = 1; uint16 nd, nd1; uint16 nf, nf1; uint32 tf, tf1; uint32 td, td1; tMemHdr *t; /** run thru mem list ... */ nd1= nf1 = 0; tf1 = td1 = 0; t = head_mem; if( t == NULL ) { dprintf(( "head_mem is NULL!!, cache doesn't exist\n" )); return 1; } /* if */ while( t != NULL ) { if( check_block(t) == 0 ) result = 0; if( ISDATA(t) ) { nd1++; td1 += t->size; } else { nf1++; tf1 += t->size; } /* if */ t->magic = 0; if( t->next_mem != NULL && (uint32)(t+1) + t->size != (uint32)t->next_mem ) { dprintf(( "memory block(%ld) & next are not contiguous\n", (long)t->data[0] )); result = 0; } /* if */ if( t->prev_mem != NULL && (uint32)(t->prev_mem+1) + t->prev_mem->size != (uint32)t ) { dprintf(( "memory block(%ld) & prev are not contiguous\n", (long)t->data[0] )); result = 0; } /* if */ if( t->next_mem != NULL && t->next_mem->prev_mem != t) { dprintf(( "memory block(%ld) next doesn't link back\n", (long)t->data[0] )); result = 0; } /* if */ if( t->prev_mem != NULL && t->prev_mem->next_mem != t) { dprintf(( "memory block(%ld) prev doesn't link back\n", (long)t->data[0] )); result = 0; } /* if */ if( t->next_mem == NULL && (uint32)(t+1) + t->size != (uint32)(head_mem+1) + total_size ) { dprintf(( "last memory block(%ld) in wrong place\n", (long)t->data[0] )); result = 0; } /* if */ t = t->next_mem; } /* while */ if( nd1 + nf1 != nr_blocks ) { dprintf(( "nr_blocks count is %d, counted %d\n", nr_blocks, nd1+nf1 )); result = 0; } /* if */ if( tf1 != total_free ) { dprintf(( "total_free is %ld, counted %ld\n", total_free, tf1 )); result = 0; } /* if */ /** run thru free list ... */ nf = 0; tf = 0; t = head_free; while( t != NULL ) { nf++; tf += t->size; if( t->magic != 0 ) { dprintf(( "memory block(%ld) in free list, not in mem list\n", (long)t->data[0] )); result = 0; } /* if */ t->magic = MAGIC; if( !ISFREE(t) ) { dprintf(( "free memory block(%ld) marked as data\n", (long)t->data[0] )); result = 0; } /* if */ if( t->next_list != NULL && t->next_list->size > t->size ) { dprintf(( "free memory block(%ld) smaller than next\n", (long)t->data[0] )); result = 0; } /* if */ if( t->prev_list != NULL && t->prev_list->size < t->size ) { dprintf(( "free memory block(%ld) larger than prev\n", (long)t->data[0] )); result = 0; } /* if */ if( t->prev_list != NULL && t->prev_list->next_list != t ) { dprintf(( "free memory block(%ld) doesn't link back\n", (long)t->data[0] )); result = 0; } /* if */ if( t->next_list != NULL && t->next_list->prev_list != t ) { dprintf(( "free memory block(%ld) doesn't link forward\n", (long)t->data[0] )); result = 0; } /* if */ t = t->next_list; } /* while */ if( nf != nf1 ) { dprintf(( "miscounted free blocks, mem chain ==> %d, free list ==> %d\n", nf1, nf )); result = 0; } /* if */ if( tf != tf1 ) { dprintf(( "miscounted free mem, mem chain ==> %ld, free list ==> %ld\n", tf1, tf )); result = 0; } /* if */ if( tf != total_free ) { dprintf(( "total_free is %ld, counted %ld\n", total_free, tf )); result = 0; } /* if */ /** run thru data list ... */ nd = 0; td = 0; t = head_data; if( (head_data == NULL) != (tail_data == NULL) ) { dprintf(( "head_data & tail_data disagree\n" )); result = 0; } /* if */ while( t != NULL ) { nd++; td += t->size; if( t->magic != 0 ) { dprintf(( "memory block(%ld) in data list, not in mem list\n", (long)t->data[0] )); result = 0; } /* if */ t->magic = MAGIC; if( ISFREE(t) ) { dprintf(( "data memory block(%ld) marked as free\n", (long)t->data[0] )); result = 0; } /* if */ if( t->prev_list == NULL && t != head_data ) { dprintf(( "block(%ld) with null prev link not at head\n", (long)t->data[0] )); result = 0; } /* if */ if( t->next_list == NULL && t != tail_data ) { dprintf(( "block(%ld) with null next link not at tail\n", (long)t->data[0] )); result = 0; } /* if */ if( t->prev_list != NULL && t->prev_list->next_list != t ) { dprintf(( "data memory block(%ld) doesn't link back\n", (long)t->data[0] )); result = 0; } /* if */ if( t->next_list != NULL && t->next_list->prev_list != t ) { dprintf(( "data memory block(%ld) doesn't link forward\n", (long)t->data[0] )); result = 0; } /* if */ if( *t->pbase != t->data ) { dprintf(( "base block(%ld) doesn't link to data\n", (long)t->data[0] )); result = 0; } /* if */ t = t->next_list; } /* while */ if( nd != nd1 ) { dprintf(( "miscounted data blocks, mem chain ==> %d, free list ==> %d\n", nd1, nd )); result = 0; } /* if */ if( td != td1 ) { dprintf(( "miscounted data mem, mem chain ==> %ld, free list ==> %ld\n", td1, td )); result = 0; } /* if */ if( td != total_used ) { dprintf(( "total_used is %ld, counted %ld\n", total_used, td )); result = 0; } /* if */ if( nd+nf != nr_blocks ) { dprintf(( "lost blocks, nr blocks is %d, nd is %d, nf is %d\n", nr_blocks, nd, nf )); result = 0; } /* if */ t = head_mem; while( t != NULL ) { if( t->magic != MAGIC ) { dprintf(( "memory block(%ld) is lost\n", (long)t->data[0] )); result = 0; } /* if */ t = t->next_mem; } /* while */ return result; } /* check_cache() */
/************************************** * functions to check block and cache for consistency * return 1 if OK, 0 if failure found */ static int check_block( tMemHdr *t ) { int result = 1; if( t == NULL ) { dprintf(( "memory block is NULL\n" )); return head_mem == NULL; } /* if */ if( t->magic != MAGIC ) { dprintf(("memory block(%ld) has no magic number\n", (long)t->data[0] )); result = 0; } /* if */ if( (t->size & 3) != 0 ) { dprintf(("memory block(%ld) size is %ld, sb exact nr longs\n", (long)t->data[0], (long)t->size )); result = 0; } /* if */ if( t->size > total_size ) { dprintf(("memory block(%ld) size is out of range (%ld)\n", (long)t->data[0], (long)t->size )); result = 0; } /* if */ if( t->next_mem != NULL && t->next_mem < t + 1 ){ dprintf(("memory block(%ld) next mem is wrong\n", (long)t->data[0] )); result = 0; } /* if */ if( t->prev_mem != NULL && t->prev_mem >= t ){ dprintf(("memory block(%ld) prev mem is wrong\n", (long)t->data[0] )); result = 0; } /* if */ if( t->next_mem != NULL && (uint32)t->data + t->size != (uint32)t->next_mem ){ dprintf(("memory block(%ld) size and next are inconsistent\n", (long)t->data[0] )); result = 0; } /* if */ #if 0 // if( t->next_mem != NULL && t->next_mem->prev_mem != t) { // dprintf(("memory block(%ld) next doesn't link back\n", (long)t->data[0] )); // } /* if */ // if( t->prev_mem != NULL && t->next_mem->prev_mem != t) { // dprintf(("memory block(%ld) prev doesn't link back\n", (long)t->data[0] )); // } /* if */ #endif if( ISDATA(t) ) { if( t->next_list == NULL && t != tail_data ) { dprintf(("memory block(%ld) is at end of data list, but doesn't match tail_data\n", (long)t->data[0] )); result = 0; } /* if */ if( t->prev_list == NULL && t != head_data ) { dprintf(("memory block(%ld) is at head of data list, but doesn't match head_data\n", (long)t->data[0] )); result = 0; } /* if */ if( *t->pbase == NULL ) { dprintf(("memory block(%ld) contains data, but *pbase is NULL\n", (long)t->data[0] )); result = 0; } /* if */ } else { if( (t->next_mem != NULL) && ISFREE(t->next_mem) ) { dprintf(("memory block(%ld) is free and so is next block\n", (long)t->data[0] )); result = 0; } /* if */ if( (t->prev_mem != NULL) && ISFREE(t->prev_mem) ) { dprintf(("memory block(%ld) is free and so is prev block\n", (long)t->data[0] )); result = 0; } /* if */ if( (t->prev_list != NULL) && (t->size > t->prev_list->size) ) { dprintf(("memory block(%ld) is larger than next in free list\n", (long)t->data[0] )); result = 0; } /* if */ if( (t->next_list != NULL) && (t->size < t->next_list->size) ) { dprintf(("memory block(%ld) is smaller than prev in free list\n", (long)t->data[0] )); result = 0; } /* if */ } /* if */ return result; } /* check_block() */
int _RTLENTRY _EXPFUNC _heapchk(void) { int rc; HEAP *h; BLOCKHDR *bh; int fnum1 = 0; int fnum2 = 0; int commitSum = 0; int _roverFound = 0; _lock_heap(); if (!_firstHeap) RETURN(_HEAPEMPTY); for (h = _firstHeap; h; h = h->nextHeap) { if (__memBogusAddr (h)) { RETURN(_HEAPCORRUPT); } commitSum += h->cSize; for (bh = FIRSTBLOCK(h); HDR2PTR(bh) != ((char *) h + h->cSize); bh = NEXT(bh)) { void *p = HDR2PTR(bh); if (__memBogusAddr (bh)) { RETURN(_HEAPCORRUPT); } if (p < h || p > (char *) h + h->cSize) { #ifdef DBG char buf[80]; wsprintf(buf, "Block out of range block[%08X] heap[%08X]", p, h); DBG_MAC (buf); #endif RETURN(_HEAPCORRUPT); } if (ISFREE(bh)) { if (__memBogusAddr(NEXT(bh))) { RETURN(_HEAPCORRUPT); } if (!ISPFREE(NEXT(bh))) { #ifdef DBG DBG_MAC("prev free bit missing"); #endif RETURN(_HEAPCORRUPT); } if (PFREE(NEXT(bh)) != bh) { #ifdef DBG DBG_MAC("free backlink broken"); #endif RETURN(_HEAPCORRUPT); } fnum1++; } } } if (commitSum != __allocated) { #ifdef DBG DBG_MAC("allocated number is off!!!"); #endif RETURN(_HEAPCORRUPT); } if (_linktable) { size_t i; for (i = MINSIZE; i < _smalloc_threshold; i += ALIGNMENT) { BLOCKHDR *p = HDR4SIZE(i); if (__memBogusAddr(p)) { RETURN(_HEAPCORRUPT); } for (bh = p->nextFree; bh != p; bh = bh->nextFree) { if (__memBogusAddr(bh)) { RETURN(_HEAPCORRUPT); } if (__memBogusAddr(bh->nextFree)) { RETURN(_HEAPCORRUPT); } if (bh->nextFree->prevFree != bh) { #ifdef DBG DBG_MAC("free list error"); #endif RETURN(_HEAPCORRUPT); } if (SIZE(bh) != i) { #ifdef DBG DBG_MAC("bad size block in small free list"); #endif RETURN(_HEAPCORRUPT); } if (!ISPFREE(NEXT(bh))) { #ifdef DBG DBG_MAC("bad block in free list"); #endif RETURN(_HEAPCORRUPT); } if (PFREE(NEXT(bh)) != bh) { #ifdef DBG DBG_MAC("bad block in free list"); #endif RETURN(_HEAPCORRUPT); } fnum2++; } } for (bh = _freeStart.nextFree; bh != &_freeStart; bh = bh->nextFree) { if (__memBogusAddr(bh)) { RETURN(_HEAPCORRUPT); } if (__memBogusAddr(bh->nextFree)) { RETURN(_HEAPCORRUPT); } if (bh->nextFree->prevFree != bh) { #ifdef DBG DBG_MAC("free list error"); #endif RETURN(_HEAPCORRUPT); } if (SIZE(bh) < _smalloc_threshold) { #ifdef DBG DBG_MAC("small block in big free list"); #endif RETURN(_HEAPCORRUPT); } if (!ISPFREE(NEXT(bh))) { #ifdef DBG DBG_MAC("bad block in free list"); #endif RETURN(_HEAPCORRUPT); } if (PFREE(NEXT(bh)) != bh) { #ifdef DBG DBG_MAC("bad block in free list"); #endif RETURN(_HEAPCORRUPT); } fnum2++; if (bh == _rover) _roverFound = 1; } } if (!_roverFound && &_freeStart != _rover) { #ifdef DBG DBG_MAC("_rover not in free list!"); #endif RETURN(_HEAPCORRUPT); } if (fnum1 != fnum2) { #ifdef DBG DBG_MAC("Free block number mismatch"); #endif RETURN(_HEAPCORRUPT); } rc = _HEAPOK; exit: _unlock_heap(); return rc; }