Advertisement
DarthGizka

BC++ 5.02 heap.c

Dec 28th, 2014
325
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 36.28 KB | None | 0 0
  1. /*-----------------------------------------------------------------------*
  2.  * filename - heap.c
  3.  *
  4.  * function(s)
  5.  *      _lock_heap      - lock the global heap lock
  6.  *      _unlock_heap    - unlock the global heap lock
  7.  *      _release_heap   - releases all the memory allocated by the heap manager
  8.  *                        this function is not defined for OS/2
  9.  *      _init_lock      - creates the lock for MT heap management
  10.  *      free            - free an allocated block
  11.  *      _heapadd        - add a block to the heap
  12.  *      malloc          - allocate a block from the heap
  13.  *-----------------------------------------------------------------------*/
  14.  
  15. /*
  16.  *      C/C++ Run Time Library - Version 2.0
  17.  *
  18.  *      Copyright (c) 1995, 1996 by Borland International
  19.  *      All Rights Reserved.
  20.  *
  21.  */
  22.  
  23. #include <mem.h>
  24. #include <_heap.h>
  25. #include <_thread.h>
  26. #include <assert.h>
  27.  
  28.  
  29. /*----------------------------------------------------------------------
  30.  * Knuth's "boundary tag" algorithm is used to manage the heap.
  31.  * Each block in the heap has a tag word before it, which
  32.  * contains the size of the block and two bits:
  33.  *  SIZE f1 f2
  34.  *  block ...
  35.  *  SIZE f1 f2
  36.  *  block ...
  37.  * The size is stored as a long word, and does not include the 4 bytes of
  38.  * overhead that the boundary tag consumes.  Blocks are allocated
  39.  * on LONG word boundaries, so the size is always even.  When the
  40.  * block is allocated, bit 0 (F_FREE) of the size is set to 1.  When a block
  41.  * is freed, it is merged with adjacent free blocks, and bit 0 of the
  42.  * size is set to 0. Bit 1 (F_PFREE) signals that the previous block is free.
  43.  *
  44.  * When a block is on the free list, the first two LONG words of the block
  45.  * contain double links. In addition, there is a tag at the end of the block,
  46.  * which stores the size + 4. These links are not used when the block is
  47.  * allocated, but space needs to be reserved for them.  Thus, the minimum
  48.  * block size (not counting the tag) is 12 bytes.
  49.  *
  50.  * There are separate free lists for blocks smaller than _smalloc_threshold.
  51.  * Each of these lists link free blocks of the same size. There is one list
  52.  * for free blocks > _smalloc_threshold with a roving pointer.
  53.  *
  54.  * When an allocation request comes in for a block >= _smalloc_threshold,
  55.  * the usual 'nextfit' algorithm is used with the rover. Note that the search
  56.  * will only browse the free blocks that are >=_smalloc_threshold.
  57.  *
  58.  * When an allocation request is made for a block <=smalloc_threshold,
  59.  * first we check if we have a free block of that size. Note that this is
  60.  * very fast, since it involves only one indexing. If there is a free
  61.  * block of the requested size, it simply needs to be unlinked from the
  62.  * free list. If there is no such size free block, we will take the rover
  63.  * (>=_smalloc_threshold). If there are no blocks > _smalloc_threshold,
  64.  * we will scan forward in the 'small' list until we find any free
  65.  * blocks.
  66.  *
  67.  * See <heap.h> for the definition and description of the macros
  68.  * and structures used to access heap blocks.
  69.  */
  70.  
  71. /*----------------------------------------------------------------------
  72.  * Internal public variables.
  73.  */
  74. size_t _virt_heap_size = 0x400000;      // reserve that much for a heap
  75.  
  76. size_t _virt_chunk_size = 0x010000;     // commit that much at once
  77.  
  78. size_t _virt_chunk_size2 = 0x001000;    // commit that much at once after going virtual
  79.  
  80. size_t _nv_heap_size = 0x100000;        // take that much for a heap if no virtual memory support
  81.  
  82. size_t _smalloc_threshold = 4096;       // small block allocation threshold. Uses *2 bytes overhead
  83.  
  84. size_t _virt_chunk_free = 0x020000;     // free if that much is free
  85.  
  86. size_t _virt_chunk_free2 = 0x002000;    // free if that much is free if virtual
  87.  
  88. HEAP  *_firstHeap = NULL;
  89. HEAP  *_lastHeap = NULL;
  90. DLINK *_linktable = NULL;               // vector of double link list headers for blocks < _smalloc_threshold
  91.  
  92. // free list header for blocks > _smalloc_threshold
  93. BLOCKHDR _freeStart = {0 + F_FREE, &_freeStart, &_freeStart};
  94.  
  95. // _rover for blocks > _smalloc_threshold
  96. BLOCKHDR *_rover = &_freeStart;
  97.  
  98. #ifdef  BALANCEDFIT
  99. int _numSmall = 0;                      // number of small free blocks
  100. int _numBig   = 0;                      // number of big   free blocks
  101. #endif
  102.  
  103. #ifdef  STAT
  104. unsigned long n = 0;
  105. unsigned long l = 0;
  106. #endif
  107.  
  108. static size_t avail = 0;
  109. size_t __allocated  = 0;
  110.  
  111. #ifdef _MT
  112. lock_t _heap_lock;                      // heap semaphore
  113. #endif
  114.  
  115. #ifdef _MT
  116.  
  117. /*---------------------------------------------------------------------*
  118.  
  119. Name            _init_lock - creates the lock for the global heap
  120.  
  121. Usage           void _init_lock(void);
  122.  
  123. Prototype in    _heap.h
  124.  
  125. Return value    None.
  126.  
  127. *---------------------------------------------------------------------*/
  128.  
  129. void _init_lock (void)
  130. {
  131. #pragma startup _init_lock 2
  132.     // Create the lock used to govern access to the heap.
  133.     _create_lock(&_heap_lock,"creating heap lock");
  134. }
  135.  
  136.  
  137. /*---------------------------------------------------------------------*
  138.  
  139. Name            _lock_heap - lock the global heap lock
  140.  
  141. Usage           void _lock_heap(void);
  142.  
  143. Prototype in    _stdio.h
  144.  
  145. Related
  146. functions usage void _unlock_heap(void);
  147.  
  148. Description     This function locks the global lock that governs
  149.                 access to the heap.
  150.  
  151. Return value    None.
  152.  
  153. *---------------------------------------------------------------------*/
  154.  
  155. void _lock_heap(void)
  156. {
  157.     _lock(_heap_lock, "locking heap");
  158. }
  159.  
  160.  
  161. /*---------------------------------------------------------------------*
  162.  
  163. Name            _unlock_heap - unlock the global heap lock
  164.  
  165. Usage           void _unlock_heap(void);
  166.  
  167. Prototype in    _stdio.h
  168.  
  169. Related
  170. functions usage void _unlock_heap(void);
  171.  
  172. Description     This function unlocks the global lock that governs
  173.                 access to the heap.
  174.  
  175. Return value    None.
  176.  
  177. *---------------------------------------------------------------------*/
  178.  
  179. void _unlock_heap(void)
  180. {
  181.     _unlock(_heap_lock, "unlocking heap");
  182. }
  183. #endif /* _MT */
  184.  
  185.  
  186. /*---------------------------------------------------------------------*
  187.  
  188. Name            _table_init - initializes the headers for small blocks
  189.  
  190. Usage           int _table_init(void)
  191.  
  192. Prototype in
  193.  
  194. Description
  195.  
  196. Return value    None
  197.  
  198. *---------------------------------------------------------------------*/
  199.  
  200. static void _table_init(void)
  201. {
  202.     int i;
  203.     BLOCKHDR *stopper;
  204.  
  205.     for (i = MINSIZE; i < _smalloc_threshold; i += ALIGNMENT)
  206.     {
  207.         BLOCKHDR *p = HDR4SIZE(i);
  208.  
  209.         p->nextFree = p;
  210.         p->prevFree = p;
  211.     }
  212.     stopper = HDR4SIZE(_smalloc_threshold);
  213.     stopper->nextFree = NULL;
  214.     stopper->prevFree = NULL;
  215. }
  216.  
  217.  
  218. /*---------------------------------------------------------------------*
  219.  
  220. Name            _vheapadd - add a block to the heap
  221.  
  222. Usage           int _vheapadd(void *block, size_t cSize, size_t rSize);
  223.  
  224. Prototype in    malloc.h
  225.  
  226. Description     This function adds a new block of memory to the heap.
  227.                 The block must not have been previously allocated from
  228.                 the heap.
  229.  
  230. Return value    If the block can be successfully added to the heap,
  231.                 0 is returned; otherwise -1.
  232.  
  233. *---------------------------------------------------------------------*/
  234.  
  235. static int _RTLENTRY _EXPFUNC _vheapadd(void *ptr, size_t cSize, size_t rSize)
  236. {
  237.     BLOCKHDR *b, *bp;
  238.     HEAP *h = (HEAP *) ptr;
  239.     size_t tsize = 0, size;
  240.  
  241.     if (cSize < PAGESIZE)
  242.         return -1;
  243.  
  244.     _lock_heap();
  245.  
  246.     // create the heap header
  247.  
  248.     h->numSysBlocks = 1;
  249.     h->sysBlocks[0] = ptr;
  250.  
  251.     h->cSize = cSize;
  252.     h->rSize = rSize;
  253.  
  254.     // add it to the list of heaps
  255.  
  256.     h->nextHeap = _firstHeap;
  257.     h->prevHeap = NULL;
  258.     if (_firstHeap)
  259.         _firstHeap->prevHeap = h;
  260.     else
  261.         _lastHeap = h;
  262.  
  263.     _firstHeap = h;
  264.  
  265.     // Setup zero length allocated block
  266.  
  267.     b = FIRSTBLOCK(h);
  268.     b->blockSize = 0;                   // size 0 , used, prev used.
  269.     b = NEXT(b);
  270.  
  271.     // If table has not been initialized, allocate block and initialize
  272.     if (!_linktable)
  273.     {
  274.         tsize = ALIGNUPBY(_smalloc_threshold * (sizeof(DLINK) / ALIGNMENT), ALIGNMENT);
  275.         _linktable = HDR2PTR(b);
  276.         b->blockSize = tsize;
  277.         b = NEXT(b);
  278.         _table_init();
  279.         tsize += sizeof(size_t);
  280.     }
  281.  
  282.     // Setup huge free block
  283.  
  284.     // Size of block is (committed size) - (heap header) -
  285.     //                  (zero length block + free block header + last block header) -
  286.     //                  (linktable size)
  287.     size = cSize - sizeof(HEAP) - 3 * sizeof(size_t) - tsize;
  288.     b->blockSize = size + F_FREE;
  289.  
  290.     // Set last block header
  291.     NEXT(b)->blockSize = 0 + F_PFREE;   // size 0, used, prev free.
  292.  
  293.     if (size < _smalloc_threshold)
  294.     {
  295.         bp = HDR4SIZE(size);
  296. #ifdef  BALANCEDFIT
  297.         _numSmall++;
  298. #endif
  299.     }
  300.     else
  301.     {
  302.         bp = _rover;
  303. #ifdef  BALANCEDFIT
  304.         _numBig++;
  305. #endif
  306.     }
  307.  
  308.     ADDFREEAFTER(b, bp);
  309.     SETFSIZE(b, size);
  310.  
  311.     _unlock_heap();
  312.     return 0;
  313. }
  314.  
  315.  
  316. /*---------------------------------------------------------------------*
  317.  
  318. Name            _heapadd - add a block to the heap
  319.  
  320. Usage           int _heapadd(void *block, size_t size);
  321.  
  322. Prototype in    malloc.h
  323.  
  324. Description     This function adds a new block of memory to the heap.
  325.                 The block must not have been previously allocated from
  326.                 the heap.
  327.  
  328. Return value    If the block can be successfully added to the heap,
  329.                 0 is returned; otherwise -1.
  330.  
  331. *---------------------------------------------------------------------*/
  332. /*
  333.    int _RTLENTRY _EXPFUNC _heapadd(void *ptr, size_t size)
  334.    {
  335.    return _vheapadd(ptr, size, size);
  336.    }
  337.  */
  338.  
  339.  
  340. /*---------------------------------------------------------------------*
  341.  
  342. Name            _heapresize - resize a heap
  343.  
  344. Usage           int _heapresize (HEAP * h, size_t newSize);
  345.  
  346. Prototype in    malloc.h
  347.  
  348. Description     This function adds a new block of memory to the heap.
  349.                 The block must not have been previously allocated from
  350.                 the heap.
  351.  
  352. Return value    If the block can be successfully added to the heap,
  353.                 0 is returned; otherwise -1.
  354.  
  355. *---------------------------------------------------------------------*/
  356.  
  357. static int _RTLENTRY _EXPFUNC _heapresize(HEAP * h, size_t cSize)
  358. {
  359.     size_t delta;
  360.     BLOCKHDR *b;
  361.  
  362.     cSize = ALIGNDNBY(cSize, PAGESIZE);
  363.  
  364.     b = LASTBLOCK(h);
  365.  
  366.     if (cSize < h->cSize)
  367.     {
  368.         // shrink
  369.         if (ISPFREE(b))
  370.         {
  371.             b = PFREE(b);
  372.             delta = h->cSize - cSize;
  373.  
  374.             //if (SIZE(b) + MINFREE < delta)
  375.             if (SIZE(b) - MINFREE < delta)
  376.                 return -1;
  377.  
  378.             _lock_heap();
  379.  
  380.             b->blockSize -= delta;
  381.             SETFSIZE(b, SIZE(b));
  382.             NEXT(b)->blockSize = 0 + F_PFREE;
  383.         if (SIZE(b)<_smalloc_threshold)
  384.         {
  385.             // the block needs to move
  386.             REMOVEFREE(b);
  387.             ADDFREEAFTER(b, HDR4SIZE(SIZE(b)));
  388.         }
  389.  
  390.             _unlock_heap();
  391.         }
  392.         else
  393.             return -1;
  394.     }
  395.     else
  396.     {
  397.         // grow
  398.  
  399.         _lock_heap();
  400.  
  401.         delta = cSize - h->cSize;
  402.  
  403.         b->blockSize += delta - sizeof(size_t);             // was 0, now it is cSize
  404.  
  405.         NEXT(b)->blockSize = 0;
  406.  
  407.         gfree(HDR2PTR(b));
  408.  
  409.         h->cSize += delta;
  410.         _unlock_heap();
  411.  
  412.     }
  413.  
  414.     return 0;
  415. }
  416.  
  417.  
  418. /*---------------------------------------------------------------------*
  419.  
  420. Name            _get_more_heap - allocate more memory from the system for heap
  421.  
  422. Usage           void  _get_more_heap(size_t minSize);
  423.  
  424. Prototype in    local
  425.  
  426. Description     This function allocates more system memory by growing a heap
  427.                                 or adding a new one.
  428.  
  429. Return value    none.
  430.  
  431. *---------------------------------------------------------------------*/
  432.  
  433. static int _get_more_heap(size_t minSize)
  434. {
  435.     HEAP *h;
  436.     void *v;
  437.     size_t vsize;
  438.     size_t csize;
  439.     size_t aMinSize = ALIGNUPBY(minSize, PAGESIZE);
  440.  
  441.     if (!avail)
  442.         avail = _phys_avail();
  443.  
  444.     if (!_linktable)
  445.         aMinSize += ALIGNUPBY(_smalloc_threshold * (sizeof(DLINK) / ALIGNMENT) + sizeof(HEAP)+12, PAGESIZE);
  446.  
  447.     for (h = _firstHeap; h; h = h->nextHeap)
  448.     {
  449.         if (h->rSize - h->cSize > aMinSize)
  450.         {
  451.             size_t newSize = MIN(h->rSize, h->cSize + ALIGNUPBY(aMinSize, avail > __allocated + _virt_chunk_size ? _virt_chunk_size : _virt_chunk_size2));
  452.  
  453.             if (_virt_commit((char *) h + h->cSize, newSize - h->cSize) != 0)
  454.             {
  455.                 // should never fail
  456.                 _lock_heap();
  457.                 __allocated += newSize - h->cSize;
  458.                 _heapresize(h, newSize);
  459.                 _unlock_heap();
  460.                 return 0;
  461.             }
  462.         // otherwise, try to commit PAGESIZE
  463.         else if(_virt_commit ((char *) h+h->cSize, PAGESIZE))
  464.         {
  465.             __allocated+= PAGESIZE;
  466.             _heapresize(h, h->cSize+PAGESIZE);
  467.             return 0;
  468.         }
  469.         // we are out of memory, not worth trying more
  470.         else return -1;
  471.         }
  472.     }
  473.  
  474.     if (_virt_reserve(MAX(_virt_heap_size, aMinSize), &v, &vsize) == 0)
  475.         return -1;
  476.  
  477.     csize = ALIGNUPBY(aMinSize + PAGESIZE, avail > __allocated + _virt_chunk_size ? _virt_chunk_size : _virt_chunk_size2);
  478.  
  479.     for (h = _firstHeap; h; h = h->nextHeap)
  480.     {
  481.         if ((char *) h + h->rSize == v && h->numSysBlocks < MAXSYSBLOCKS)
  482.         {
  483.             size_t g = h->rSize - h->cSize;
  484.  
  485.             // merge the heaps and commit overlapping
  486.  
  487.             if (g)
  488.             {
  489.                 if (_virt_commit((char *) h + h->cSize, g) != 0)
  490.                 {
  491.                     __allocated += g;
  492.                     _heapresize(h, h->rSize);
  493.                 }
  494.                 else
  495.                     return -1;
  496.             }
  497.  
  498.             if (_virt_commit(v, csize - g) != 0)
  499.             {
  500.                 _lock_heap();
  501.                 __allocated += csize - g;
  502.                 h->sysBlocks[h->numSysBlocks++] = v;
  503.                 h->rSize += vsize;
  504.                 _heapresize(h, h->cSize + csize - g);
  505.                 _unlock_heap();
  506.                 return 0;
  507.             }
  508.             else
  509.                 return -1;
  510.         }
  511.     }
  512.  
  513.     if (_virt_commit(v, csize) == 0)
  514.     {
  515.         _virt_release(v);
  516.         return -1;
  517.     }
  518.  
  519.     // should never fail
  520.  
  521.     __allocated += csize;
  522.     _vheapadd(v, csize, vsize);
  523.     return 0;
  524. }
  525.  
  526.  
  527. /*---------------------------------------------------------------------*
  528.  
  529. Name            _release_heap_at
  530.  
  531. Usage
  532.  
  533. Prototype in
  534.  
  535. Description
  536.  
  537.  
  538. Return value
  539.  
  540. *---------------------------------------------------------------------*/
  541.  
  542. static int _release_heap_at(BLOCKHDR * b)
  543. {
  544.     HEAP *h;
  545.     BLOCKHDR *bn = NEXT(b);
  546.     size_t delta;
  547.     size_t freethreshold = avail > __allocated ? _virt_chunk_free : _virt_chunk_free2;
  548.  
  549.     if (b->blockSize-MINFREE < freethreshold)
  550.         return 0;
  551.  
  552.     delta = ALIGNDNBY(b->blockSize-MINFREE, freethreshold);
  553.  
  554.     for (h = _firstHeap; h; h = h->nextHeap)
  555.     {
  556.         if (LASTBLOCK(h) == bn)
  557.         {
  558.             // we can shrink this heap
  559.  
  560.             size_t newSize = h->cSize - delta;
  561.  
  562.             _lock_heap();
  563.  
  564.             // we made sure it will not fail
  565.             _heapresize(h, newSize);
  566.  
  567.             while ((char *) h + newSize <= h->sysBlocks[h->numSysBlocks - 1])
  568.             {
  569.                 // release attached block
  570.  
  571.                 size_t s = h->cSize - (h->sysBlocks[--h->numSysBlocks] -(char*)h);
  572.  
  573.                 _virt_decommit(h->sysBlocks[h->numSysBlocks], s);
  574.                 __allocated -= s;
  575.  
  576.                 _virt_release(h->sysBlocks[h->numSysBlocks]);
  577.  
  578.                 h->cSize = h->rSize = h->sysBlocks[h->numSysBlocks] - (char *) h;
  579.  
  580.             }
  581.  
  582.             _virt_decommit(h->sysBlocks[h->numSysBlocks - 1] + newSize, h->cSize - newSize);
  583.             __allocated -= h->cSize - newSize;
  584.             h->cSize = newSize;
  585.             _unlock_heap();
  586.             return 1;
  587.         }
  588.     }
  589.  
  590.     return 0;
  591. }
  592.  
  593.  
  594. /*---------------------------------------------------------------------*
  595.  
  596. Name            free - free an allocated block
  597.  
  598. Usage           void free(void *block);
  599.  
  600. Prototype in
  601.  
  602. Description     Return a block to the heap.  The block must have
  603.                 previously allocated with malloc, realloc, or calloc.
  604.                 If the block pointer is NULL, no action is performed.
  605.  
  606.                 There is an internal routine called _free which is
  607.                 identical, except that it does not call the _free_hook
  608.                 routine.  This should be used for internal calls to
  609.                 free that do not refer to user-specified blocks.
  610.  
  611. Return value    None.
  612.  
  613. *---------------------------------------------------------------------*/
  614.  
  615. void _RTLENTRY _EXPFUNC gfree(void *block)
  616. {
  617.     BLOCKHDR *b, *nb, *bp;
  618.     size_t s;
  619.  
  620.  
  621.     if (!block)
  622.         return;
  623.  
  624.     b = PTR2HDR(block);
  625.  
  626.     _lock_heap();
  627.  
  628.     if (ISPFREE(b))
  629.     {
  630.         // previous block is free, merge it
  631.  
  632.         BLOCKHDR *bp = PFREE(b);
  633.  
  634. #ifdef  BALANCEDFIT
  635.         if (bp->blockSize >= _smalloc_threshold)
  636.             _numBig--;
  637.         else
  638.             _numSmall--;
  639. #endif
  640.  
  641.         bp->blockSize += SIZE(b) + sizeof(size_t);
  642.         b = bp;
  643.  
  644.         if (_rover == b)
  645.             _rover = _rover->nextFree;
  646.         REMOVEFREE(b);
  647.     }
  648.     else
  649.     {
  650.         // can't merge back, mark it free simply and add to free list
  651.         b->blockSize |= F_FREE;
  652.     }
  653.  
  654.     if (ISFREE(nb = NEXT(b)))
  655.     {
  656.         // merge forward
  657.         b->blockSize += SIZE(nb) + sizeof(size_t);
  658.  
  659.         if (_rover == nb)
  660.             _rover = nb->nextFree;
  661.  
  662. #ifdef  BALANCEDFIT
  663.         if (nb->blockSize >= _smalloc_threshold)
  664.             _numBig--;
  665.         else
  666.             _numSmall--;
  667. #endif
  668.  
  669.         REMOVEFREE(nb);
  670.     }
  671.  
  672.     NEXT(b)->blockSize |= F_PFREE;
  673.  
  674.     // reinsert b to free list
  675.     s = SIZE(b);
  676.  
  677.     if (s < _smalloc_threshold)
  678.     {
  679.         bp = HDR4SIZE(s);
  680. #ifdef  BALANCEDFIT
  681.         _numSmall++;
  682. #endif
  683.     }
  684.     else
  685.     {
  686.         bp = _rover->nextFree;
  687. #ifdef  BALANCEDFIT
  688.         _numBig++;
  689. #endif
  690.     }
  691.  
  692.     ADDFREEAFTER(b, bp);
  693.     SETFSIZE(b, s);
  694.  
  695.     _unlock_heap();
  696.  
  697.     // check if we can shrink the heap
  698.     if (NEXT(b)->blockSize == 0 + F_PFREE && b->blockSize > (avail > __allocated ? _virt_chunk_free : _virt_chunk_free2))
  699.     {
  700.         _release_heap_at(b);
  701.     }
  702. }
  703.  
  704.  
  705. /*---------------------------------------------------------------------*
  706.  
  707. Name            malloc - allocate a block from the heap
  708.  
  709. Usage           void * malloc(size_t size);
  710.  
  711. Prototype in    local
  712.  
  713. Description     This function allocates a block from the heap.
  714.                 The contents of the block are undefined.
  715.                 If the size of the block is less than 64K, the
  716.                 block is guaranteed to not cross a 64K boundary.
  717.  
  718. Return value    If the block can be successfully allocated, the
  719.                 address of the block is returned; otherwise NULL
  720.                 is returned.
  721.  
  722. *---------------------------------------------------------------------*/
  723.  
  724. void *_RTLENTRY _EXPFUNC gmalloc(size_t size)
  725. {
  726.     size_t aSize;
  727.     size_t saveSize;
  728.     BLOCKHDR *fh;
  729.  
  730.     if (!size)
  731.         return NULL;
  732.  
  733.     if (size < MINSIZE)
  734.         aSize = MINSIZE;
  735.     else
  736.         aSize = ALIGNUPBY(size, ALIGNMENT);
  737.  
  738.     if (!_linktable)
  739.         _get_more_heap(1);
  740.  
  741.  
  742. #ifdef  STAT
  743.     n++;
  744. #endif
  745.  
  746.     _lock_heap();
  747.  
  748.     if (aSize < _smalloc_threshold)
  749.     {
  750.         fh = HDR4SIZE(aSize);
  751.  
  752. #if !defined(WORSTFIT)
  753.         if (fh->nextFree != fh)
  754.         {
  755.             fh = fh->nextFree;
  756.             fh->blockSize &= ~F_FREE;   // size remains, but now it's used
  757.  
  758.             NEXT(fh)->blockSize &= ~F_PFREE;
  759. #ifdef  BALANCEDFIT
  760.             _numSmall--;
  761. #endif
  762.             REMOVEFREE(fh);
  763.             _unlock_heap();
  764.             return HDR2PTR(fh);
  765.         }
  766. #endif
  767. #ifdef BALANCEDFIT
  768.         if (_numSmall > _smalloc_threshold / (ALIGNMENT * 4) && _numSmall > _numBig * 4)
  769. #endif
  770. #if defined(BESTFIT) || defined (BALANCEDFIT)
  771.         {
  772.             // scan the free list vector for an entry. It will be terminated
  773.             // by the 'stopper', whose ->nextFree is NULL.
  774.  
  775. #ifdef  UNROLL
  776.             fh = HDR4SIZE(aSize + ALIGNMENT);
  777.             while (1)
  778.             {
  779.                 if (fh->nextFree != fh)
  780.                     break;
  781.                 // cmp  eax, [eax+4]        ;; 1+2
  782.                 // jne  @@break                 ;; 1
  783.  
  784.                 ((DLINK *) fh)++;
  785.                 // add  eax, 8                  ;; 1
  786.  
  787.                 if (fh->nextFree != fh)
  788.                     break;
  789.                 ((DLINK *) fh)++;
  790.                 if (fh->nextFree != fh)
  791.                     break;
  792.                 ((DLINK *) fh)++;
  793.                 if (fh->nextFree != fh)
  794.                     break;
  795.                 ((DLINK *) fh)++;
  796.                 if (fh->nextFree != fh)
  797.                     break;
  798.                 ((DLINK *) fh)++;
  799.                 if (fh->nextFree != fh)
  800.                     break;
  801.                 ((DLINK *) fh)++;
  802.                 if (fh->nextFree != fh)
  803.                     break;
  804.                 ((DLINK *) fh)++;
  805.                 if (fh->nextFree != fh)
  806.                     break;
  807.                 ((DLINK *) fh)++;
  808.                 if (fh->nextFree != fh)
  809.                     break;
  810.                 ((DLINK *) fh)++;
  811.                 if (fh->nextFree != fh)
  812.                     break;
  813.                 ((DLINK *) fh)++;
  814.                 if (fh->nextFree != fh)
  815.                     break;
  816.                 ((DLINK *) fh)++;
  817.                 if (fh->nextFree != fh)
  818.                     break;
  819.                 ((DLINK *) fh)++;
  820.                 if (fh->nextFree != fh)
  821.                     break;
  822.                 ((DLINK *) fh)++;
  823.                 if (fh->nextFree != fh)
  824.                     break;
  825.                 ((DLINK *) fh)++;
  826.                 if (fh->nextFree != fh)
  827.                     break;
  828.                 ((DLINK *) fh)++;
  829.                 if (fh->nextFree != fh)
  830.                     break;
  831.                 ((DLINK *) fh)++;
  832.             }
  833. #elif   defined(UNROLL2)
  834.             fh = HDR4SIZE(aSize + ALIGNMENT);
  835.             while (1)
  836.             {
  837.                 BLOCKHDR *f2 = fh;      //      ;; mov edx, eax;        1
  838.  
  839.                 if (((BLOCKHDR *) (((DLINK *) f2)[0]))->nextFree != fh)
  840.                     break;
  841.                 // cmp  eax, [edx+4]            ;; 1
  842.                 // jne  @@break                         ;; 1
  843.  
  844.                 ((DLINK *) fh)++;
  845.                 // add  eax, 8                          ;; 1
  846.  
  847.                 if (((BLOCKHDR *) (((DLINK *) f2) + 1))->nextFree != fh)
  848.                     break;
  849.                 ((DLINK *) fh)++;
  850.                 if (((BLOCKHDR *) (((DLINK *) f2) + 2))->nextFree != fh)
  851.                     break;
  852.                 ((DLINK *) fh)++;
  853.                 if (((BLOCKHDR *) (((DLINK *) f2) + 3))->nextFree != fh)
  854.                     break;
  855.                 ((DLINK *) fh)++;
  856.                 if (((BLOCKHDR *) (((DLINK *) f2) + 4))->nextFree != fh)
  857.                     break;
  858.                 ((DLINK *) fh)++;
  859.                 if (((BLOCKHDR *) (((DLINK *) f2) + 5))->nextFree != fh)
  860.                     break;
  861.                 ((DLINK *) fh)++;
  862.                 if (((BLOCKHDR *) (((DLINK *) f2) + 6))->nextFree != fh)
  863.                     break;
  864.                 ((DLINK *) fh)++;
  865.                 if (((BLOCKHDR *) (((DLINK *) f2) + 7))->nextFree != fh)
  866.                     break;
  867.                 ((DLINK *) fh)++;
  868.                 if (((BLOCKHDR *) (((DLINK *) f2) + 8))->nextFree != fh)
  869.                     break;
  870.                 ((DLINK *) fh)++;
  871.                 if (((BLOCKHDR *) (((DLINK *) f2) + 9))->nextFree != fh)
  872.                     break;
  873.                 ((DLINK *) fh)++;
  874.                 if (((BLOCKHDR *) (((DLINK *) f2) + 10))->nextFree != fh)
  875.                     break;
  876.                 ((DLINK *) fh)++;
  877.                 if (((BLOCKHDR *) (((DLINK *) f2) + 11))->nextFree != fh)
  878.                     break;
  879.                 ((DLINK *) fh)++;
  880.                 if (((BLOCKHDR *) (((DLINK *) f2) + 12))->nextFree != fh)
  881.                     break;
  882.                 ((DLINK *) fh)++;
  883.                 if (((BLOCKHDR *) (((DLINK *) f2) + 13))->nextFree != fh)
  884.                     break;
  885.                 ((DLINK *) fh)++;
  886.                 if (((BLOCKHDR *) (((DLINK *) f2) + 14))->nextFree != fh)
  887.                     break;
  888.                 ((DLINK *) fh)++;
  889.                 if (((BLOCKHDR *) (((DLINK *) f2) + 15))->nextFree != fh)
  890.                     break;
  891.                 ((DLINK *) fh)++;
  892.             }
  893.  
  894. #else
  895.             for (fh = HDR4SIZE(aSize + ALIGNMENT); fh->nextFree == fh; ((DLINK *) fh)++)
  896.                 ;
  897.             //      ...
  898.             //      @@loop: add     eax, 8                      ;;      1
  899.             //                      cmp     eax, [eax+4]        ;;      1+2
  900.             //                      je      @@loop              ;;      3
  901. #endif
  902.  
  903.             if (fh->nextFree)
  904.                 fh = fh->nextFree;      // found
  905.  
  906.             else
  907.             {
  908.                 // use the _rover
  909.                 fh = _rover;
  910.                 if (fh == &_freeStart)
  911.                     fh = fh->nextFree;
  912.             }
  913.         }
  914. #endif
  915.  
  916. #ifdef BALANCEDFIT
  917.         else
  918. #endif
  919.  
  920. #if !defined(BESTFIT)
  921.         {
  922.             // we won't need to search the 'big list' _rover should be perfect
  923.  
  924.             fh = _rover;
  925.             if (fh == &_freeStart)
  926.                 fh = fh->nextFree;
  927.  
  928.             // if 'big block list' is empty, find a small slot
  929.  
  930.             if (_freeStart.nextFree == &_freeStart)
  931.             {
  932.                 // scan the free list vector for an entry. It will be terminated
  933.                 // by the 'stopper', whose ->nextFree is NULL.
  934.  
  935. #ifdef  UNROLL
  936. #if !defined(WORSTFIT)
  937.                 fh = HDR4SIZE(aSize + ALIGNMENT);
  938. #else
  939.                 fh = HDR4SIZE(aSize);
  940. #endif
  941.                 while (1)
  942.                 {
  943.                     if (fh->nextFree != fh)
  944.                         break;
  945.                     ((DLINK *) fh)++;
  946.                     if (fh->nextFree != fh)
  947.                         break;
  948.                     ((DLINK *) fh)++;
  949.                     if (fh->nextFree != fh)
  950.                         break;
  951.                     ((DLINK *) fh)++;
  952.                     if (fh->nextFree != fh)
  953.                         break;
  954.                     ((DLINK *) fh)++;
  955.                     if (fh->nextFree != fh)
  956.                         break;
  957.                     ((DLINK *) fh)++;
  958.                     if (fh->nextFree != fh)
  959.                         break;
  960.                     ((DLINK *) fh)++;
  961.                     if (fh->nextFree != fh)
  962.                         break;
  963.                     ((DLINK *) fh)++;
  964.                     if (fh->nextFree != fh)
  965.                         break;
  966.                     ((DLINK *) fh)++;
  967.                     if (fh->nextFree != fh)
  968.                         break;
  969.                     ((DLINK *) fh)++;
  970.                     if (fh->nextFree != fh)
  971.                         break;
  972.                     ((DLINK *) fh)++;
  973.                     if (fh->nextFree != fh)
  974.                         break;
  975.                     ((DLINK *) fh)++;
  976.                     if (fh->nextFree != fh)
  977.                         break;
  978.                     ((DLINK *) fh)++;
  979.                     if (fh->nextFree != fh)
  980.                         break;
  981.                     ((DLINK *) fh)++;
  982.                     if (fh->nextFree != fh)
  983.                         break;
  984.                     ((DLINK *) fh)++;
  985.                     if (fh->nextFree != fh)
  986.                         break;
  987.                     ((DLINK *) fh)++;
  988.                     if (fh->nextFree != fh)
  989.                         break;
  990.                     ((DLINK *) fh)++;
  991.                 }
  992. #elif   defined(UNROLL2)
  993. #if !defined(WORSTFIT)
  994.                 fh = HDR4SIZE(aSize + ALIGNMENT);
  995. #else
  996.                 fh = HDR4SIZE(aSize);
  997. #endif
  998.                 while (1)
  999.                 {
  1000.                     BLOCKHDR *f2 = fh;  //      ;; mov edx, eax;        1
  1001.  
  1002.                     if (((BLOCKHDR *) (((DLINK *) f2) + 0))->nextFree != fh)
  1003.                         break;
  1004.                     // cmp  eax, [edx+4]        ;; 1
  1005.                     // jne  @@break             ;; 1
  1006.  
  1007.                     ((DLINK *) fh)++;
  1008.                     // add  eax, 8              ;; 1
  1009.  
  1010.                     if (((BLOCKHDR *) (((DLINK *) f2) + 1))->nextFree != fh)
  1011.                         break;
  1012.                     ((DLINK *) fh)++;
  1013.                     if (((BLOCKHDR *) (((DLINK *) f2) + 2))->nextFree != fh)
  1014.                         break;
  1015.                     ((DLINK *) fh)++;
  1016.                     if (((BLOCKHDR *) (((DLINK *) f2) + 3))->nextFree != fh)
  1017.                         break;
  1018.                     ((DLINK *) fh)++;
  1019.                     if (((BLOCKHDR *) (((DLINK *) f2) + 4))->nextFree != fh)
  1020.                         break;
  1021.                     ((DLINK *) fh)++;
  1022.                     if (((BLOCKHDR *) (((DLINK *) f2) + 5))->nextFree != fh)
  1023.                         break;
  1024.                     ((DLINK *) fh)++;
  1025.                     if (((BLOCKHDR *) (((DLINK *) f2) + 6))->nextFree != fh)
  1026.                         break;
  1027.                     ((DLINK *) fh)++;
  1028.                     if (((BLOCKHDR *) (((DLINK *) f2) + 7))->nextFree != fh)
  1029.                         break;
  1030.                     ((DLINK *) fh)++;
  1031.                     if (((BLOCKHDR *) (((DLINK *) f2) + 8))->nextFree != fh)
  1032.                         break;
  1033.                     ((DLINK *) fh)++;
  1034.                     if (((BLOCKHDR *) (((DLINK *) f2) + 9))->nextFree != fh)
  1035.                         break;
  1036.                     ((DLINK *) fh)++;
  1037.                     if (((BLOCKHDR *) (((DLINK *) f2) + 10))->nextFree != fh)
  1038.                         break;
  1039.                     ((DLINK *) fh)++;
  1040.                     if (((BLOCKHDR *) (((DLINK *) f2) + 11))->nextFree != fh)
  1041.                         break;
  1042.                     ((DLINK *) fh)++;
  1043.                     if (((BLOCKHDR *) (((DLINK *) f2) + 12))->nextFree != fh)
  1044.                         break;
  1045.                     ((DLINK *) fh)++;
  1046.                     if (((BLOCKHDR *) (((DLINK *) f2) + 13))->nextFree != fh)
  1047.                         break;
  1048.                     ((DLINK *) fh)++;
  1049.                     if (((BLOCKHDR *) (((DLINK *) f2) + 14))->nextFree != fh)
  1050.                         break;
  1051.                     ((DLINK *) fh)++;
  1052.                     if (((BLOCKHDR *) (((DLINK *) f2) + 15))->nextFree != fh)
  1053.                         break;
  1054.                     ((DLINK *) fh)++;
  1055.                 }
  1056. #else
  1057.  
  1058. #if !defined(WORSTFIT)
  1059.                 for (fh = HDR4SIZE(aSize + ALIGNMENT); fh->nextFree == fh; ((DLINK *) fh)++)
  1060.                     ;
  1061. #else
  1062.                 for (fh = HDR4SIZE(aSize); fh->nextFree == fh; ((DLINK *) fh)++)
  1063.                     ;
  1064. #endif
  1065.  
  1066. #endif
  1067.                 if (fh->nextFree)
  1068.                     fh = fh->nextFree;  // found
  1069.                 else
  1070.                     fh = _rover;        // not found (out of memory)
  1071.             }
  1072.         }
  1073. #endif
  1074.     }
  1075.     else                                //  aSize >= _smalloc_threshold
  1076.     {
  1077.         if ((saveSize = (fh = _rover)->blockSize) < aSize)
  1078.         {
  1079.             _rover->blockSize = 0xFFFFFFFCL + F_FREE;
  1080.  
  1081. #ifdef  UNROLL
  1082.             fh = fh->nextFree;
  1083.             while (1)
  1084.             {
  1085.                 if (fh->blockSize >= aSize)
  1086.                     break;
  1087.                 fh = fh->nextFree;
  1088.                 if (fh->blockSize >= aSize)
  1089.                     break;
  1090.                 fh = fh->nextFree;
  1091.                 if (fh->blockSize >= aSize)
  1092.                     break;
  1093.                 fh = fh->nextFree;
  1094.                 if (fh->blockSize >= aSize)
  1095.                     break;
  1096.                 fh = fh->nextFree;
  1097.                 if (fh->blockSize >= aSize)
  1098.                     break;
  1099.                 fh = fh->nextFree;
  1100.                 if (fh->blockSize >= aSize)
  1101.                     break;
  1102.                 fh = fh->nextFree;
  1103.                 if (fh->blockSize >= aSize)
  1104.                     break;
  1105.                 fh = fh->nextFree;
  1106.                 if (fh->blockSize >= aSize)
  1107.                     break;
  1108.                 fh = fh->nextFree;
  1109.                 if (fh->blockSize >= aSize)
  1110.                     break;
  1111.                 fh = fh->nextFree;
  1112.                 if (fh->blockSize >= aSize)
  1113.                     break;
  1114.                 fh = fh->nextFree;
  1115.                 if (fh->blockSize >= aSize)
  1116.                     break;
  1117.                 fh = fh->nextFree;
  1118.                 if (fh->blockSize >= aSize)
  1119.                     break;
  1120.                 fh = fh->nextFree;
  1121.                 if (fh->blockSize >= aSize)
  1122.                     break;
  1123.                 fh = fh->nextFree;
  1124.                 if (fh->blockSize >= aSize)
  1125.                     break;
  1126.                 fh = fh->nextFree;
  1127.                 if (fh->blockSize >= aSize)
  1128.                     break;
  1129.                 fh = fh->nextFree;
  1130.                 if (fh->blockSize >= aSize)
  1131.                     break;
  1132.                 fh = fh->nextFree;
  1133.             }
  1134.  
  1135. #else
  1136.             for (fh = fh->nextFree; fh->blockSize < aSize; fh = fh->nextFree)
  1137. #ifdef  STAT
  1138.                 l++
  1139. #endif
  1140.                 ;
  1141. #endif
  1142.             _rover->blockSize = saveSize;
  1143.             if (fh == _rover)
  1144.                 fh = &_freeStart;
  1145.         }
  1146.     }
  1147.  
  1148.     if (fh != &_freeStart)
  1149.     {
  1150.         size_t fSize = SIZE(fh);
  1151.  
  1152.         if (fSize - aSize < MINFREEH)
  1153.         {
  1154.  
  1155.             fh->blockSize &= ~F_FREE;   // size remains, but now it's used
  1156.  
  1157.             NEXT(fh)->blockSize &= ~F_PFREE;
  1158.             if (fSize >= _smalloc_threshold)
  1159.             {
  1160.                 _rover = fh->nextFree;
  1161. #ifdef  BALANCEDFIT
  1162.                 _numBig--;
  1163. #endif
  1164.             }
  1165.  
  1166. #ifdef  BALANCEDFIT
  1167.             else
  1168.             {
  1169.                 _numSmall--;
  1170.             }
  1171. #endif
  1172.  
  1173.             REMOVEFREE(fh);
  1174.             _unlock_heap();
  1175.             return HDR2PTR(fh);
  1176.         }
  1177.         else
  1178.         {
  1179.             // split block
  1180.  
  1181.             BLOCKHDR *nh, *f;
  1182.             size_t s;
  1183.  
  1184.             fh->blockSize = aSize;      // that takes it too
  1185.  
  1186.             nh = NEXT(fh);
  1187.             s = fSize - aSize - sizeof(size_t);
  1188.             nh->blockSize = s + F_FREE;
  1189.  
  1190.             SETFSIZE(nh, s);
  1191.             if (s < _smalloc_threshold)
  1192.             {
  1193.                 f = HDR4SIZE(s);
  1194. #ifdef  BALANCEDFIT
  1195.                 if (fSize >= _smalloc_threshold)
  1196.                 {
  1197.                     _numSmall++;
  1198.                     _numBig--;
  1199.                 }
  1200. #endif
  1201.                 ADDFREEAFTER(nh, f);
  1202.                 if (fh == _rover)
  1203.                     _rover = fh->nextFree;
  1204.  
  1205.                 REMOVEFREE(fh);
  1206.             }
  1207.             else
  1208.             {
  1209.                 fh->prevFree->nextFree = nh;
  1210.                 nh->prevFree = fh->prevFree;
  1211.                 fh->nextFree->prevFree = nh;
  1212.                 nh->nextFree = fh->nextFree;
  1213.  
  1214.                 _rover = nh;
  1215.             }
  1216.  
  1217.             _unlock_heap();
  1218.             return HDR2PTR(fh);
  1219.         }
  1220.     }
  1221.     else
  1222.     {
  1223.         _unlock_heap();
  1224.  
  1225.         if (_get_more_heap(size + 64) == 0)
  1226.         {
  1227.             return gmalloc(size);
  1228.         }
  1229.  
  1230.         else
  1231.             return NULL;
  1232.     }
  1233. }
  1234.  
  1235.  
  1236. #include <windows.h>
  1237. #include <stdio.h>
  1238.  
  1239. size_t  _phys_avail(void)
  1240. {
  1241.     MEMORYSTATUS mst;
  1242.     mst.dwLength = sizeof(MEMORYSTATUS);
  1243.     GlobalMemoryStatus(&mst);
  1244.  
  1245.     return  mst.dwAvailPhys;
  1246. }
  1247.  
  1248. static int releaseHeap = 0;
  1249.  
  1250. void _EXPFUNC _free_heaps()
  1251. {
  1252.     HEAP *h;
  1253.     int i;
  1254.  
  1255.     if (releaseHeap)
  1256.     {
  1257.     for (h = _firstHeap;;)
  1258.     {
  1259.         void *nextH = h->nextHeap;
  1260.  
  1261.         for (i = --h->numSysBlocks; i>=0 ; i--)
  1262.         {
  1263.         size_t s = h->cSize - (h->sysBlocks[i] -(char*)h);
  1264.         void *p = h->sysBlocks[i];
  1265.  
  1266.         h->cSize = h->rSize = h->sysBlocks[i] - (char *) h;
  1267.  
  1268.         _virt_decommit(p, s);
  1269.         _virt_release(p);
  1270.         }
  1271.         if (nextH)
  1272.         h = nextH;
  1273.         else
  1274.         break;
  1275.     }
  1276.     }
  1277. }
  1278.  
  1279. static void set_releaseHeap()
  1280. {
  1281. #pragma exit set_releaseHeap 0
  1282.     releaseHeap = 1;
  1283. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement