home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / mac / MacMemoryAllocator / src / LowLevel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  16.8 KB  |  618 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include <Memory.h>
  20. #include <Processes.h>
  21.  
  22. #include "stdlib.h"
  23.  
  24. #include "TypesAndSwitches.h"
  25. #include "MacMemAllocator.h"
  26.  
  27. #ifndef NSPR20
  28. #include "prglobal.h"
  29. #include "prmacos.h"
  30. #include "prthread.h"
  31. #include "prgc.h"
  32. #include "swkern.h"
  33. #else
  34. #include "prlog.h"
  35. #endif
  36.  
  37. #if DEBUG_MAC_MEMORY
  38. #include "MemoryTracker.h"
  39.  
  40.  
  41. extern AllocationSet *    gFixedSizeAllocatorSet;
  42. extern AllocationSet *    gSmallHeapAllocatorSet;
  43. extern AllocationSet *    gLargeBlockAllocatorSet;
  44. #endif
  45.  
  46. void    *        gOurApplicationHeapBase;
  47. void    *        gOurApplicationHeapMax;
  48.  
  49. Boolean            gMemoryInitialized = false;
  50.  
  51. //##############################################################################
  52. //##############################################################################
  53. #pragma mark DECLARATIONS AND ENUMERATIONS
  54.  
  55. typedef struct MemoryCacheFlusherProcRec MemoryCacheFlusherProcRec;
  56.  
  57. struct MemoryCacheFlusherProcRec {
  58.     MemoryCacheFlusherProc            flushProc;
  59.     MemoryCacheFlusherProcRec        *next;
  60. };
  61.  
  62. typedef struct PreAllocationProcRec PreAllocationProcRec;
  63.  
  64. struct PreAllocationProcRec {
  65.     PreAllocationHookProc            preAllocProc;
  66.     PreAllocationProcRec            *next;
  67. };
  68.  
  69. MemoryCacheFlusherProcRec    *gFirstFlusher = NULL;
  70. PreAllocationProcRec        *gFirstPreAllocator = NULL;
  71. MallocHeapLowWarnProc        gMallocLowProc = NULL;
  72.  
  73. void CallPreAllocators(void);
  74. void InitializeSubAllocators ( void );
  75. Boolean ReclaimMemory(size_t amountNeeded);
  76. long pascal MallocGrowZoneProc(Size cbNeeded);
  77.  
  78. #define    kMinLargeBlockHeapSize            (65 * 1024)
  79. #define    kMaxLargeBlockHeapSize            (1024 * 1024)
  80. #define    kLargeBlockInitialPercentage    (50)
  81.  
  82. // this is a boundary point at which we assume we're running low on temp memory
  83. #define    kMallocLowTempMemoryBoundary    (256 * 1024)
  84.  
  85. #if GENERATINGCFM
  86. RoutineDescriptor     gMallocGrowZoneProcRD = BUILD_ROUTINE_DESCRIPTOR(uppGrowZoneProcInfo, &MallocGrowZoneProc);
  87. #else
  88. #define gMallocGrowZoneProcRD MallocGrowZoneProc
  89. #endif
  90.  
  91. //##############################################################################
  92. //##############################################################################
  93. #pragma mark FIXED-SIZE ALLOCATION DECLARATIONS
  94.  
  95. // the real declarators
  96. DeclareFixedSizeAllocator(4, 2600, 1000);
  97. DeclareFixedSizeAllocator(8, 2000, 1000);
  98. DeclareFixedSizeAllocator(12, 3200, 1000);
  99. DeclareFixedSizeAllocator(16, 2000, 1000);
  100. DeclareFixedSizeAllocator(20, 7000, 3000);
  101. DeclareFixedSizeAllocator(24, 9500, 3000);
  102. DeclareFixedSizeAllocator(28, 3200, 1000);
  103. DeclareFixedSizeAllocator(32, 3400, 1000);
  104. DeclareFixedSizeAllocator(36, 2500, 500);
  105. DeclareFixedSizeAllocator(40, 9300, 5000);
  106. DeclareSmallHeapAllocator(512 * 1024, 256 * 1024);
  107. DeclareLargeBlockAllocator(kLargeBlockInitialPercentage, kMaxLargeBlockHeapSize, kMinLargeBlockHeapSize);
  108.  
  109. AllocMemoryBlockDescriptor gFastMemSmallSizeAllocators[] = {
  110.     DeclareLargeBlockHeapDescriptor(),
  111.     DeclareFixedBlockHeapDescriptor(4),
  112.     DeclareFixedBlockHeapDescriptor(8),
  113.     DeclareFixedBlockHeapDescriptor(12),
  114.     DeclareFixedBlockHeapDescriptor(16),
  115.     DeclareFixedBlockHeapDescriptor(20),
  116.     DeclareFixedBlockHeapDescriptor(24),
  117.     DeclareFixedBlockHeapDescriptor(28),
  118.     DeclareFixedBlockHeapDescriptor(32),
  119.     DeclareFixedBlockHeapDescriptor(36),
  120.     DeclareFixedBlockHeapDescriptor(40),
  121.     DeclareSmallSmallHeapDescriptor(),
  122.     DeclareSmallSmallHeapDescriptor(),
  123.     DeclareSmallSmallHeapDescriptor(),
  124.     DeclareSmallSmallHeapDescriptor(),
  125.     DeclareSmallSmallHeapDescriptor(),
  126.     DeclareSmallSmallHeapDescriptor(),
  127.     DeclareSmallSmallHeapDescriptor(),
  128.     DeclareSmallSmallHeapDescriptor(),
  129.     DeclareSmallSmallHeapDescriptor(),
  130.     DeclareSmallSmallHeapDescriptor(),
  131.     DeclareSmallSmallHeapDescriptor(),
  132.     DeclareSmallSmallHeapDescriptor(),
  133.     DeclareSmallSmallHeapDescriptor(),
  134.     DeclareSmallSmallHeapDescriptor(),
  135.     DeclareSmallSmallHeapDescriptor(),
  136.     DeclareSmallSmallHeapDescriptor(),
  137.     DeclareSmallSmallHeapDescriptor(),
  138.     DeclareSmallSmallHeapDescriptor(),
  139.     DeclareSmallSmallHeapDescriptor(),
  140.     DeclareSmallSmallHeapDescriptor(),
  141.     DeclareSmallSmallHeapDescriptor(),
  142.     DeclareSmallSmallHeapDescriptor(),
  143.     DeclareSmallSmallHeapDescriptor(),
  144.     DeclareSmallSmallHeapDescriptor(),
  145.     DeclareSmallSmallHeapDescriptor(),
  146.     DeclareSmallSmallHeapDescriptor(),
  147.     DeclareSmallSmallHeapDescriptor(),
  148.     DeclareSmallSmallHeapDescriptor(),
  149.     DeclareSmallSmallHeapDescriptor(),
  150.     DeclareSmallSmallHeapDescriptor(),
  151.     DeclareSmallSmallHeapDescriptor(),
  152.     DeclareSmallSmallHeapDescriptor(),
  153.     DeclareSmallSmallHeapDescriptor(),
  154.     DeclareSmallSmallHeapDescriptor(),
  155.     DeclareSmallSmallHeapDescriptor(),
  156.     DeclareSmallSmallHeapDescriptor(),
  157.     DeclareSmallSmallHeapDescriptor(),
  158.     DeclareSmallSmallHeapDescriptor(),
  159.     DeclareSmallSmallHeapDescriptor(),
  160.     DeclareSmallSmallHeapDescriptor(),
  161.     DeclareSmallSmallHeapDescriptor(),
  162.     DeclareSmallSmallHeapDescriptor(),
  163.     DeclareSmallSmallHeapDescriptor(),
  164.     DeclareSmallSmallHeapDescriptor(),
  165.     DeclareSmallSmallHeapDescriptor(),
  166.     DeclareSmallSmallHeapDescriptor(),
  167.     DeclareSmallSmallHeapDescriptor(),
  168.     DeclareSmallSmallHeapDescriptor(),
  169.     DeclareSmallSmallHeapDescriptor(),
  170.     DeclareSmallSmallHeapDescriptor(),
  171.     DeclareSmallSmallHeapDescriptor(),
  172.     DeclareSmallSmallHeapDescriptor(),
  173.     DeclareSmallSmallHeapDescriptor(),
  174.     DeclareSmallSmallHeapDescriptor(),
  175.     DeclareSmallSmallHeapDescriptor(),
  176.     DeclareSmallSmallHeapDescriptor()
  177. };
  178.  
  179. //##############################################################################
  180. //##############################################################################
  181. #pragma mark INITIALIZATION
  182.  
  183. void MacintoshInitializeMemory(void)
  184. {
  185.     UInt32                i;
  186.     ProcessSerialNumber    thisProcess = { 0, kCurrentProcess };
  187.     ProcessInfoRec        processInfo;
  188.  
  189. // Increase the stack space.
  190. // This is because PA_MDL_ParseTag can go into deep recursion when dealing with 
  191. // malformed HTML comments (the only occurrence where we bombed).
  192. #ifndef powerc
  193.     SetApplLimit(GetApplLimit() - 16384);    
  194. #endif
  195.     MaxApplZone();
  196.     for (i = 1; i <= 30; i++)
  197.         MoreMasters();
  198.  
  199.     // init our new compact allocators
  200.     
  201.     processInfo.processInfoLength = sizeof(processInfo);
  202.     processInfo.processName = NULL;
  203.     processInfo.processAppSpec = NULL;
  204.  
  205.     GetProcessInformation(&thisProcess, &processInfo);
  206.     gOurApplicationHeapBase = processInfo.processLocation;
  207.     gOurApplicationHeapMax = (Ptr)gOurApplicationHeapBase + processInfo.processSize;
  208.     
  209. #if DEBUG_MAC_MEMORY
  210.     InstallMemoryManagerPatches();
  211.  
  212. #if 1
  213.     // Create some allocation sets to track our allocators
  214.     gFixedSizeAllocatorSet = NewAllocationSet ( 0, "Fixed Size Compact Allocator" );
  215.     gSmallHeapAllocatorSet = NewAllocationSet ( 0, "Small Heap Allocator" );
  216.     gLargeBlockAllocatorSet = NewAllocationSet ( 0, "Large Block Allocator" );
  217.      
  218.     // disable them so we don't get random garbage
  219.     DisableAllocationSet ( gFixedSizeAllocatorSet );
  220.     DisableAllocationSet ( gSmallHeapAllocatorSet );
  221.     DisableAllocationSet ( gLargeBlockAllocatorSet );
  222. #endif
  223.  
  224. #endif
  225.     
  226.     // intialize the sub allocators
  227.     InitializeSubAllocators();
  228.     
  229.     gMemoryInitialized = true;
  230. }
  231.  
  232. void InitializeSubAllocators ( void )
  233. {
  234.     SubHeapAllocationChunk *    chunk;
  235.     
  236.     /* fixed size allocators */
  237.     chunk = FixedSizeAllocChunk ( 0, &gFixedSize4Root );
  238.     PR_ASSERT(chunk);
  239.     if ( chunk == NULL ) goto fail;
  240.     
  241.     chunk = FixedSizeAllocChunk ( 0, &gFixedSize8Root );
  242.     PR_ASSERT(chunk);
  243.     if ( chunk == NULL ) goto fail;
  244.  
  245.     chunk = FixedSizeAllocChunk ( 0, &gFixedSize12Root );
  246.     PR_ASSERT(chunk);
  247.     if ( chunk == NULL ) goto fail;
  248.  
  249.     chunk = FixedSizeAllocChunk ( 0, &gFixedSize16Root );
  250.     PR_ASSERT(chunk);
  251.     if ( chunk == NULL ) goto fail;
  252.  
  253.     chunk = FixedSizeAllocChunk ( 0, &gFixedSize20Root );
  254.     PR_ASSERT(chunk);
  255.     if ( chunk == NULL ) goto fail;
  256.  
  257.     chunk = FixedSizeAllocChunk ( 0, &gFixedSize24Root );
  258.     PR_ASSERT(chunk);
  259.     if ( chunk == NULL ) goto fail;
  260.  
  261.     chunk = FixedSizeAllocChunk ( 0, &gFixedSize28Root );
  262.     PR_ASSERT(chunk);
  263.     if ( chunk == NULL ) goto fail;
  264.  
  265.     chunk = FixedSizeAllocChunk ( 0, &gFixedSize32Root );
  266.     PR_ASSERT(chunk);
  267.     if ( chunk == NULL ) goto fail;
  268.  
  269.     chunk = FixedSizeAllocChunk ( 0, &gFixedSize36Root );
  270.     PR_ASSERT(chunk);
  271.     if ( chunk == NULL ) goto fail;
  272.  
  273.     chunk = FixedSizeAllocChunk ( 0, &gFixedSize40Root );
  274.     PR_ASSERT(chunk);
  275.     if ( chunk == NULL ) goto fail;
  276.     
  277.     chunk = SmallHeapAllocChunk ( 0, &gSmallHeapRoot );
  278.     PR_ASSERT(chunk);
  279.     if ( chunk == NULL ) goto fail;
  280.     
  281.     chunk = LargeBlockAllocChunk ( 0, &gLargeBlockRoot );
  282.     PR_ASSERT(chunk);
  283.     if ( chunk == NULL ) goto fail;
  284.  
  285. #if DEBUG_MAC_MEMORY && TRACK_EACH_ALLOCATOR
  286.     gFixedSize4Root.header.set = NewAllocationSet ( 0, "Fixed Block 4" );
  287.     DisableAllocationSet ( gFixedSize4Root.header.set );
  288.     
  289.     gFixedSize8Root.header.set = NewAllocationSet ( 0, "Fixed Block 8" );
  290.     DisableAllocationSet ( gFixedSize8Root.header.set );
  291.     
  292.     gFixedSize12Root.header.set = NewAllocationSet ( 0, "Fixed Block 12" );
  293.     DisableAllocationSet ( gFixedSize12Root.header.set );
  294.     
  295.     gFixedSize16Root.header.set = NewAllocationSet ( 0, "Fixed Block 16" );
  296.     DisableAllocationSet ( gFixedSize16Root.header.set );
  297.     
  298.     gFixedSize20Root.header.set = NewAllocationSet ( 0, "Fixed Block 20" );
  299.     DisableAllocationSet ( gFixedSize20Root.header.set );
  300.     
  301.     gFixedSize24Root.header.set = NewAllocationSet ( 0, "Fixed Block 24" );
  302.     DisableAllocationSet ( gFixedSize24Root.header.set );
  303.     
  304.     gFixedSize28Root.header.set = NewAllocationSet ( 0, "Fixed Block 28" );
  305.     DisableAllocationSet ( gFixedSize28Root.header.set );
  306.     
  307.     gFixedSize32Root.header.set = NewAllocationSet ( 0, "Fixed Block 32" );
  308.     DisableAllocationSet ( gFixedSize32Root.header.set );
  309.     
  310.     gFixedSize36Root.header.set = NewAllocationSet ( 0, "Fixed Block 36" );
  311.     DisableAllocationSet ( gFixedSize36Root.header.set );
  312.     
  313.     gFixedSize40Root.header.set = NewAllocationSet ( 0, "Fixed Block 40" );
  314.     DisableAllocationSet ( gFixedSize40Root.header.set );
  315.     
  316.     gSmallHeapRoot.header.set = NewAllocationSet ( 0, "Small Block" );
  317.     DisableAllocationSet ( gSmallHeapRoot.header.set );
  318.     
  319.     gLargeBlockRoot.header.set = NewAllocationSet ( 0, "Large Block" );
  320.     DisableAllocationSet ( gLargeBlockRoot.header.set );
  321. #endif
  322.  
  323.     return;
  324.     
  325. fail:
  326.     /* We couldn't initialize one of the sub allocators, so we're screwed */
  327.     /* I don't think we need an alert here as we should never hit this case unless */
  328.     /* a user really mucks up our heap partition */
  329.     ExitToShell();
  330. }
  331.  
  332. //##############################################################################
  333. //##############################################################################
  334. #pragma mark -
  335. #pragma mark INSTALLING MEMORY MANAGER HOOKS
  336.  
  337. void InstallPreAllocationHook(PreAllocationHookProc newHook)
  338. {
  339.     PreAllocationProcRec            *preAllocatorRec;
  340.  
  341.     preAllocatorRec = (PreAllocationProcRec *)(NewPtr(sizeof(PreAllocationProcRec)));
  342.  
  343.     if (preAllocatorRec != NULL) {
  344.     
  345.         preAllocatorRec->next = gFirstPreAllocator;
  346.         preAllocatorRec->preAllocProc = newHook;
  347.         gFirstPreAllocator = preAllocatorRec;        
  348.     
  349.     }
  350.  
  351. }
  352.  
  353. void InstallMemoryCacheFlusher(MemoryCacheFlusherProc newFlusher)
  354. {    
  355.     MemoryCacheFlusherProcRec        *previousFlusherRec = NULL;
  356.     MemoryCacheFlusherProcRec        *cacheFlusherRec = gFirstFlusher;
  357.     
  358.     while (cacheFlusherRec != NULL) {
  359.         previousFlusherRec = cacheFlusherRec;
  360.         cacheFlusherRec = cacheFlusherRec->next;
  361.     }
  362.  
  363.     cacheFlusherRec =  (MemoryCacheFlusherProcRec *)NewPtrClear(sizeof(MemoryCacheFlusherProcRec));
  364.     
  365.     if (cacheFlusherRec == NULL)
  366.         return;
  367.  
  368.     cacheFlusherRec->flushProc = newFlusher;
  369.  
  370.     if (previousFlusherRec != NULL) {
  371.         previousFlusherRec->next = cacheFlusherRec;
  372.     }
  373.     
  374.     else {
  375.         gFirstFlusher = cacheFlusherRec;
  376.     }
  377.     
  378. }
  379.  
  380. void CallPreAllocators(void)
  381. {
  382.     PreAllocationProcRec        *currentPreAllocator = gFirstPreAllocator;
  383.  
  384.     while (currentPreAllocator != NULL) {
  385.         (*(currentPreAllocator->preAllocProc))();
  386.         currentPreAllocator = currentPreAllocator->next;
  387.     }
  388.     
  389. }
  390.  
  391. static MemoryCacheFlusherProc sGarbageCollectorCacheFlusher = NULL;
  392.  
  393. UInt8 CallCacheFlushers(size_t blockSize)
  394. {
  395.     MemoryCacheFlusherProcRec        *currentCacheFlusher = gFirstFlusher;
  396.     UInt8                            result = false;
  397.  
  398.     while (currentCacheFlusher != NULL) {
  399.         result |= (*(currentCacheFlusher->flushProc))(blockSize);
  400.         currentCacheFlusher = currentCacheFlusher->next;
  401.     }
  402.     
  403.     //    We used to try calling the GC if malloc failed, but that's
  404.     //  a waste of time since the GC never frees segments (bug?)
  405.     //  and thus won't increase heap space.
  406.         
  407.     return result;
  408.     
  409. }
  410.  
  411. void InstallGarbageCollectorCacheFlusher(const MemoryCacheFlusherProc inFlusher)
  412. {
  413.     sGarbageCollectorCacheFlusher = inFlusher;
  414. }
  415.  
  416. void InstallMallocHeapLowProc( MallocHeapLowWarnProc proc )
  417. {
  418.     gMallocLowProc = proc;
  419. }
  420.  
  421. void CallFE_LowMemory(void)
  422. {
  423.     if ( gMallocLowProc != NULL )
  424.         {
  425.         gMallocLowProc();
  426.         }
  427. }
  428.  
  429. //##############################################################################
  430. //##############################################################################
  431. #pragma mark -
  432. #pragma mark SUB HEAP ALLOCATION
  433.  
  434. SubHeapAllocationChunk * AllocateSubHeap ( SubHeapAllocationRoot * root, Size heapSize, Boolean useTemp )
  435. {
  436.     SubHeapAllocationChunk *    heapBlock;
  437.     Handle                        tempHandle;
  438.     OSErr                        err;
  439.     
  440.     heapBlock = NULL;
  441.     tempHandle = NULL;
  442.     
  443. #if DEBUG_MAC_MEMORY
  444.     DisableMemoryTracker();
  445. #endif
  446.  
  447.     if ( useTemp )
  448.         {
  449.         tempHandle = TempNewHandle ( heapSize, &err );
  450.         if ( tempHandle != NULL && err == noErr )
  451.             {
  452.             HLock ( tempHandle );
  453.             heapBlock = *(SubHeapAllocationChunk **) tempHandle;
  454.             }
  455.         }
  456.     else
  457.         {
  458.         heapBlock = (SubHeapAllocationChunk *) NewPtr ( heapSize );
  459.         }
  460.     
  461.     if ( heapBlock != NULL )
  462.         {
  463.         heapBlock->root = root;
  464.         heapBlock->refCon = tempHandle;
  465.         heapBlock->next = NULL;
  466.         heapBlock->usedBlocks = 0;
  467.         heapBlock->freeDescriptor.freeRoutine = NULL;
  468.         heapBlock->freeDescriptor.refcon = NULL;
  469.         
  470.         // whack this on the root's chunk list
  471.         if ( root->lastChunk == NULL )
  472.             {
  473.             root->firstChunk = heapBlock;
  474.             }
  475.         else
  476.             {
  477.             root->lastChunk->next = heapBlock;
  478.             }
  479.         
  480.         root->lastChunk = heapBlock;
  481.         }
  482.     
  483. #if DEBUG_MAC_MEMORY
  484.     EnableMemoryTracker();
  485. #endif
  486.     
  487.     return heapBlock;
  488. }
  489.  
  490.  
  491. void FreeSubHeap ( SubHeapAllocationRoot * root, SubHeapAllocationChunk * chunk )
  492. {
  493.     Handle                        tempHandle;
  494.     SubHeapAllocationChunk *    list;
  495.     SubHeapAllocationChunk *    prev;
  496.     SubHeapAllocationChunk *    next;
  497.     
  498.     if ( chunk != NULL )
  499.         {
  500.         // run through the root's chunk list and remove our block
  501.         prev = NULL;
  502.         list = root->firstChunk;
  503.         
  504.         while ( list != NULL )
  505.             {
  506.             next = list->next;
  507.             
  508.             if ( list == chunk )
  509.                 {
  510.                 break;
  511.                 }
  512.             
  513.             prev = list;
  514.             list = next;
  515.             }
  516.         
  517.         if ( list != NULL )
  518.             {
  519.             if ( prev != NULL )
  520.                 {
  521.                 prev->next = next;
  522.                 }
  523.             
  524.             if ( root->firstChunk == list )
  525.                 {
  526.                 root->firstChunk = next;
  527.                 }
  528.             
  529.             if ( root->lastChunk == list )
  530.                 {
  531.                 root->lastChunk = prev;
  532.                 }
  533.             }
  534.             
  535.         tempHandle = (Handle) chunk->refCon;
  536.         if ( tempHandle != NULL )
  537.             {
  538.             DisposeHandle ( tempHandle );
  539.             }
  540.         else
  541.             {
  542.             DisposePtr ( (Ptr) chunk );
  543.             }
  544.         }
  545. }
  546.  
  547.  
  548. //##############################################################################
  549. //##############################################################################
  550. #pragma mark -
  551. #pragma mark MEMORY UTILS
  552.  
  553. Boolean gInMemory_ReserveInMacHeap = false;
  554.  
  555. Boolean InMemory_ReserveInMacHeap()
  556. {
  557.     return gInMemory_ReserveInMacHeap;
  558. }
  559.  
  560. Boolean ReclaimMemory(size_t amountNeeded)
  561. {
  562.     Boolean            result;
  563.             
  564.     result = CallCacheFlushers(amountNeeded);
  565.         
  566.     return result;
  567.  
  568. }
  569.  
  570. Boolean Memory_ReserveInMacHeap(size_t spaceNeeded)
  571. {
  572.     Boolean        result = true;
  573.     
  574.     gInMemory_ReserveInMacHeap = true;
  575.     
  576.     if (MaxBlock() < spaceNeeded)
  577.         result = ReclaimMemory(spaceNeeded);
  578.     
  579.     gInMemory_ReserveInMacHeap = false;
  580.  
  581.     return result;
  582.     
  583. }
  584.  
  585. Boolean Memory_ReserveInMallocHeap(size_t spaceNeeded)
  586. {
  587.     Boolean        result = true;
  588.     Size        freeMem;
  589.     
  590.     gInMemory_ReserveInMacHeap = true;
  591.     
  592.     freeMem = MaxBlock();
  593.     
  594.     if (freeMem < spaceNeeded)
  595.         result = ReclaimMemory(spaceNeeded);
  596.  
  597.     gInMemory_ReserveInMacHeap = false;
  598.  
  599.     return result;
  600.     
  601. }
  602.  
  603. size_t Memory_FreeMemoryRemaining()
  604. {
  605.     size_t        mainHeap;
  606.     size_t        mallocHeap;
  607.     
  608.     mainHeap = FreeMem();
  609.     
  610.     mallocHeap = FreeMem();
  611.     
  612.     return (mainHeap < mallocHeap) ? mainHeap : mallocHeap; 
  613.  
  614. }
  615.  
  616.  
  617.  
  618.