home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / Memory / MemMgr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-13  |  11.2 KB  |  470 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        MemMgr.cpp
  3.  
  4.     Contains:    Procedural API for memory heaps
  5.  
  6.     Owned by:    Jens Alfke
  7.  
  8.     Copyright:    © 1994 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.     
  12.          <2>     9/13/96    jpa        1371387: Speed optimizations.
  13.          <8>    10/24/95    jpa        1293441: Added slush-fund.
  14.          <7>      8/4/95    DM        Leak detection [1267956]
  15.          <6>      6/7/95    jpa        Added MMConfiguration [1246897]
  16.          <5>      5/4/95    jpa        Added MMGetFreeSpace [1235657] and MMMove
  17.                                     [1246077]
  18.          <4>     12/5/94    jpa        Nuked errant pragma lib_export's. [1195676]
  19.          <3>    10/24/94    jpa        Constness [1194286]. MMSplice [1194287].
  20.          <2>     9/29/94    RA        1189812: Mods for 68K build.
  21.          <1>     9/14/94    jpa        first checked in
  22.  
  23.     To Do:
  24.     In Progress:
  25.         
  26. */
  27.  
  28.  
  29. #ifndef _MEMMGR_
  30. #include "MemMgr.h"
  31. #endif
  32.  
  33. #ifndef _MEMMGRPV_
  34. #include "MemMgrPv.h"
  35. #endif
  36.  
  37. #ifndef _MEMDEBG_
  38. #include "MemDebg.h"
  39. #endif
  40.  
  41.  
  42. #undef SURVEY_SIZES
  43.  
  44.  
  45. //==============================================================================
  46. // GLOBAL VARIABLES
  47. //==============================================================================
  48.  
  49.  
  50. BestFitHeap    *gDefaultHeap;
  51.  
  52.  
  53. #ifdef SURVEY_SIZES
  54.     const int kNSizeBins = 100;
  55.     unsigned long gSizeBin[kNSizeBins];
  56.     unsigned long gNAllocations;
  57. #endif
  58.  
  59.  
  60. //========================================================================================
  61. // HEAP MANAGEMENT
  62. //========================================================================================
  63.  
  64.  
  65. long
  66. MMConfiguration( )
  67. {
  68.     return MM_DEBUG ?kMMDebugConfigMask :0;
  69. }
  70.  
  71.  
  72. //------------------------------------------------------------------------------
  73. // MMNewHeap
  74. //------------------------------------------------------------------------------
  75.  
  76. MemHeap* MMNewHeap( MMHeapLocation loc, size_t initialSize, size_t growAmount,
  77.                     const char *name )
  78. {
  79.     BestFitHeap *heap = new( (MMHeapLocation)loc )
  80.                                 BestFitHeap(initialSize,growAmount,0, (MMHeapLocation)loc);
  81.     if( heap ) {
  82.         heap->IBestFitHeap();
  83.         if( name )
  84.             heap->SetDescription(name);
  85. #if MM_DEBUG
  86.         if( gValidate>0 ) {
  87.             heap->SetZapOnAllocate(kMMTrue);
  88.             heap->SetZapOnFree(kMMTrue);
  89.             heap->SetAutoValidation(kMMTrue);
  90.         }
  91. #endif
  92.     }
  93.     return (MemHeap*) heap;
  94. }
  95.  
  96.  
  97. //------------------------------------------------------------------------------
  98. // MMDisposeHeap
  99. //------------------------------------------------------------------------------
  100.  
  101. void
  102. MMDisposeHeap( MemHeap *heap )
  103. {
  104.     delete (BestFitHeap*) heap;
  105. }
  106.  
  107.  
  108. //------------------------------------------------------------------------------
  109. // MMGetDefaultHeap
  110. //------------------------------------------------------------------------------
  111.  
  112. MemHeap*
  113. MMGetDefaultHeap( )
  114. {
  115.     return (MemHeap*) gDefaultHeap;
  116. }
  117.  
  118.  
  119. //------------------------------------------------------------------------------
  120. // MMSetDefaultHeap
  121. //------------------------------------------------------------------------------
  122.  
  123. MemHeap*
  124. MMSetDefaultHeap( MemHeap *heap )
  125. {
  126.     MM_ASSERT(heap!=kMMNULL);
  127.     MemHeap *oldDefault = (MemHeap*)gDefaultHeap;
  128.     gDefaultHeap = (BestFitHeap*)heap;
  129.     return oldDefault;
  130. }
  131.  
  132.  
  133. //========================================================================================
  134. // FREE SPACE MANAGEMENT
  135. //========================================================================================
  136.  
  137.  
  138. //----------------------------------------------------------------------------------------
  139. // MMGetFreeSpace
  140. //----------------------------------------------------------------------------------------
  141.  
  142. void
  143. MMGetFreeSpace( MemHeap *heapID, size_t *total, size_t *contig )
  144. {
  145.     BestFitHeap *heap = (BestFitHeap*)( heapID ?heapID :MMGetDefaultHeap() );
  146.     
  147.     size_t sysTotal, sysContig, heapTotal, heapContig;
  148.     
  149.     MMSystemFreeSpace(heap->GetLocation(),&sysTotal,&sysContig);
  150.     heapTotal = heap->BytesFree();
  151.     size_t incr = heap->GetSizeIncrement();
  152.     
  153.     if( sysContig < incr || sysTotal < incr+kPlatformMinFreeSpace ) {
  154.         // Not enough memory to grow heap, so we're limited to space in heap.
  155.         heapTotal = sysTotal;
  156.         heapContig = heap->LargestFreeBlock();
  157.     } else {
  158.         heapTotal += sysTotal;
  159.         heapContig = sysContig;
  160.     }
  161.     
  162.     if( total ) *total = heapTotal;
  163.     if( contig) *contig= heapContig;
  164. }
  165.  
  166.  
  167. MMBoolean
  168. MMAllocateSlushFund( MemHeap *heapID, size_t size, size_t allocSizeLimit )
  169. {
  170.     MemoryHeap *heap = heapID ?(MemoryHeap*)heapID :gDefaultHeap;
  171.     return heap->AllocateSlushFund(size,allocSizeLimit);
  172. }
  173.  
  174.  
  175. size_t
  176. MMSlushFundSize( MemHeap *heapID )
  177. {
  178.     MemoryHeap *heap = heapID ?(MemoryHeap*)heapID :gDefaultHeap;
  179.     return heap->GetSlushFundSize();
  180. }
  181.  
  182.  
  183. size_t
  184. MMFreeSlushFund( MemHeap *heapID )
  185. {
  186.     MemoryHeap *heap = heapID ?(MemoryHeap*)heapID :gDefaultHeap;
  187.     return heap->FreeSlushFund();
  188. }
  189.  
  190.  
  191.  
  192. //========================================================================================
  193. // OPERATIONS ON BLOCKS
  194. //========================================================================================
  195.  
  196.  
  197. #ifdef SURVEY_SIZES
  198. static void SurveySize( size_t size )
  199. {
  200.     size_t index = (size+3)>>2;
  201.     if( index >= kNSizeBins )
  202.         index = kNSizeBins-1;
  203.     gSizeBin[index]++;
  204.     gNAllocations++;
  205. }
  206. #endif
  207.  
  208.  
  209. //------------------------------------------------------------------------------
  210. // MMAllocate
  211. //------------------------------------------------------------------------------
  212.  
  213. void*
  214. MMAllocate( size_t size )
  215. {
  216. #if MM_DEBUG
  217.     if( (MMULong)size>BestFitBlock_kMaxBlockSize ) {
  218.         MM_WARN("Bogus size 0x%08lx for MMAllocate",size);
  219.         return kMMNULL;
  220.     }
  221.     
  222.     if( gHeapChecking>0 )
  223.         MMValidateHeap((MemHeap*)gDefaultHeap);
  224. #endif
  225.  
  226. #ifdef SURVEY_SIZES
  227.     SurveySize(size);
  228. #endif
  229.  
  230.     return gDefaultHeap->Allocate(size);
  231. }
  232.  
  233.  
  234. //------------------------------------------------------------------------------
  235. // MMAllocateIn
  236. //------------------------------------------------------------------------------
  237.  
  238. void*
  239. MMAllocateIn( size_t size, MemHeap *heap )
  240. {
  241. #if MM_DEBUG
  242.     if( (MMULong)size>BestFitBlock_kMaxBlockSize ) {
  243.         MM_WARN("Bogus size 0x%08lx for MMAllocate",size);
  244.         return kMMNULL;
  245.     }
  246.     
  247.     if( gHeapChecking>0 )
  248.         MMValidateHeap(heap);
  249. #endif
  250.  
  251. #ifdef SURVEY_SIZES
  252.     SurveySize(size);
  253. #endif
  254.  
  255.     return ((BestFitHeap*)heap)->Allocate(size);
  256. }
  257.  
  258.  
  259. //------------------------------------------------------------------------------
  260. // MMAllocateClear
  261. //------------------------------------------------------------------------------
  262.  
  263. void*
  264. MMAllocateClear( size_t size )
  265. {
  266.     return MMAllocateClearIn(size,(MemHeap*)gDefaultHeap);
  267. }
  268.  
  269.  
  270. //------------------------------------------------------------------------------
  271. // MMAllocateClearIn
  272. //------------------------------------------------------------------------------
  273.  
  274. void*
  275. MMAllocateClearIn( size_t size, MemHeap *heap )
  276. {
  277.     void *block = MMAllocateIn(size,heap);
  278.     if( block )
  279.         PlatformZapMem(block,size,0);
  280.     return block;
  281. }
  282.  
  283.  
  284. //------------------------------------------------------------------------------
  285. // MMReallocate
  286. //------------------------------------------------------------------------------
  287.  
  288. void*
  289. MMReallocate( void *block, size_t size )
  290. {
  291. #ifdef SURVEY_SIZES
  292.     SurveySize(size);
  293. #endif
  294.  
  295.     if( block==kMMNULL )
  296.         return gDefaultHeap->Allocate(size);
  297.     else {
  298.         BestFitHeap *heap = (BestFitHeap*)MMGetHeap(block);
  299.         if( heap )
  300.             return heap->Reallocate(block,size);
  301.         else
  302.             return kMMNULL;
  303.     }
  304. }
  305.  
  306.  
  307. //------------------------------------------------------------------------------
  308. // MMSplice
  309. //------------------------------------------------------------------------------
  310.  
  311. void*
  312. MMSplice( void *block, size_t offset, long delta )
  313. {
  314.     // If delta>0, insert bytes at offset. If delta<0, delete bytes at offset.
  315.     
  316.     if( delta==0 ) return block;
  317.     size_t oldSize = block ?MMBlockSize(block) :0;
  318.     MM_ASSERT(offset<=oldSize);
  319.     if( MM_DEBUG && delta<0 )
  320.         MM_ASSERT(offset-delta<=oldSize);
  321.         
  322.     size_t newSize = oldSize + delta;
  323.     void *newBlock;
  324.     if( newSize==0 )
  325.         newBlock = kMMNULL;
  326.     else {
  327.         BestFitHeap *heap = (BestFitHeap*)MMGetHeap(block);
  328.         if( heap )
  329.             newBlock = heap->Allocate(newSize);
  330.         else {
  331.             MM_WARN("Couldn't get block's heap in MMSplice");
  332.             return kMMNULL;
  333.         }
  334.         if( newBlock ) {
  335.             PlatformCopyMemory(block,newBlock,offset);
  336.             if( delta>0 )
  337.                 PlatformCopyMemory((char*)block+offset,(char*)newBlock+offset+delta, oldSize-offset);
  338.             else
  339.                 PlatformCopyMemory((char*)block+offset-delta,(char*)newBlock+offset, oldSize-offset+delta);
  340.         }
  341.     }
  342.     MMFree(block);
  343.     return newBlock;
  344. }
  345.  
  346.  
  347. //------------------------------------------------------------------------------
  348. // GetHeap [static]
  349. //------------------------------------------------------------------------------
  350.  
  351.  
  352. BestFitHeap*
  353. GetHeap( const void* block, const char *op )
  354. {
  355.     if (block == kMMNULL)
  356.     {
  357.         MM_WARN("%s(NULL) is bogus, dude",op);
  358.         return kMMNULL;
  359.     }
  360.     
  361. #if MM_DEBUG        
  362.     if( gValidate>0 )
  363.         if( !MMValidatePtr(block,gHeapChecking>0,op) )
  364.             return kMMNULL;
  365. #endif
  366.     
  367.     return (BestFitHeap*) gDefaultHeap->GetBlockHeap(block);    // Should be static but isn't
  368. }
  369.  
  370.  
  371.  
  372. //------------------------------------------------------------------------------
  373. // MMFree
  374. //------------------------------------------------------------------------------
  375.  
  376. void
  377. MMFree( void *block )
  378. {
  379.     if( block ) {
  380.         #if !MM_DEBUG
  381.             gDefaultHeap->GetBlockHeap(block)->Free(block);
  382.         #else
  383.             BestFitHeap *heap = (BestFitHeap*) GetHeap(block,"MMFree");
  384.             if( heap ) {
  385.                 // The isObject flag should have been cleared by ODObject::SOMUninit!
  386.                 if( heap->BlockIsObject(block) )
  387.                     MM_WARN("Object %p unexpectedly disposed!",block);
  388.                 heap->Free(block);
  389.             }
  390.         #endif
  391.     }
  392. }
  393.  
  394.  
  395. //------------------------------------------------------------------------------
  396. // MMBlockSize
  397. //------------------------------------------------------------------------------
  398.  
  399. size_t
  400. MMBlockSize( const void *block )
  401. {
  402.     BestFitHeap *heap = GetHeap(block,"MMBlockSize");
  403.     if( heap )
  404.         return heap->BlockSize(block);
  405.     else
  406.         return 0;
  407. }
  408.  
  409.  
  410. //------------------------------------------------------------------------------
  411. // MMGetHeap
  412. //------------------------------------------------------------------------------
  413.  
  414. MemHeap*
  415. MMGetHeap( const void* block )
  416. {
  417.     return (MemHeap*) GetHeap(block,"MMGetHeap");
  418. }
  419.  
  420.  
  421. //------------------------------------------------------------------------------
  422. // MMSetIsObject
  423. //------------------------------------------------------------------------------
  424.  
  425. void MMSetIsObject( void *block, char isObject )
  426. {
  427.     BestFitHeap *heap = GetHeap(block,"MMSetIsObject");
  428.     if( heap )
  429.         heap->SetBlockIsObject(block,isObject);
  430. }
  431.  
  432.  
  433. //------------------------------------------------------------------------------
  434. // MMIsObject
  435. //------------------------------------------------------------------------------
  436.  
  437. char MMIsObject( const void *block )
  438. {
  439.     BestFitHeap *heap = GetHeap(block,"MMIsObject");
  440.     if( heap )
  441.         return heap->BlockIsObject(block);
  442.     else
  443.         return kMMFalse;
  444. }
  445.  
  446.  
  447. //------------------------------------------------------------------------------
  448. // MMMove
  449. //------------------------------------------------------------------------------
  450.  
  451. void MMMove( void *dst, const void *src, size_t size )
  452. {
  453.     if( size!=0 && src!=dst ) {
  454. #if MM_DEBUG
  455.         static void *worldStart = LOWEST_POSSIBLE_ADDRESS();
  456.         static void *worldEnd   = HIGHEST_POSSIBLE_ADDRESS();
  457.         const void *srcEnd = (char*)src+size;
  458.         const void *dstEnd = (char*)dst+size;
  459.         if( srcEnd<worldStart || src>worldEnd || dstEnd<worldStart || dst>worldEnd
  460.                     || (size&~0x0FFFFFFF) )
  461.             MM_WARN("MMMove(%p,%p,%ld) looks weird", dst,src,size);
  462.         if( gValidate>0 ) {
  463.             MMValidateMemoryRange(src,srcEnd);
  464.             MMValidateMemoryRange(dst,(char*)dst+size);
  465.         }
  466. #endif
  467.         PlatformCopyMemory((void*)src,dst,size);
  468.     }
  469. }
  470.