297 lines
7.9 KiB
C
297 lines
7.9 KiB
C
|
/***
|
||
|
*free.c - free an entry in the heap
|
||
|
*
|
||
|
* Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved.
|
||
|
*
|
||
|
*Purpose:
|
||
|
* Defines the following functions:
|
||
|
* free() - free a memory block in the heap
|
||
|
*
|
||
|
*Revision History:
|
||
|
* 06-30-89 JCR Module created
|
||
|
* 07-07-89 GJF Fixed test for resetting proverdesc
|
||
|
* 11-10-89 GJF Added MTHREAD support. Also, a little cleanup.
|
||
|
* 12-18-89 GJF Change header file name to heap.h, added register
|
||
|
* declarations and added explicit _cdecl to function
|
||
|
* definitions
|
||
|
* 03-09-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
|
||
|
* <cruntime.h> and removed #include <register.h>.
|
||
|
* 09-27-90 GJF New-style function declarators. Also, rewrote expr.
|
||
|
* so that a cast was not used as an lvalue.
|
||
|
* 03-05-91 GJF Changed strategy for rover - old version available
|
||
|
* by #define-ing _OLDROVER_.
|
||
|
* 04-08-91 GJF Temporary hack for Win32/DOS folks - special version
|
||
|
* of free that just calls HeapFree. Change conditioned
|
||
|
* on _WIN32DOS_.
|
||
|
* 04-06-93 SKS Replace _CRTAPI* with __cdecl
|
||
|
* 11-12-93 GJF Incorporated Jonathan Mark's suggestion for reducing
|
||
|
* fragmentation: if the block following the newly freed
|
||
|
* block is the rover block, reset the rover to the
|
||
|
* newly freed block. Also, replaced MTHREAD with _MT
|
||
|
* and deleted obsolete WIN32DOS support.
|
||
|
* 05-19-94 GJF Added __mark_block_as_free() for the sole use by
|
||
|
* __dllonexit() in the Win32s version of msvcrt*.dll.
|
||
|
* 06-06-94 GJF Removed __mark_block_as_free()!
|
||
|
* 11-03-94 CFW Debug heap support.
|
||
|
* 12-01-94 CFW Simplify debug interface.
|
||
|
* 01-12-95 GJF Fixed bogus test to reset rover. Also, purged
|
||
|
* _OLDROVER_ code.
|
||
|
* 02-01-95 GJF #ifdef out the *_base names for the Mac builds
|
||
|
* (temporary).
|
||
|
* 02-09-95 GJF Restored *_base names.
|
||
|
* 04-30-95 GJF Made conditional on WINHEAP.
|
||
|
* 03-01-96 GJF Added support fro small-block heap.
|
||
|
* 04-10-96 GJF Return type of __sbh_find_block and __sbh_free_block
|
||
|
* changed to __map_t *.
|
||
|
* 05-30-96 GJF Minor changes for latest version of small-block heap.
|
||
|
* 05-22-97 RDK New small-block heap scheme implemented.
|
||
|
* 09-26-97 BWT Fix POSIX
|
||
|
* 11-05-97 GJF Small POSIX fix from Roger Lanser.
|
||
|
* 12-17-97 GJF Exception-safe locking.
|
||
|
* 05-22-98 JWM Support for KFrei's RTC work.
|
||
|
* 07-28-98 JWM RTC update.
|
||
|
* 09-29-98 GJF Bypass all small-block heap code when __sbh_initialized
|
||
|
* is 0.
|
||
|
* 11-16-98 GJF Merged in VC++ 5.0 version of small-block heap.
|
||
|
* 05-01-99 PML Disable small-block heap for Win64.
|
||
|
* 05-17-99 PML Remove all Macintosh support.
|
||
|
* 05-26-99 KBF Updated RTC hook func params
|
||
|
* 06-22-99 GJF Removed old small-block heap from static libs.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#ifdef WINHEAP
|
||
|
|
||
|
#include <cruntime.h>
|
||
|
#include <malloc.h>
|
||
|
#include <winheap.h>
|
||
|
#include <windows.h>
|
||
|
#include <internal.h>
|
||
|
#include <mtdll.h>
|
||
|
#include <dbgint.h>
|
||
|
#include <rtcsup.h>
|
||
|
|
||
|
/***
|
||
|
*void free(pblock) - free a block in the heap
|
||
|
*
|
||
|
*Purpose:
|
||
|
* Free a memory block in the heap.
|
||
|
*
|
||
|
* Special ANSI Requirements:
|
||
|
*
|
||
|
* (1) free(NULL) is benign.
|
||
|
*
|
||
|
*Entry:
|
||
|
* void *pblock - pointer to a memory block in the heap
|
||
|
*
|
||
|
*Return:
|
||
|
* <void>
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
void __cdecl _free_base (void * pBlock)
|
||
|
{
|
||
|
#ifdef _POSIX_
|
||
|
HeapFree(_crtheap,
|
||
|
0,
|
||
|
pBlock
|
||
|
);
|
||
|
#else /* _POSIX_ */
|
||
|
|
||
|
#ifdef HEAPHOOK
|
||
|
/* call heap hook if installed */
|
||
|
if (_heaphook)
|
||
|
{
|
||
|
if ((*_heaphook)(_HEAP_FREE, 0, pBlock, NULL))
|
||
|
return;
|
||
|
}
|
||
|
#endif /* HEAPHOOK */
|
||
|
|
||
|
if (pBlock == NULL)
|
||
|
return;
|
||
|
|
||
|
RTCCALLBACK(_RTC_Free_hook, (pBlock, 0));
|
||
|
|
||
|
#ifndef _WIN64
|
||
|
if ( __active_heap == __V6_HEAP )
|
||
|
{
|
||
|
PHEADER pHeader;
|
||
|
|
||
|
#ifdef _MT
|
||
|
_mlock( _HEAP_LOCK );
|
||
|
__try {
|
||
|
#endif
|
||
|
|
||
|
if ((pHeader = __sbh_find_block(pBlock)) != NULL)
|
||
|
__sbh_free_block(pHeader, pBlock);
|
||
|
|
||
|
#ifdef _MT
|
||
|
}
|
||
|
__finally {
|
||
|
_munlock( _HEAP_LOCK );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (pHeader == NULL)
|
||
|
HeapFree(_crtheap, 0, pBlock);
|
||
|
}
|
||
|
#ifdef CRTDLL
|
||
|
else if ( __active_heap == __V5_HEAP )
|
||
|
{
|
||
|
__old_sbh_region_t *preg;
|
||
|
__old_sbh_page_t * ppage;
|
||
|
__old_page_map_t * pmap;
|
||
|
#ifdef _MT
|
||
|
_mlock(_HEAP_LOCK );
|
||
|
__try {
|
||
|
#endif
|
||
|
|
||
|
if ( (pmap = __old_sbh_find_block(pBlock, &preg, &ppage)) != NULL )
|
||
|
__old_sbh_free_block(preg, ppage, pmap);
|
||
|
|
||
|
#ifdef _MT
|
||
|
}
|
||
|
__finally {
|
||
|
_munlock(_HEAP_LOCK );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (pmap == NULL)
|
||
|
HeapFree(_crtheap, 0, pBlock);
|
||
|
}
|
||
|
#endif /* CRTDLL */
|
||
|
else // __active_heap == __SYSTEM_HEAP
|
||
|
#endif /* ndef _WIN64 */
|
||
|
{
|
||
|
HeapFree(_crtheap, 0, pBlock);
|
||
|
}
|
||
|
#endif /* _POSIX_ */
|
||
|
}
|
||
|
|
||
|
|
||
|
#else /* ndef WINHEAP */
|
||
|
|
||
|
|
||
|
#include <cruntime.h>
|
||
|
#include <heap.h>
|
||
|
#include <malloc.h>
|
||
|
#include <mtdll.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <dbgint.h>
|
||
|
|
||
|
/***
|
||
|
*void free(pblock) - free a block in the heap
|
||
|
*
|
||
|
*Purpose:
|
||
|
* Free a memory block in the heap.
|
||
|
*
|
||
|
* Special Notes For Multi-thread: The non-multi-thread version is renamed
|
||
|
* to _free_lk(). The multi-thread free() simply locks the heap, calls
|
||
|
* _free_lk(), then unlocks the heap and returns.
|
||
|
*
|
||
|
*Entry:
|
||
|
* void *pblock - pointer to a memory block in the heap
|
||
|
*
|
||
|
*Return:
|
||
|
* <void>
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#ifdef _MT
|
||
|
|
||
|
void __cdecl _free_base (
|
||
|
void *pblock
|
||
|
)
|
||
|
{
|
||
|
/* lock the heap
|
||
|
*/
|
||
|
_mlock(_HEAP_LOCK);
|
||
|
|
||
|
/* free the block
|
||
|
*/
|
||
|
_free_base_lk(pblock);
|
||
|
|
||
|
/* unlock the heap
|
||
|
*/
|
||
|
_munlock(_HEAP_LOCK);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***
|
||
|
*void _free_lk(pblock) - non-locking form of free
|
||
|
*
|
||
|
*Purpose:
|
||
|
* Same as free() except that no locking is performed
|
||
|
*
|
||
|
*Entry:
|
||
|
* See free
|
||
|
*
|
||
|
*Return:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
void __cdecl _free_base_lk (
|
||
|
|
||
|
#else /* ndef _MT */
|
||
|
|
||
|
void __cdecl _free_base (
|
||
|
|
||
|
#endif /* _MT */
|
||
|
|
||
|
REG1 void *pblock
|
||
|
)
|
||
|
{
|
||
|
REG2 _PBLKDESC pdesc;
|
||
|
|
||
|
#ifdef HEAPHOOK
|
||
|
/* call heap hook if installed */
|
||
|
if (_heaphook) {
|
||
|
if ((*_heaphook)(_HEAP_FREE, 0, pblock, NULL))
|
||
|
return;
|
||
|
}
|
||
|
#endif /* HEAPHOOK */
|
||
|
|
||
|
/*
|
||
|
* 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;
|
||
|
}
|
||
|
else if ( _heap_desc.proverdesc == pdesc->pnextdesc )
|
||
|
{
|
||
|
_heap_desc.proverdesc = pdesc;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif /* WINHEAP */
|