static void free_locked(void * address) { Slot * slot; Slot * previousSlot = 0; Slot * nextSlot = 0; if ( address == 0 ) return; if ( !noAllocationListProtection ) Page_AllowAccess(allocationList, allocationListSize); slot = slotForUserAddress(address); if ( !slot ) EF_Abort("free(%a): address not from malloc().", address); if ( slot->mode != ALLOCATED ) { if ( internalUse && slot->mode == INTERNAL_USE ) /* Do nothing. */; else { EF_Abort( "free(%a): freeing free memory." ,address); } } if ( EF_PROTECT_FREE ) slot->mode = PROTECTED; else slot->mode = FREE; /* * Free memory is _always_ set to deny access. When EF_PROTECT_FREE * is true, free memory is never reallocated, so it remains access * denied for the life of the process. When EF_PROTECT_FREE is false, * the memory may be re-allocated, at which time access to it will be * allowed again. * * Some operating systems allow munmap() with single-page resolution, * and allow you to un-map portions of a region, rather than the * entire region that was mapped with mmap(). On those operating * systems, we can release protected free pages with Page_Delete(), * in the hope that the swap space attached to those pages will be * released as well. */ Page_Delete(slot->internalAddress, slot->internalSize); previousSlot = slotForInternalAddressPreviousTo(slot->internalAddress); nextSlot = slotForInternalAddress( ((char *)slot->internalAddress) + slot->internalSize); if ( previousSlot && previousSlot->mode == slot->mode ) { /* Coalesce previous slot with this one. */ previousSlot->internalSize += slot->internalSize; slot->internalAddress = slot->userAddress = 0; slot->internalSize = slot->userSize = 0; slot->mode = NOT_IN_USE; slot = previousSlot; unUsedSlots++; } if ( nextSlot && nextSlot->mode == slot->mode ) { /* Coalesce next slot with this one. */ slot->internalSize += nextSlot->internalSize; nextSlot->internalAddress = nextSlot->userAddress = 0; nextSlot->internalSize = nextSlot->userSize = 0; nextSlot->mode = NOT_IN_USE; unUsedSlots++; } slot->userAddress = slot->internalAddress; slot->userSize = slot->internalSize; if ( !noAllocationListProtection ) Page_DenyAccess(allocationList, allocationListSize); }
extern C_LINKAGE void _DpsFree(void * address, const char *filename, size_t fileline) { Slot * slot; Slot * previousSlot = 0; Slot * nextSlot = 0; if ( address == 0 ) return; /* fprintf(stderr, "DpsFree: %p at %s:%d\n", address, filename, fileline); */ if ( allocationList == 0 ) EF_Abort("DpsFree() called before first DpsMalloc() at %s:%d.", filename, fileline); lock(); if ( !noAllocationListProtection ) Page_AllowAccess(allocationList, allocationListSize); slot = slotForUserAddress(address); if ( !slot ) { /* EF_Abort("DpsFree(%a): address not from DpsMalloc() at %s:%d.", address, filename, fileline);*/ EF_Print("DpsFree(%a): address not from DpsMalloc() at %s:%d.\n", address, filename, fileline); release(); return; } /* EF_Print("DpsFree(%a): slot=%a\n", address, slot); */ if ( slot->mode != ALLOCATED ) { if ( internalUse && slot->mode == INTERNAL_USE ) /* Do nothing. */; else { if (slot->mode == FREE) EF_Print("DpsFree(%a) FREE\n", address); if (slot->mode == PROTECTED) EF_Print("DpsFree(%a) PROTECTED\n", address); if (slot->mode == INTERNAL_USE) EF_Print("DpsFree(%a) INTERNAL_USE\n", address); if (slot->mode == NOT_IN_USE) EF_Print("DpsFree(%a) NOT_IN_USE\n", address); EF_Abort("DpsFree(%a): freeing free memory at %s:%d.", address, filename, fileline); } } if ( EF_PROTECT_FREE ) slot->mode = PROTECTED; else slot->mode = FREE; /* * Free memory is _always_ set to deny access. When EF_PROTECT_FREE * is true, free memory is never reallocated, so it remains access * denied for the life of the process. When EF_PROTECT_FREE is false, * the memory may be re-allocated, at which time access to it will be * allowed again. * * Some operating systems allow munmap() with single-page resolution, * and allow you to un-map portions of a region, rather than the * entire region that was mapped with mmap(). On those operating * systems, we can release protected free pages with Page_Delete(), * in the hope that the swap space attached to those pages will be * released as well. */ if ( EF_PROTECT_FREE ) Page_Delete(slot->internalAddress, slot->internalSize); else Page_DenyAccess(slot->internalAddress, slot->internalSize); previousSlot = slotForInternalAddressPreviousTo(slot->internalAddress); nextSlot = slotForInternalAddress( ((char *)slot->internalAddress) + slot->internalSize); if ( previousSlot && (previousSlot->mode == slot->mode) ) { /* Coalesce previous slot with this one. */ previousSlot->internalSize += slot->internalSize; slot->internalAddress = slot->userAddress = 0; slot->internalSize = slot->userSize = 0; slot->mode = NOT_IN_USE; slot = previousSlot; unUsedSlots++; } if ( nextSlot && (nextSlot->mode == slot->mode) ) { /* Coalesce next slot with this one. */ slot->internalSize += nextSlot->internalSize; nextSlot->internalAddress = nextSlot->userAddress = 0; nextSlot->internalSize = nextSlot->userSize = 0; nextSlot->mode = NOT_IN_USE; unUsedSlots++; } /* slot->userAddress = slot->internalAddress; slot->userSize = slot->internalSize; */ if ( !noAllocationListProtection ) Page_DenyAccess(allocationList, allocationListSize); release(); /* fprintf(stderr, "DpsFree Done\n");*/ }
extern C_LINKAGE void ef_free(void * address) { Slot * slot; Slot * previousSlot = 0; Slot * nextSlot = 0; //printf(" ::free %p \n",address); lock(); if ( address == 0 ) { unlock(); return; } if ( allocationList == 0 ) EF_Abort("free() called before first malloc()."); if ( !noAllocationListProtection ) Page_AllowAccess(allocationList, allocationListSize); slot = slotForUserAddress(address); if ( !slot ) EF_Abort("free(%a): address not from malloc().", address); if ( slot->mode != ALLOCATED ) { if ( internalUse && slot->mode == INTERNAL_USE ) /* Do nothing. */; else { EF_Abort( "free(%a): freeing free memory." ,address); } } if ( EF_PROTECT_FREE ) slot->mode = PROTECTED; else slot->mode = FREE; if ( EF_FREE_WIPES ) memset(slot->userAddress, 0xbd, slot->userSize); previousSlot = slotForInternalAddressPreviousTo(slot->internalAddress); nextSlot = slotForInternalAddress( ((char *)slot->internalAddress) + slot->internalSize); if ( previousSlot && (previousSlot->mode == FREE || previousSlot->mode == PROTECTED) ) { /* Coalesce previous slot with this one. */ previousSlot->internalSize += slot->internalSize; if ( EF_PROTECT_FREE ) previousSlot->mode = PROTECTED; slot->internalAddress = slot->userAddress = 0; slot->internalSize = slot->userSize = 0; slot->mode = NOT_IN_USE; slot = previousSlot; unUsedSlots++; } if ( nextSlot && (nextSlot->mode == FREE || nextSlot->mode == PROTECTED) ) { /* Coalesce next slot with this one. */ slot->internalSize += nextSlot->internalSize; nextSlot->internalAddress = nextSlot->userAddress = 0; nextSlot->internalSize = nextSlot->userSize = 0; nextSlot->mode = NOT_IN_USE; unUsedSlots++; } slot->userAddress = slot->internalAddress; slot->userSize = slot->internalSize; /* * Free memory is _always_ set to deny access. When EF_PROTECT_FREE * is true, free memory is never reallocated, so it remains access * denied for the life of the process. When EF_PROTECT_FREE is false, * the memory may be re-allocated, at which time access to it will be * allowed again. */ Page_DenyAccess(slot->internalAddress, slot->internalSize); if ( !noAllocationListProtection ) Page_DenyAccess(allocationList, allocationListSize); unlock(); }