Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*-----------------------------------------------------------------------*
- * filename - heap.c
- *
- * function(s)
- * _lock_heap - lock the global heap lock
- * _unlock_heap - unlock the global heap lock
- * _release_heap - releases all the memory allocated by the heap manager
- * this function is not defined for OS/2
- * _init_lock - creates the lock for MT heap management
- * free - free an allocated block
- * _heapadd - add a block to the heap
- * malloc - allocate a block from the heap
- *-----------------------------------------------------------------------*/
- /*
- * C/C++ Run Time Library - Version 2.0
- *
- * Copyright (c) 1995, 1996 by Borland International
- * All Rights Reserved.
- *
- */
- #include <mem.h>
- #include <_heap.h>
- #include <_thread.h>
- #include <assert.h>
- /*----------------------------------------------------------------------
- * Knuth's "boundary tag" algorithm is used to manage the heap.
- * Each block in the heap has a tag word before it, which
- * contains the size of the block and two bits:
- * SIZE f1 f2
- * block ...
- * SIZE f1 f2
- * block ...
- * The size is stored as a long word, and does not include the 4 bytes of
- * overhead that the boundary tag consumes. Blocks are allocated
- * on LONG word boundaries, so the size is always even. When the
- * block is allocated, bit 0 (F_FREE) of the size is set to 1. When a block
- * is freed, it is merged with adjacent free blocks, and bit 0 of the
- * size is set to 0. Bit 1 (F_PFREE) signals that the previous block is free.
- *
- * When a block is on the free list, the first two LONG words of the block
- * contain double links. In addition, there is a tag at the end of the block,
- * which stores the size + 4. These links are not used when the block is
- * allocated, but space needs to be reserved for them. Thus, the minimum
- * block size (not counting the tag) is 12 bytes.
- *
- * There are separate free lists for blocks smaller than _smalloc_threshold.
- * Each of these lists link free blocks of the same size. There is one list
- * for free blocks > _smalloc_threshold with a roving pointer.
- *
- * When an allocation request comes in for a block >= _smalloc_threshold,
- * the usual 'nextfit' algorithm is used with the rover. Note that the search
- * will only browse the free blocks that are >=_smalloc_threshold.
- *
- * When an allocation request is made for a block <=smalloc_threshold,
- * first we check if we have a free block of that size. Note that this is
- * very fast, since it involves only one indexing. If there is a free
- * block of the requested size, it simply needs to be unlinked from the
- * free list. If there is no such size free block, we will take the rover
- * (>=_smalloc_threshold). If there are no blocks > _smalloc_threshold,
- * we will scan forward in the 'small' list until we find any free
- * blocks.
- *
- * See <heap.h> for the definition and description of the macros
- * and structures used to access heap blocks.
- */
- /*----------------------------------------------------------------------
- * Internal public variables.
- */
- size_t _virt_heap_size = 0x400000; // reserve that much for a heap
- size_t _virt_chunk_size = 0x010000; // commit that much at once
- size_t _virt_chunk_size2 = 0x001000; // commit that much at once after going virtual
- size_t _nv_heap_size = 0x100000; // take that much for a heap if no virtual memory support
- size_t _smalloc_threshold = 4096; // small block allocation threshold. Uses *2 bytes overhead
- size_t _virt_chunk_free = 0x020000; // free if that much is free
- size_t _virt_chunk_free2 = 0x002000; // free if that much is free if virtual
- HEAP *_firstHeap = NULL;
- HEAP *_lastHeap = NULL;
- DLINK *_linktable = NULL; // vector of double link list headers for blocks < _smalloc_threshold
- // free list header for blocks > _smalloc_threshold
- BLOCKHDR _freeStart = {0 + F_FREE, &_freeStart, &_freeStart};
- // _rover for blocks > _smalloc_threshold
- BLOCKHDR *_rover = &_freeStart;
- #ifdef BALANCEDFIT
- int _numSmall = 0; // number of small free blocks
- int _numBig = 0; // number of big free blocks
- #endif
- #ifdef STAT
- unsigned long n = 0;
- unsigned long l = 0;
- #endif
- static size_t avail = 0;
- size_t __allocated = 0;
- #ifdef _MT
- lock_t _heap_lock; // heap semaphore
- #endif
- #ifdef _MT
- /*---------------------------------------------------------------------*
- Name _init_lock - creates the lock for the global heap
- Usage void _init_lock(void);
- Prototype in _heap.h
- Return value None.
- *---------------------------------------------------------------------*/
- void _init_lock (void)
- {
- #pragma startup _init_lock 2
- // Create the lock used to govern access to the heap.
- _create_lock(&_heap_lock,"creating heap lock");
- }
- /*---------------------------------------------------------------------*
- Name _lock_heap - lock the global heap lock
- Usage void _lock_heap(void);
- Prototype in _stdio.h
- Related
- functions usage void _unlock_heap(void);
- Description This function locks the global lock that governs
- access to the heap.
- Return value None.
- *---------------------------------------------------------------------*/
- void _lock_heap(void)
- {
- _lock(_heap_lock, "locking heap");
- }
- /*---------------------------------------------------------------------*
- Name _unlock_heap - unlock the global heap lock
- Usage void _unlock_heap(void);
- Prototype in _stdio.h
- Related
- functions usage void _unlock_heap(void);
- Description This function unlocks the global lock that governs
- access to the heap.
- Return value None.
- *---------------------------------------------------------------------*/
- void _unlock_heap(void)
- {
- _unlock(_heap_lock, "unlocking heap");
- }
- #endif /* _MT */
- /*---------------------------------------------------------------------*
- Name _table_init - initializes the headers for small blocks
- Usage int _table_init(void)
- Prototype in
- Description
- Return value None
- *---------------------------------------------------------------------*/
- static void _table_init(void)
- {
- int i;
- BLOCKHDR *stopper;
- for (i = MINSIZE; i < _smalloc_threshold; i += ALIGNMENT)
- {
- BLOCKHDR *p = HDR4SIZE(i);
- p->nextFree = p;
- p->prevFree = p;
- }
- stopper = HDR4SIZE(_smalloc_threshold);
- stopper->nextFree = NULL;
- stopper->prevFree = NULL;
- }
- /*---------------------------------------------------------------------*
- Name _vheapadd - add a block to the heap
- Usage int _vheapadd(void *block, size_t cSize, size_t rSize);
- Prototype in malloc.h
- Description This function adds a new block of memory to the heap.
- The block must not have been previously allocated from
- the heap.
- Return value If the block can be successfully added to the heap,
- 0 is returned; otherwise -1.
- *---------------------------------------------------------------------*/
- static int _RTLENTRY _EXPFUNC _vheapadd(void *ptr, size_t cSize, size_t rSize)
- {
- BLOCKHDR *b, *bp;
- HEAP *h = (HEAP *) ptr;
- size_t tsize = 0, size;
- if (cSize < PAGESIZE)
- return -1;
- _lock_heap();
- // create the heap header
- h->numSysBlocks = 1;
- h->sysBlocks[0] = ptr;
- h->cSize = cSize;
- h->rSize = rSize;
- // add it to the list of heaps
- h->nextHeap = _firstHeap;
- h->prevHeap = NULL;
- if (_firstHeap)
- _firstHeap->prevHeap = h;
- else
- _lastHeap = h;
- _firstHeap = h;
- // Setup zero length allocated block
- b = FIRSTBLOCK(h);
- b->blockSize = 0; // size 0 , used, prev used.
- b = NEXT(b);
- // If table has not been initialized, allocate block and initialize
- if (!_linktable)
- {
- tsize = ALIGNUPBY(_smalloc_threshold * (sizeof(DLINK) / ALIGNMENT), ALIGNMENT);
- _linktable = HDR2PTR(b);
- b->blockSize = tsize;
- b = NEXT(b);
- _table_init();
- tsize += sizeof(size_t);
- }
- // Setup huge free block
- // Size of block is (committed size) - (heap header) -
- // (zero length block + free block header + last block header) -
- // (linktable size)
- size = cSize - sizeof(HEAP) - 3 * sizeof(size_t) - tsize;
- b->blockSize = size + F_FREE;
- // Set last block header
- NEXT(b)->blockSize = 0 + F_PFREE; // size 0, used, prev free.
- if (size < _smalloc_threshold)
- {
- bp = HDR4SIZE(size);
- #ifdef BALANCEDFIT
- _numSmall++;
- #endif
- }
- else
- {
- bp = _rover;
- #ifdef BALANCEDFIT
- _numBig++;
- #endif
- }
- ADDFREEAFTER(b, bp);
- SETFSIZE(b, size);
- _unlock_heap();
- return 0;
- }
- /*---------------------------------------------------------------------*
- Name _heapadd - add a block to the heap
- Usage int _heapadd(void *block, size_t size);
- Prototype in malloc.h
- Description This function adds a new block of memory to the heap.
- The block must not have been previously allocated from
- the heap.
- Return value If the block can be successfully added to the heap,
- 0 is returned; otherwise -1.
- *---------------------------------------------------------------------*/
- /*
- int _RTLENTRY _EXPFUNC _heapadd(void *ptr, size_t size)
- {
- return _vheapadd(ptr, size, size);
- }
- */
- /*---------------------------------------------------------------------*
- Name _heapresize - resize a heap
- Usage int _heapresize (HEAP * h, size_t newSize);
- Prototype in malloc.h
- Description This function adds a new block of memory to the heap.
- The block must not have been previously allocated from
- the heap.
- Return value If the block can be successfully added to the heap,
- 0 is returned; otherwise -1.
- *---------------------------------------------------------------------*/
- static int _RTLENTRY _EXPFUNC _heapresize(HEAP * h, size_t cSize)
- {
- size_t delta;
- BLOCKHDR *b;
- cSize = ALIGNDNBY(cSize, PAGESIZE);
- b = LASTBLOCK(h);
- if (cSize < h->cSize)
- {
- // shrink
- if (ISPFREE(b))
- {
- b = PFREE(b);
- delta = h->cSize - cSize;
- //if (SIZE(b) + MINFREE < delta)
- if (SIZE(b) - MINFREE < delta)
- return -1;
- _lock_heap();
- b->blockSize -= delta;
- SETFSIZE(b, SIZE(b));
- NEXT(b)->blockSize = 0 + F_PFREE;
- if (SIZE(b)<_smalloc_threshold)
- {
- // the block needs to move
- REMOVEFREE(b);
- ADDFREEAFTER(b, HDR4SIZE(SIZE(b)));
- }
- _unlock_heap();
- }
- else
- return -1;
- }
- else
- {
- // grow
- _lock_heap();
- delta = cSize - h->cSize;
- b->blockSize += delta - sizeof(size_t); // was 0, now it is cSize
- NEXT(b)->blockSize = 0;
- gfree(HDR2PTR(b));
- h->cSize += delta;
- _unlock_heap();
- }
- return 0;
- }
- /*---------------------------------------------------------------------*
- Name _get_more_heap - allocate more memory from the system for heap
- Usage void _get_more_heap(size_t minSize);
- Prototype in local
- Description This function allocates more system memory by growing a heap
- or adding a new one.
- Return value none.
- *---------------------------------------------------------------------*/
- static int _get_more_heap(size_t minSize)
- {
- HEAP *h;
- void *v;
- size_t vsize;
- size_t csize;
- size_t aMinSize = ALIGNUPBY(minSize, PAGESIZE);
- if (!avail)
- avail = _phys_avail();
- if (!_linktable)
- aMinSize += ALIGNUPBY(_smalloc_threshold * (sizeof(DLINK) / ALIGNMENT) + sizeof(HEAP)+12, PAGESIZE);
- for (h = _firstHeap; h; h = h->nextHeap)
- {
- if (h->rSize - h->cSize > aMinSize)
- {
- size_t newSize = MIN(h->rSize, h->cSize + ALIGNUPBY(aMinSize, avail > __allocated + _virt_chunk_size ? _virt_chunk_size : _virt_chunk_size2));
- if (_virt_commit((char *) h + h->cSize, newSize - h->cSize) != 0)
- {
- // should never fail
- _lock_heap();
- __allocated += newSize - h->cSize;
- _heapresize(h, newSize);
- _unlock_heap();
- return 0;
- }
- // otherwise, try to commit PAGESIZE
- else if(_virt_commit ((char *) h+h->cSize, PAGESIZE))
- {
- __allocated+= PAGESIZE;
- _heapresize(h, h->cSize+PAGESIZE);
- return 0;
- }
- // we are out of memory, not worth trying more
- else return -1;
- }
- }
- if (_virt_reserve(MAX(_virt_heap_size, aMinSize), &v, &vsize) == 0)
- return -1;
- csize = ALIGNUPBY(aMinSize + PAGESIZE, avail > __allocated + _virt_chunk_size ? _virt_chunk_size : _virt_chunk_size2);
- for (h = _firstHeap; h; h = h->nextHeap)
- {
- if ((char *) h + h->rSize == v && h->numSysBlocks < MAXSYSBLOCKS)
- {
- size_t g = h->rSize - h->cSize;
- // merge the heaps and commit overlapping
- if (g)
- {
- if (_virt_commit((char *) h + h->cSize, g) != 0)
- {
- __allocated += g;
- _heapresize(h, h->rSize);
- }
- else
- return -1;
- }
- if (_virt_commit(v, csize - g) != 0)
- {
- _lock_heap();
- __allocated += csize - g;
- h->sysBlocks[h->numSysBlocks++] = v;
- h->rSize += vsize;
- _heapresize(h, h->cSize + csize - g);
- _unlock_heap();
- return 0;
- }
- else
- return -1;
- }
- }
- if (_virt_commit(v, csize) == 0)
- {
- _virt_release(v);
- return -1;
- }
- // should never fail
- __allocated += csize;
- _vheapadd(v, csize, vsize);
- return 0;
- }
- /*---------------------------------------------------------------------*
- Name _release_heap_at
- Usage
- Prototype in
- Description
- Return value
- *---------------------------------------------------------------------*/
- static int _release_heap_at(BLOCKHDR * b)
- {
- HEAP *h;
- BLOCKHDR *bn = NEXT(b);
- size_t delta;
- size_t freethreshold = avail > __allocated ? _virt_chunk_free : _virt_chunk_free2;
- if (b->blockSize-MINFREE < freethreshold)
- return 0;
- delta = ALIGNDNBY(b->blockSize-MINFREE, freethreshold);
- for (h = _firstHeap; h; h = h->nextHeap)
- {
- if (LASTBLOCK(h) == bn)
- {
- // we can shrink this heap
- size_t newSize = h->cSize - delta;
- _lock_heap();
- // we made sure it will not fail
- _heapresize(h, newSize);
- while ((char *) h + newSize <= h->sysBlocks[h->numSysBlocks - 1])
- {
- // release attached block
- size_t s = h->cSize - (h->sysBlocks[--h->numSysBlocks] -(char*)h);
- _virt_decommit(h->sysBlocks[h->numSysBlocks], s);
- __allocated -= s;
- _virt_release(h->sysBlocks[h->numSysBlocks]);
- h->cSize = h->rSize = h->sysBlocks[h->numSysBlocks] - (char *) h;
- }
- _virt_decommit(h->sysBlocks[h->numSysBlocks - 1] + newSize, h->cSize - newSize);
- __allocated -= h->cSize - newSize;
- h->cSize = newSize;
- _unlock_heap();
- return 1;
- }
- }
- return 0;
- }
- /*---------------------------------------------------------------------*
- Name free - free an allocated block
- Usage void free(void *block);
- Prototype in
- Description Return a block to the heap. The block must have
- previously allocated with malloc, realloc, or calloc.
- If the block pointer is NULL, no action is performed.
- There is an internal routine called _free which is
- identical, except that it does not call the _free_hook
- routine. This should be used for internal calls to
- free that do not refer to user-specified blocks.
- Return value None.
- *---------------------------------------------------------------------*/
- void _RTLENTRY _EXPFUNC gfree(void *block)
- {
- BLOCKHDR *b, *nb, *bp;
- size_t s;
- if (!block)
- return;
- b = PTR2HDR(block);
- _lock_heap();
- if (ISPFREE(b))
- {
- // previous block is free, merge it
- BLOCKHDR *bp = PFREE(b);
- #ifdef BALANCEDFIT
- if (bp->blockSize >= _smalloc_threshold)
- _numBig--;
- else
- _numSmall--;
- #endif
- bp->blockSize += SIZE(b) + sizeof(size_t);
- b = bp;
- if (_rover == b)
- _rover = _rover->nextFree;
- REMOVEFREE(b);
- }
- else
- {
- // can't merge back, mark it free simply and add to free list
- b->blockSize |= F_FREE;
- }
- if (ISFREE(nb = NEXT(b)))
- {
- // merge forward
- b->blockSize += SIZE(nb) + sizeof(size_t);
- if (_rover == nb)
- _rover = nb->nextFree;
- #ifdef BALANCEDFIT
- if (nb->blockSize >= _smalloc_threshold)
- _numBig--;
- else
- _numSmall--;
- #endif
- REMOVEFREE(nb);
- }
- NEXT(b)->blockSize |= F_PFREE;
- // reinsert b to free list
- s = SIZE(b);
- if (s < _smalloc_threshold)
- {
- bp = HDR4SIZE(s);
- #ifdef BALANCEDFIT
- _numSmall++;
- #endif
- }
- else
- {
- bp = _rover->nextFree;
- #ifdef BALANCEDFIT
- _numBig++;
- #endif
- }
- ADDFREEAFTER(b, bp);
- SETFSIZE(b, s);
- _unlock_heap();
- // check if we can shrink the heap
- if (NEXT(b)->blockSize == 0 + F_PFREE && b->blockSize > (avail > __allocated ? _virt_chunk_free : _virt_chunk_free2))
- {
- _release_heap_at(b);
- }
- }
- /*---------------------------------------------------------------------*
- Name malloc - allocate a block from the heap
- Usage void * malloc(size_t size);
- Prototype in local
- Description This function allocates a block from the heap.
- The contents of the block are undefined.
- If the size of the block is less than 64K, the
- block is guaranteed to not cross a 64K boundary.
- Return value If the block can be successfully allocated, the
- address of the block is returned; otherwise NULL
- is returned.
- *---------------------------------------------------------------------*/
- void *_RTLENTRY _EXPFUNC gmalloc(size_t size)
- {
- size_t aSize;
- size_t saveSize;
- BLOCKHDR *fh;
- if (!size)
- return NULL;
- if (size < MINSIZE)
- aSize = MINSIZE;
- else
- aSize = ALIGNUPBY(size, ALIGNMENT);
- if (!_linktable)
- _get_more_heap(1);
- #ifdef STAT
- n++;
- #endif
- _lock_heap();
- if (aSize < _smalloc_threshold)
- {
- fh = HDR4SIZE(aSize);
- #if !defined(WORSTFIT)
- if (fh->nextFree != fh)
- {
- fh = fh->nextFree;
- fh->blockSize &= ~F_FREE; // size remains, but now it's used
- NEXT(fh)->blockSize &= ~F_PFREE;
- #ifdef BALANCEDFIT
- _numSmall--;
- #endif
- REMOVEFREE(fh);
- _unlock_heap();
- return HDR2PTR(fh);
- }
- #endif
- #ifdef BALANCEDFIT
- if (_numSmall > _smalloc_threshold / (ALIGNMENT * 4) && _numSmall > _numBig * 4)
- #endif
- #if defined(BESTFIT) || defined (BALANCEDFIT)
- {
- // scan the free list vector for an entry. It will be terminated
- // by the 'stopper', whose ->nextFree is NULL.
- #ifdef UNROLL
- fh = HDR4SIZE(aSize + ALIGNMENT);
- while (1)
- {
- if (fh->nextFree != fh)
- break;
- // cmp eax, [eax+4] ;; 1+2
- // jne @@break ;; 1
- ((DLINK *) fh)++;
- // add eax, 8 ;; 1
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- }
- #elif defined(UNROLL2)
- fh = HDR4SIZE(aSize + ALIGNMENT);
- while (1)
- {
- BLOCKHDR *f2 = fh; // ;; mov edx, eax; 1
- if (((BLOCKHDR *) (((DLINK *) f2)[0]))->nextFree != fh)
- break;
- // cmp eax, [edx+4] ;; 1
- // jne @@break ;; 1
- ((DLINK *) fh)++;
- // add eax, 8 ;; 1
- if (((BLOCKHDR *) (((DLINK *) f2) + 1))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 2))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 3))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 4))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 5))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 6))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 7))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 8))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 9))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 10))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 11))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 12))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 13))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 14))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 15))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- }
- #else
- for (fh = HDR4SIZE(aSize + ALIGNMENT); fh->nextFree == fh; ((DLINK *) fh)++)
- ;
- // ...
- // @@loop: add eax, 8 ;; 1
- // cmp eax, [eax+4] ;; 1+2
- // je @@loop ;; 3
- #endif
- if (fh->nextFree)
- fh = fh->nextFree; // found
- else
- {
- // use the _rover
- fh = _rover;
- if (fh == &_freeStart)
- fh = fh->nextFree;
- }
- }
- #endif
- #ifdef BALANCEDFIT
- else
- #endif
- #if !defined(BESTFIT)
- {
- // we won't need to search the 'big list' _rover should be perfect
- fh = _rover;
- if (fh == &_freeStart)
- fh = fh->nextFree;
- // if 'big block list' is empty, find a small slot
- if (_freeStart.nextFree == &_freeStart)
- {
- // scan the free list vector for an entry. It will be terminated
- // by the 'stopper', whose ->nextFree is NULL.
- #ifdef UNROLL
- #if !defined(WORSTFIT)
- fh = HDR4SIZE(aSize + ALIGNMENT);
- #else
- fh = HDR4SIZE(aSize);
- #endif
- while (1)
- {
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (fh->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- }
- #elif defined(UNROLL2)
- #if !defined(WORSTFIT)
- fh = HDR4SIZE(aSize + ALIGNMENT);
- #else
- fh = HDR4SIZE(aSize);
- #endif
- while (1)
- {
- BLOCKHDR *f2 = fh; // ;; mov edx, eax; 1
- if (((BLOCKHDR *) (((DLINK *) f2) + 0))->nextFree != fh)
- break;
- // cmp eax, [edx+4] ;; 1
- // jne @@break ;; 1
- ((DLINK *) fh)++;
- // add eax, 8 ;; 1
- if (((BLOCKHDR *) (((DLINK *) f2) + 1))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 2))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 3))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 4))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 5))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 6))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 7))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 8))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 9))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 10))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 11))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 12))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 13))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 14))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- if (((BLOCKHDR *) (((DLINK *) f2) + 15))->nextFree != fh)
- break;
- ((DLINK *) fh)++;
- }
- #else
- #if !defined(WORSTFIT)
- for (fh = HDR4SIZE(aSize + ALIGNMENT); fh->nextFree == fh; ((DLINK *) fh)++)
- ;
- #else
- for (fh = HDR4SIZE(aSize); fh->nextFree == fh; ((DLINK *) fh)++)
- ;
- #endif
- #endif
- if (fh->nextFree)
- fh = fh->nextFree; // found
- else
- fh = _rover; // not found (out of memory)
- }
- }
- #endif
- }
- else // aSize >= _smalloc_threshold
- {
- if ((saveSize = (fh = _rover)->blockSize) < aSize)
- {
- _rover->blockSize = 0xFFFFFFFCL + F_FREE;
- #ifdef UNROLL
- fh = fh->nextFree;
- while (1)
- {
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- if (fh->blockSize >= aSize)
- break;
- fh = fh->nextFree;
- }
- #else
- for (fh = fh->nextFree; fh->blockSize < aSize; fh = fh->nextFree)
- #ifdef STAT
- l++
- #endif
- ;
- #endif
- _rover->blockSize = saveSize;
- if (fh == _rover)
- fh = &_freeStart;
- }
- }
- if (fh != &_freeStart)
- {
- size_t fSize = SIZE(fh);
- if (fSize - aSize < MINFREEH)
- {
- fh->blockSize &= ~F_FREE; // size remains, but now it's used
- NEXT(fh)->blockSize &= ~F_PFREE;
- if (fSize >= _smalloc_threshold)
- {
- _rover = fh->nextFree;
- #ifdef BALANCEDFIT
- _numBig--;
- #endif
- }
- #ifdef BALANCEDFIT
- else
- {
- _numSmall--;
- }
- #endif
- REMOVEFREE(fh);
- _unlock_heap();
- return HDR2PTR(fh);
- }
- else
- {
- // split block
- BLOCKHDR *nh, *f;
- size_t s;
- fh->blockSize = aSize; // that takes it too
- nh = NEXT(fh);
- s = fSize - aSize - sizeof(size_t);
- nh->blockSize = s + F_FREE;
- SETFSIZE(nh, s);
- if (s < _smalloc_threshold)
- {
- f = HDR4SIZE(s);
- #ifdef BALANCEDFIT
- if (fSize >= _smalloc_threshold)
- {
- _numSmall++;
- _numBig--;
- }
- #endif
- ADDFREEAFTER(nh, f);
- if (fh == _rover)
- _rover = fh->nextFree;
- REMOVEFREE(fh);
- }
- else
- {
- fh->prevFree->nextFree = nh;
- nh->prevFree = fh->prevFree;
- fh->nextFree->prevFree = nh;
- nh->nextFree = fh->nextFree;
- _rover = nh;
- }
- _unlock_heap();
- return HDR2PTR(fh);
- }
- }
- else
- {
- _unlock_heap();
- if (_get_more_heap(size + 64) == 0)
- {
- return gmalloc(size);
- }
- else
- return NULL;
- }
- }
- #include <windows.h>
- #include <stdio.h>
- size_t _phys_avail(void)
- {
- MEMORYSTATUS mst;
- mst.dwLength = sizeof(MEMORYSTATUS);
- GlobalMemoryStatus(&mst);
- return mst.dwAvailPhys;
- }
- static int releaseHeap = 0;
- void _EXPFUNC _free_heaps()
- {
- HEAP *h;
- int i;
- if (releaseHeap)
- {
- for (h = _firstHeap;;)
- {
- void *nextH = h->nextHeap;
- for (i = --h->numSysBlocks; i>=0 ; i--)
- {
- size_t s = h->cSize - (h->sysBlocks[i] -(char*)h);
- void *p = h->sysBlocks[i];
- h->cSize = h->rSize = h->sysBlocks[i] - (char *) h;
- _virt_decommit(p, s);
- _virt_release(p);
- }
- if (nextH)
- h = nextH;
- else
- break;
- }
- }
- }
- static void set_releaseHeap()
- {
- #pragma exit set_releaseHeap 0
- releaseHeap = 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement