예제 #1
0
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);
}
예제 #2
0
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();
}