Beispiel #1
0
void __cdecl _heap_print_heaplist(void)

#endif	/* _MT */
{

	_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");

}
Beispiel #2
0
int __cdecl _heapmin(void)
{
	REG1 int index;
	_PBLKDESC pdesc;
	REG2 _PBLKDESC pdesc2;
	void * regend;
	int region_min_count = 0;
#if	defined(_M_MPPC) || defined(_M_M68K)
	struct _heap_region_ *pHeapRegions;
#endif
	/*
	 * Lock the heap
	 */

	_mlock(_HEAP_LOCK);

	/*
	 * Coalesce the heap (should return NULL)
	 */

	if ( _heap_search((unsigned)_HEAP_COALESCE) != NULL )
		_heap_abort();

	/*
	 * Loop through the region descriptor table freeing as much
	 * memory to the OS as possible.
	 */

#if	defined(_M_MPPC) || defined(_M_M68K)

	for ( index=0 ; index < _heap_region_table_cur ; index++ ) {

		pHeapRegions = (struct _heap_region_ *)(*hHeapRegions);
		if ( (pHeapRegions + index)->_regbase == NULL )
			continue;       /* region entry is empty */

		/*
		 * Get the entry that contains the last address of
		 * the region (allocated so far, that is).
		 */

		regend = (char *) ( (pHeapRegions + index)->_regbase) +
				 (pHeapRegions + index)->_currsize - 1;

#else	/* !defined(_M_MPPC) && !defined(_M_M68K) */

	for ( index=0 ; index < _HEAP_REGIONMAX ; index++ ) {

		if ( _heap_regions[index]._regbase == NULL )
			continue;	/* region entry is empty */

		/*
		 * Get the entry that contains the last address of
		 * the region (allocated so far, that is).
		 */

		regend = (char *) _heap_regions[index]._regbase +
				 _heap_regions[index]._currsize - 1;

#endif	/* defined(_M_MPPC) || defined(_M_M68K) */

		if ( _heap_findaddr(regend, &pdesc) != _HEAPFIND_WITHIN )
			_heap_abort();	/* last address not within a block */

		/*
		 * See if the containing block is free
		 */

		if ( !(_IS_FREE(pdesc)) )
			continue;	/* block is not free */


		/*
		 * Region ends with a free block, go free as much mem
		 * as possible.
		 */

		region_min_count += _heapmin_region(index, regend, pdesc);


	}  /* region loop */

	/*
	 * By minimizing the heap, we've likely invalidated the rover and
	 * may have produced contiguous dummy blocks so:
	 *
	 *	(1) reset the rover
	 *	(2) coalesce contiguous dummy blocks
	 */

	if ( region_min_count ) {

		/*
		 * Set proverdesc to pfirstdesc
		 */

		_heap_desc.proverdesc = _heap_desc.pfirstdesc;

		for ( pdesc = _heap_desc.pfirstdesc ; pdesc !=
		    &_heap_desc.sentinel ; pdesc = pdesc->pnextdesc ) {

			/*
			 * Check and remove consecutive dummy blocks
			 */

			if ( _IS_DUMMY(pdesc) ) {

				for ( pdesc2 = pdesc->pnextdesc ;
				    _IS_DUMMY(pdesc2) ;
				    pdesc2 = pdesc->pnextdesc ) {

					/*
					 * coalesce the dummy blocks
					 */

					pdesc->pnextdesc = pdesc2->pnextdesc;
					_PUTEMPTY(pdesc2);

				}  /* dummy loop */

			}  /* if */

		}  /* heap loop */

	}  /* region_min_count */

	/*
	 * Good return
	 */

	/* goodrtn:   unreferenced label to be removed */
		/*
		 * Release the heap lock
		 */

		_munlock(_HEAP_LOCK);

		return(0);

}


/***
*_heapmin_region() - Minimize a region
*
*Purpose:
*	Free as much of a region back to the OS as possible.
*
*Entry:
*	int index = index of the region in the region table
*	void * regend = last valid address in region
*	pdesc = pointer to the last block of memory in the region
*		(it has already been determined that this block is free)
*
*Exit:
*	int 1 = minimized region
*	    0 = no change to region
*
*Exceptions:
*
*******************************************************************************/

static int __cdecl _heapmin_region (
	int index,
	void * regend,
	REG1 _PBLKDESC pdesc
	)
{
	unsigned size;
	REG2 _PBLKDESC pnew;
#if	defined(_M_MPPC) || defined(_M_M68K)
	struct _heap_region_ *pHeapRegions;
#endif

	/*
	 * Init some variables
	 *
	 * regend = 1st address AFTER region
	 * size = amount of free memory at end of current region
	 */

	regend = (char *) regend + 1;	/* "regend++" give compiler error... */
	size = ((char *)regend - (char *)_ADDRESS(pdesc));


	/*
	 * See if there's enough free memory to release to the OS.
	 * (NOTE:  Need more than a page since we may need a back pointer.)
	 */

	if ( size <= _PAGESIZE_ )
		return(0);		/* 0 = no change to region */

	/*
	 * We're going to free some memory to the OS.  See if the
	 * free block crosses the end of the region and, if so,
	 * split up the block appropriately.
	 */

	if ( (_MEMSIZE(pdesc) - size) != 0 ) {

		/*
		 * The free block spans the end of the region.
		 * Divide it up.
		 */

		/*
		 * Get an empty descriptor
		 */

		if ( (pnew = __getempty()) == NULL )
			return(0);

		pnew->pblock = regend;		/* init block pointer */
		* (_PBLKDESC*)regend = pnew;	/* init back pointer */
		_SET_FREE(pnew);		/* set the block free */

		pnew->pnextdesc = pdesc->pnextdesc;	/* link it in */
		pdesc->pnextdesc = pnew;

	}


	/*
	 * At this point, we have a free block of memory that goes
	 * up to (but not exceeding) the end of the region.
	 *
	 * pdesc = descriptor of the last free block in region
	 * size = amount of free mem at end of region (i.e., _MEMSIZE(pdesc))
	 * regend = 1st address AFTER end of region
	 */


	/*
	 * See if we should return the whole region of only part of it.
	 */
#if	defined(_M_MPPC) || defined(_M_M68K)
	pHeapRegions = (struct _heap_region_ *)(*hHeapRegions);
	if ( _ADDRESS(pdesc) == (pHeapRegions + index)->_regbase ) {
#else
	if ( _ADDRESS(pdesc) == _heap_regions[index]._regbase ) {
#endif

		/*
		 * Whole region is free, return it to OS
		 */

		_heap_free_region(index);

		/*
		 * Put a dummy block in the heap to hold space for
		 * the memory we just freed up.
		 */

		_SET_DUMMY(pdesc);

	}

	else {

		/*
		 * Whole region is NOT free, return part of it to OS
		 */
#if	!defined(_M_MPPC) && !defined(_M_M68K)
		 _free_partial_region(pdesc, size, index);
#endif
	}

	/*
	 * Exit paths
	 */

	return(1);	/* 1 = minimized region */

}


/***
*_free_partial_region() - Free part of a region to the OS
*
*Purpose:
*	Free a portion of a region to the OS
*
*Entry:
*	pdesc = descriptor of last free block in region
*	size = amount of free mem at end of region (i.e., _MEMSIZE(pdesc))
*	index = index of region
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/

static void __cdecl _free_partial_region (
	REG1 _PBLKDESC pdesc,
	unsigned size,
	int index
	)
{
	unsigned left;
	void * base;
	REG2 _PBLKDESC pnew;
#if	defined(_M_MPPC) || defined(_M_M68K)
	struct _heap_region_ *pHeapRegions;
#endif

	/*
	 * Init a few variables.
	 */

	left = (size & (_PAGESIZE_-1));
	base = (char *)_ADDRESS(pdesc);

	/*
	 * We return memory to the OS in page multiples.  If the
	 * free block is not page aligned, we'll insert a new free block
	 * to fill in the difference.
	 */

	if ( left != 0 ) {

		/*
		 * The block is not a multiple of pages so we need
		 * to adjust variables accordingly.
		 */

		size -= left;
		base = (char *)base + left;
	}


	/*
	 * Return the free pages to the OS.
	 */

#if	defined(_M_MPPC) || defined(_M_M68K)

	if (base)
	{
		DisposePtr(base);
	}

	/*
	 * Adjust the region table entry
	 */

	pHeapRegions = (struct _heap_region_ *)(*hHeapRegions);
	(pHeapRegions + index)->_currsize -= size;

#else	/* !defined(_M_MPPC) && !defined(_M_M68K) */

        if (!VirtualFree(base, size, MEM_DECOMMIT))
		 _heap_abort();

	/*
	 * Adjust the region table entry
	 */

	_heap_regions[index]._currsize -= size;

#endif	/* defined(_M_MPPC) || defined(_M_M68K) */

	/*
	 * Adjust the heap according to whether we released the whole
	 * free block or not. (Don't worry about consecutive dummies,
	 * we'll coalesce them later.)
	 *
	 * base = address of block we just gave back to OS
	 * size = size of block we gave back to OS
	 * left = size of block we did NOT give back to OS
	 */

	if ( left == 0 ) {

		/*
		 * The free block was released to the OS in its
		 * entirety.  Make the free block a dummy place holder.
		 */

		_SET_DUMMY(pdesc);

	}

	else {

		/*
		 * Did NOT release the whole free block to the OS.
		 * There's a block of free memory we want to leave
		 * in the heap.  Insert a dummy entry after it.
		 */

		if ( (pnew = __getempty()) == NULL )
			_heap_abort();

		pnew->pblock = (char *)base;
		_SET_DUMMY(pnew);

		pnew->pnextdesc = pdesc->pnextdesc;
		pdesc->pnextdesc = pnew;

	}

}
_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 ;
}
Beispiel #4
0
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);

}