void __cdecl _free_base ( #endif /* _MT */ REG1 void *pblock ) { REG2 _PBLKDESC pdesc; /* * If the pointer is NULL, just return [ANSI]. */ if (pblock == NULL) return; /* * Point to block header and get the pointer back to the heap desc. */ pblock = (char *)pblock - _HDRSIZE; pdesc = *(_PBLKDESC*)pblock; /* * Validate the back pointer. */ if (_ADDRESS(pdesc) != pblock) _heap_abort(); /* * Pointer is ok. Mark block free. */ _SET_FREE(pdesc); /* * Check for special conditions under which the rover is reset. */ if ( (_heap_resetsize != 0xffffffff) && (_heap_desc.proverdesc->pblock > pdesc->pblock) && (_BLKSIZE(pdesc) >= _heap_resetsize) ) { _heap_desc.proverdesc = pdesc; } #if !defined (_M_MPPC) && !defined (_M_M68K) else if ( _heap_desc.proverdesc == pdesc->pnextdesc ) { _heap_desc.proverdesc = pdesc; } #endif /* !defined (_M_MPPC) && !defined (_M_M68K) */ }
void __cdecl _heap_print_heaplist(void) { _PBLKDESC p; _PBLKDESC next; int i; int error = 0; printf("\n--- Heap Descriptor List ---\n\n"); if ((p = _heap_desc.pfirstdesc) == NULL) { printf("\t *** List is empty ***\n"); return; } for (i=1; p != NULL; i++) { next = p->pnextdesc; /* Print descriptor address */ printf("\t(%i) Address = %p ", i, p); if (p == &_heap_desc.sentinel) printf("<SENTINEL>\n"); else if (p == _heap_desc.proverdesc) printf("<ROVER>\n"); else printf("\n"); /* Print descriptor contents */ printf("\t\tpnextdesc = %p, pblock = %p", p->pnextdesc, p->pblock); if (p == &_heap_desc.sentinel) { if (next != NULL) { printf("\n\t*** ERROR: sentinel.pnextdesc != NULL ***\n"); error++; } } else if (_IS_INUSE(p)) printf(", usersize = %u <INUSE>", _BLKSIZE(p)); else if (_IS_FREE(p)) printf(", usersize = %u <FREE>", _BLKSIZE(p)); else if (_IS_DUMMY(p)) printf(", size = %u <DUMMY>", _MEMSIZE(p)); else { printf(",\n\t*** ERROR: unknown status ***\n"); error++; } printf("\n\n"); if (_heap_desc.pfirstdesc == &_heap_desc.sentinel) { printf("[No memory in heap]\n"); } p = next; } if (error) printf("\n\t *** ERRORS IN HEAP TABLE ***\n"); printf("\t--- End of table ---\n"); }
_CRTIMP size_t __cdecl _heapused(size_t *pUsed, size_t *pCommit) #endif /* _MT */ { _PBLKDESC p; _PBLKDESC next; int index ; size_t usedbytes; /* bytes devoted to in-use blocks */ size_t freebytes; /* bytes devoted to free blocks */ size_t rsrvbytes; /* total bytes of reserved address space */ void * * pageptr ; if ( (p = _heap_desc.pfirstdesc) == NULL || _heap_desc.pfirstdesc == &_heap_desc.sentinel ) { return 0 ; /* invalid heap */ } /* * Scan through the heap, counting free and used blocks. * Include the overhead of each block and its heap descriptor. */ freebytes = 0 ; usedbytes = 0 ; while (p != NULL) { next = p->pnextdesc; if (p == &_heap_desc.sentinel) { if (next != NULL) { return 0 ; } } else if (_IS_FREE(p)) { freebytes += _BLKSIZE(p) + _HDRSIZE; } else if (_IS_INUSE(p)) { usedbytes += _BLKSIZE(p) + _HDRSIZE; } p = next; } /* * Now we need to count the pages used for descriptors as reserved memory. * _heap_descpages points to the head of a singly-linked list of the pages. * The descriptors for in-use blocks are considered in-use memory. */ pageptr = _heap_descpages; rsrvbytes = 0 ; while ( pageptr ) { rsrvbytes += _HEAP_EMPTYLIST_SIZE ; pageptr = * pageptr ; } usedbytes += rsrvbytes ; /* * Loop through the region descriptor table */ for ( index=0 ; index < _HEAP_REGIONMAX ; index++ ) { rsrvbytes += _heap_regions[index]._totalsize ; } if ( pUsed ) * pUsed = usedbytes ; if ( pCommit ) * pCommit = freebytes + usedbytes ; return rsrvbytes ; }
int __cdecl _heap_addblock ( void * block, size_t size ) { _PBLKDESC pdesc; REG1 _PBLKDESC pnewdesc; _PBLKDESC pdescs[4] = { NULL, NULL, NULL, NULL }; _PBLKDESC *ppdesc = pdescs; size_t lastsize; int find; /* * Make sure we enough empty descriptors to do the job! Do it here * and now because recovering from an out-of-descriptors condition * is too dicey later on. */ if ( ((pdescs[0] = __getempty()) == NULL) || ((pdescs[1] = __getempty()) == NULL) || ((pdescs[2] = __getempty()) == NULL) ) { goto error; } /* * Find where the address fits into the heap. */ find = _heap_findaddr(block, &pdesc); /* * Fill in the new heap descriptor. * (1) If the new address is an exact fit, use the dummy * descriptor that already exists for it. * (2) If the address is NOT in the heap, allocate a new one. */ if ( find == _HEAPFIND_EXACT ) { if ( !(_IS_DUMMY(pdesc)) ) goto error; pnewdesc = pdesc; } else { pnewdesc = *(ppdesc++); } pnewdesc->pblock = block; /* pointer to block */ _SET_FREE(pnewdesc); /* set me free (why don't ya, babe) */ *(_PBLKDESC*)block = pnewdesc; /* init back pointer */ /* * Put the block in the heap * find = result of _heap_findaddr() call * pnewdesc = points to desc to be inserted * pdesc = filled in by _heap_findaddr() call as appropriate */ switch (find) { case(_HEAPFIND_EMPTY): /* * No memory in heap yet */ _heap_desc.sentinel.pblock = (char *) block + size; _before(pnewdesc, size, &_heap_desc.sentinel, &ppdesc); _heap_desc.pfirstdesc = _heap_desc.proverdesc = pnewdesc; break; case(_HEAPFIND_BEFORE): /* * New block is before the heap */ _before(pnewdesc, size, _heap_desc.pfirstdesc, &ppdesc); _heap_desc.pfirstdesc = pnewdesc; break; case(_HEAPFIND_AFTER): /* * New block is after the heap * * Find the current last block in the heap */ if ( _heap_findaddr((void *)((char *) (_heap_desc.sentinel.pblock) - 1), &pdesc) != _HEAPFIND_WITHIN ) _heap_abort(); lastsize = _MEMSIZE(pdesc); /* * Start insertion by placing new block immediately * in front of the sentinel */ _heap_desc.sentinel.pblock = (char *) block + size; pnewdesc->pnextdesc = &_heap_desc.sentinel; /* * Finish insertion by placing new block after the * old last block (with a possible intervening dummy * block being created) */ _before(pdesc, lastsize, pnewdesc, &ppdesc); break; case(_HEAPFIND_EXACT): /* * Block is already in the heap (and we've checked * that it was a "dummy" before this call). * * [NOTES: (1) pnewdesc and pdesc are the same, * (2) pnewdesc is already linked to the previous * heap entry, (3) pdesc->pnextdesc is still valid! * (4) Also, if pdesc->pnextdesc is the sentinel, * then simply update the sentinel size (calling * before will cause an error if the previous last * block was bigger than the current one!). * (see code at top of this routine).] */ if (pdesc->pnextdesc == &_heap_desc.sentinel) _heap_desc.sentinel.pblock = (char *) _ADDRESS(pdesc) + size; else _before(pnewdesc, size, pdesc->pnextdesc, &ppdesc); break; default: /* * New block is within heap */ if (!(_IS_DUMMY(pdesc))) goto error; /* * If the last block in the heap is a dummy region * and a new region is allocated which lies within * that region, we need to update sentinel.pblock. */ if (pdesc->pnextdesc == &_heap_desc.sentinel) { void * newend = (char *) _ADDRESS(pnewdesc) + size; if (_heap_desc.sentinel.pblock < newend) _heap_desc.sentinel.pblock = newend; } _before(pnewdesc, size, pdesc->pnextdesc, &ppdesc); _before(pdesc, _MEMSIZE(pdesc), pnewdesc, &ppdesc); break; } /* * Update rover, if appropriate */ if ( (block < _ADDRESS(_heap_desc.proverdesc)) && (_BLKSIZE(pnewdesc) >= _heap_resetsize) ) _heap_desc.proverdesc = pnewdesc; /* * Good return */ /* good: unreferenced label to be removed */ return(0); /* * Error return */ error: while ( *ppdesc != NULL ) { _PUTEMPTY(*ppdesc); ppdesc++; } return(-1); }
static int __cdecl _heap_checkset ( unsigned int _fill ) { REG1 _PBLKDESC pdesc; REG2 _PBLKDESC pnext; int roverfound=0; int retval = _HEAPOK; /* * lock the heap */ _mlock(_HEAP_LOCK); /* * Validate the sentinel */ if (_heap_desc.sentinel.pnextdesc != NULL) { _PRINTERR(_BADSENTINEL); retval = _HEAPBADNODE; goto done; } /* * Test for an empty heap */ if ( (_heap_desc.pfirstdesc == &_heap_desc.sentinel) && (_heap_desc.proverdesc == &_heap_desc.sentinel) ) { retval = _HEAPEMPTY; goto done; } /* * Get and validate the first descriptor */ if ((pdesc = _heap_desc.pfirstdesc) == NULL) { _PRINTERR(_EMPTYHEAP); retval = _HEAPBADBEGIN; goto done; } /* * Walk the heap descriptor list */ while (pdesc != &_heap_desc.sentinel) { /* * Make sure address for this entry is in range. */ if ( (_ADDRESS(pdesc) < _ADDRESS(_heap_desc.pfirstdesc)) || (_ADDRESS(pdesc) > _heap_desc.sentinel.pblock) ) { _PRINTERR(_BADRANGE); retval = _HEAPBADNODE; goto done; } pnext = pdesc->pnextdesc; /* * Make sure the blocks corresponding to pdesc and pnext are * in proper order. */ if ( _ADDRESS(pdesc) >= _ADDRESS(pnext) ) { _PRINTERR(_BADORDER); retval = _HEAPBADNODE; goto done; } /* * Check the backpointer. */ if (_IS_INUSE(pdesc) || _IS_FREE(pdesc)) { if (!_CHECK_PDESC(pdesc)) { retval = _HEAPBADPTR; goto done; } } /* * Check for proverdesc */ if (pdesc == _heap_desc.proverdesc) roverfound++; /* * If it is free, fill it in if appropriate */ if ( _IS_FREE(pdesc) && (_fill != _HEAP_NOFILL) ) memset( (void *)((unsigned)_ADDRESS(pdesc)+_HDRSIZE), _fill, _BLKSIZE(pdesc) ); /* * Onto the next block */ pdesc = pnext; } /* * Make sure we found 1 and only 1 rover */ if (_heap_desc.proverdesc == &_heap_desc.sentinel) roverfound++; if (roverfound != 1) { _PRINTERR(_BADROVER); retval = _HEAPBADBEGIN; goto done; } /* * Walk the empty list. We can't really compare values against * anything but we may loop forever or may cause a fault. */ pdesc = _heap_desc.emptylist; while (pdesc != NULL) { pnext = pdesc->pnextdesc; /* * Header should only appear once */ if (pnext == _heap_desc.emptylist) { _PRINTERR(_EMPTYLOOP) retval = _HEAPBADPTR; goto done; } pdesc = pnext; } /* * Common return */ done: /* * release the heap lock */ _munlock(_HEAP_LOCK); return(retval); }