home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / mslang / vm / src / vfree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-15  |  4.6 KB  |  186 lines

  1. /***
  2. * vfree.c - Free memory routines
  3. *
  4. *       Copyright (c) 1989-1992, Microsoft Corporation.  All rights reserved.
  5. *
  6. *******************************************************************************/
  7.  
  8. #include <version.h>
  9. #include <system.h>
  10. #include <vmassert.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <vmlist.h>
  14. #include <vmm.h>
  15. #include <vmbm.h>
  16.  
  17. extern PFBD _pfbdVirtHead;
  18. extern PFBD _pfbdVirtCurr;
  19. extern unsigned long _cVirtPageMax;
  20.  
  21. /*** VmFreeHbk
  22. *
  23. * Purpose:  To Free the allocated block specified
  24. *
  25. * Input:
  26. *       hbk The handle to the block to be freed
  27. *
  28. * Output:
  29. *
  30. * Exceptions:
  31. *
  32. * Notes:
  33. *   On a free it might be nice to free complete pages, however this
  34. *   causes terrible fragmentation. Its better to merge the free pages
  35. *   and reallocate them.
  36. *
  37. *   Also since free pages can only grow in size, cbMaxFree will stay
  38. *   the same or grow. But it can't shrink.
  39. *
  40. *************************************************************************/
  41. void VMFUNC __VmFreeHbk(
  42. HBK hbk
  43. ) {
  44. VPVOID      vp;
  45. PHDF        phdf;
  46. PHDB        phdb;
  47. HDF         hdf;
  48. unsigned    cb;
  49.  
  50.     int     fAddFree = TRUE, fMerge = FALSE;
  51.     HBK     hbkMerge;
  52.  
  53.    if (!_fVmInit || (unsigned long)hbk < (unsigned long)_hbkMin || (unsigned long)hbk >= (unsigned long)_hbkMax)
  54.       return;
  55.  
  56.     _fmemset( &hdf, 0, sizeof(HDF) );
  57.  
  58.     // load the page
  59.     phdb = __PVmLoadVp((VPVOID) hbk, FALSE);
  60.  
  61.    if (!phdb || phdb->fFree)
  62.       return;
  63.  
  64.     // unlock the block before freeing, if necessary
  65.  
  66.     while (phdb->cLock != 0)
  67.     {
  68.         __VmUnlockHbk(hbk, FALSE);
  69.         phdb = __PVmLoadVp((VPVOID) hbk, FALSE);
  70.     }
  71.  
  72.     // copy header
  73.  
  74.     _fmemcpy( &hdf, phdb, sizeof(HDB) );
  75.  
  76.     // if this was allocated by page, then free it by page
  77.     if(hdf.fByPage)
  78.     {
  79.         Assert(hdf.cPage > 0 && ((long)hbk % cbVmPage) == 0);
  80.  
  81.         // put on free list of free pages
  82.         __VmAddFreeBlock(&_pfbdVirtHead, &_pfbdVirtCurr, &_cVirtPageMax,
  83.                 hdf.cPage, (unsigned long)hbk);
  84.  
  85.         for(vp=(VPVOID) hbk; hdf.cPage>0; hdf.cPage--, vp += cbVmPage)
  86.         {
  87.             Assert( __CVmLockVp(vp) == 0 );
  88.             __VmFreePageVp( vp );
  89.         }
  90.         return;
  91.     }
  92.  
  93. // merge with the top block
  94. if( hdf.fAdjacent ) {
  95.  
  96.     hbkMerge = AddHbk(hbk, CbGetSize(hdf.cbSize));
  97.     phdf = __PVmLoadVp((VPVOID) hbkMerge, FALSE);
  98.  
  99.     // if it is free, then merge with the block below
  100.     if( phdf->fFree  &&
  101.     ((unsigned long) CbGetSize(hdf.cbSize) +
  102.      (unsigned long) CbGetSize(phdf->cbSize)) < cbBig ) {
  103.  
  104.     // add the size to the block before, also set the adjacent flag
  105.     fMerge = TRUE;
  106.     hdf.cbSize = CbMakeSize( CbGetSize(hdf.cbSize) +
  107.                  CbGetSize(phdf->cbSize),
  108.                  phdf->fAdjacent );
  109.  
  110.     // take this guy out of the list
  111.     __VmFreeLink(phdf->hbkBackHdf, phdf->hbkNextHdf);
  112.     _gvmbm.cFree--;
  113.  
  114.     // see if this was the last block
  115.     if( hbkMerge == _gvmbm.hbkLastBlock )
  116.         _gvmbm.hbkLastBlock = hbk;
  117.     }
  118.     }
  119.  
  120. // merge with the bottom block
  121. if( hdf.szbkBack.fAdjacent ) {
  122.  
  123.     cb = CbGetSize(hdf.szbkBack.cbSize);
  124.     hbkMerge = AddHbk(hbk, - (long) cb);
  125.     phdf = __PVmLoadVp((VPVOID) hbkMerge, FALSE);
  126.     Assert( cb == CbGetSize(phdf->cbSize) );
  127.  
  128.     if( phdf->fFree  &&
  129.     ((unsigned long) CbGetSize(hdf.cbSize) + cb) < cbBig ) {
  130.  
  131.     // we don't want to add anything to the free list
  132.     // because the one below will take it
  133.     fAddFree = FALSE;
  134.     fMerge = TRUE;
  135.  
  136.     // add the size to the block before, also set the adjacent flag
  137.     hdf.cbSize = CbMakeSize( CbGetSize(hdf.cbSize) + cb,
  138.                  hdf.fAdjacent );
  139.     hdf.szbkBack = phdf->szbkBack;
  140.     hdf.hbkBackHdf = phdf->hbkBackHdf;
  141.     hdf.hbkNextHdf = phdf->hbkNextHdf;
  142.  
  143.     // see if this was the last block
  144.     if( hbk == _gvmbm.hbkLastBlock )
  145.         _gvmbm.hbkLastBlock = hbkMerge;
  146.  
  147.     // adjust the free page to add
  148.     hbk = hbkMerge;
  149.     }
  150.     }
  151.  
  152. // Now the page above me may need its back pointer adjusted
  153. // if I did any kind of merge.
  154. if( fMerge  &&  hdf.fAdjacent ) {
  155.  
  156.     // get the block above and set it's back size and adjacent bit
  157.     // to match the current block
  158.     phdb = __PVmLoadVp((VPVOID) AddHbk(hbk, CbGetSize(hdf.cbSize)), TRUE);
  159.     Assert( phdb != NULL );
  160.     phdb->szbkBack.cbSize = hdf.cbSize;
  161.     }
  162.  
  163. // make this a free page
  164. phdf = __PVmLoadVp((VPVOID) hbk, TRUE);
  165. *phdf = hdf;
  166. phdf->fFree = TRUE;
  167.  
  168. // if required add this to the end of the free list
  169. if( fAddFree )
  170.     __VmFreeLinkEnd(hbk, CbGetSize(hdf.cbSize));
  171.  
  172. // check the free list
  173. #ifdef VMDEBUG
  174. hbk = _gvmbm.hbkFreeStart;
  175. hbkMerge = NULL;
  176. while( hbk ) {
  177.     phdf = __PVmLoadVp( (VPVOID) hbk, FALSE );
  178.     Assert( phdf != NULL );
  179.     Assert( phdf->fFree == TRUE );
  180.     Assert( phdf->hbkBackHdf == hbkMerge );
  181.     hbkMerge = hbk;
  182.     hbk = phdf->hbkNextHdf;
  183.     }
  184. #endif
  185. }
  186.