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