home *** CD-ROM | disk | FTP | other *** search
- /*
- File: MemMgrM.cpp
-
- Contains: Mac-specific implementations of MemMgr calls
-
- Owned by: Jens Alfke
-
- Copyright: © 1994 - 1995 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <10> 10/24/95 jpa 1293441: Added slush-fund. Allocate
- temp-mem handles out of app heap if
- absolutely necessary.
- <9> 10/4/95 jpa MMCopyHandle allocates in current heap's
- area. [1289074]
- <8> 5/5/95 TJ jpa: ApplicZone --> ApplicationZone.
- <7> 5/4/95 jpa Added free-space fns, and maintain a
- certain minimum free space in handle
- allocation ops [1235657]
- <6> 1/25/95 jpa Removed HandToHand workaround now that
- we're on Dagon a2. [1209733]
- <5> 1/12/95 jpa Took out five-dollar-sign mark and added
- Radar bug 1209733. [1210981]
- <4> 12/5/94 jpa Nuked errant pragma lib_export's. [1195676]
- <3> 10/12/94 JA Added 68k workaround for HandToHand; no
- effect on PPC build.
- <2> 9/29/94 RA 1189812: Mods for 68K build.
- <1> 9/14/94 jpa first checked in
-
- To Do:
- In Progress:
-
- */
-
-
- #ifndef _MEMMGR_
- #include "MemMgr.h"
- #endif
-
- #ifndef _MEMMGRPV_
- #include "MemMgrPv.h"
- #endif
-
- #ifndef _MEMDEBG_
- #include "MemDebg.h"
- #endif
-
- #ifndef __MEMORY__
- #include <Memory.h> // Mac memory manager
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
-
- const size_t kMaxHandleBlockSize = 0x7FFFFFFF;
-
- #if MM_DEBUG
- const size_t kTempMemFudge = 1000*1024;
- #else
- const size_t kTempMemFudge = 100*1024;
- #endif
-
-
- static void MMSystemFreeSpace( Zone *zone, size_t *total, size_t *contig );
-
-
- static MMBoolean
- FreeSpaceLow( MMHandle h )
- {
- if( !h )
- return kMMFalse;
- Zone *zone = ::HandleZone((Handle)h);
- if( MemError() )
- return kMMTrue;
- size_t free,contig;
- MMSystemFreeSpace(zone,&free,&contig);
- return (free < kPlatformMinFreeSpace || contig < kPlatformMinContigSpace);
- }
-
-
- //========================================================================================
- // OPERATIONS ON RELOCATABLE BLOCKS (HANDLES)
- //========================================================================================
-
-
- //----------------------------------------------------------------------------------------
- // MMAllocateHandle
- //----------------------------------------------------------------------------------------
-
- MMHandle MMAllocateHandle(size_t howBig)
- {
- return MMAllocateHandleIn(howBig,gDefaultHeap->GetLocation());
- }
-
- //----------------------------------------------------------------------------------------
- // MMAllocateHandleIn
- //----------------------------------------------------------------------------------------
-
- MMHandle MMAllocateHandleIn(size_t size, MMHeapLocation loc)
- {
- #if MMDebug
- if( size>kMaxHandleBlockSize ) {
- MM_WARN("Bogus size 0x%08lx for MMAllocateHandle",size);
- return kMMNULL;
- }
- #endif
-
- Handle handle;
- OSErr err;
-
- switch( loc ) {
- case kMMSysMemory:
- handle = ::NewHandleSys(size);
- err = MemError();
- break;
- case kMMAppMemory:
- SetZone(ApplicationZone());
- handle = ::NewHandle(size);
- err = MemError();
- break;
- case kMMTempMemory:
- handle = ::TempNewHandle(size, &err);
- break;
- default:
- MM_WARN("MMAllocateHandleIn: Bogus memory source!");
- return 0;
- }
-
- if( err!=noErr && err!=memFullErr )
- MM_WARN("MMAllocateHandle got err %d",err);
-
- if( FreeSpaceLow(handle) ) {
- DisposeHandle(handle);
- handle = kMMNULL;
- }
-
- if( handle == kMMNULL && loc==kMMTempMemory ) {
- // Allow temp-mem handle to be allocated out of app heap if there's room.
- // It's easy for temp-mem to become totally wedged (just launch an app whose
- // "preferred size" is greater than the amount available), which would
- // otherwise totally prevent allocation of handles.
- handle = (Handle) MMAllocateHandleIn(size,kMMAppMemory);
- }
-
- #if MMDebug
- if( gValidate>0 && handle )
- Zap(*(Handle)handle, size, 0xBBBBBBBB);
- #endif
-
- return (MMHandle) handle;
- }
-
- //----------------------------------------------------------------------------------------
- // MMFreeHandle
- //----------------------------------------------------------------------------------------
-
- void MMFreeHandle(MMHandle handle)
- {
- if( handle != kMMNULL ) {
- #if MMDebug
- if( gValidate>0 ) {
- if( !MMValidateHandle(handle) )
- return;
- Zap(*(Handle)handle, GetHandleSize((Handle)handle), 0xDD);
- }
-
- if( HGetState((Handle)handle) & 0x20 ) {
- MM_WARN("MMFreeHandle: Tried to dispose rsrc %p",handle);
- return;
- }
- #endif
-
- DisposeHandle((Handle)handle);
-
- #if MMDebug
- OSErr err = MemError();
- if( err!=noErr )
- MM_WARN("MMFreeHandle: DisposeHandle returned err %d",err);
- #endif
- }
- }
-
- //----------------------------------------------------------------------------------------
- // MMCopyHandle
- //----------------------------------------------------------------------------------------
-
- MMHandle MMCopyHandle( MMHandle handle )
- {
- if( handle == kMMNULL ) {
- MM_WARN("MMCopyHandle(NULL)!");
- return kMMNULL;
- }
-
- #if MMDebug
- if( gValidate>0 )
- if( !MMValidateHandle(handle) )
- return kMMNULL;
- if( (HGetState((Handle)handle)&0x20) && !(HGetState((Handle)handle)&0x80) )
- MM_WARN("Copying purgeable handle %p",handle);
- #endif
-
- size_t size = GetHandleSize((Handle) handle);
- if( MemError() ) {
- MM_WARN("MMCopyHandle got err %d",MemError());
- return kMMNULL;
- }
-
- MMHandle copy = MMAllocateHandle(size);
- if( copy ) {
- PlatformCopyMemory(*(Handle)handle,*(Handle)copy,size);
- if( FreeSpaceLow(copy) ) {
- MMFreeHandle(copy);
- copy = kMMNULL;
- }
- }
- return copy;
- }
-
- //----------------------------------------------------------------------------------------
- // MMGetHandleSize(MMHandle handle)
- //----------------------------------------------------------------------------------------
-
- size_t MMGetHandleSize(MMHandle handle)
- {
- size_t blkSize;
-
- #if MMDebug
- if( gValidate>0 )
- if( !MMValidateHandle(handle) )
- return 0;
- #endif
-
- blkSize = GetHandleSize((Handle) handle);
- if( MemError() ) {
- MM_WARN("MMGetHandleSize got err %d",MemError());
- blkSize = 0;
- }
- return blkSize;
- }
-
- //----------------------------------------------------------------------------------------
- // MMSetHandleSize(MMHandle handle, size_t blkSize)
- //----------------------------------------------------------------------------------------
-
- MMBoolean MMSetHandleSize(MMHandle handle, size_t blkSize)
- {
- size_t oldSize = ::GetHandleSize((Handle)handle);
-
- if( blkSize == oldSize )
- return kMMTrue;
-
- #if MMDebug
- if( blkSize>kMaxHandleBlockSize ) {
- MM_WARN("Bogus blkSize %08lx for MMSetHandleSize",blkSize);
- return kMMFalse;
- }
- if( gValidate>0 ) {
- if( !MMValidateHandle(handle) )
- return kMMFalse;
- // If block will shrink, zap area that will be lost:
- if( blkSize < oldSize )
- memset(OFFSET(*(Handle)handle,blkSize), 0xDD, oldSize-blkSize);
- }
- #endif
-
- SetHandleSize((Handle) handle, blkSize);
- OSErr err = MemError();
- if( err ) {
- if( err!=memFullErr )
- MM_WARN("MMSetHandleSize got err %d",err);
- return kMMFalse;
- }
-
- if( blkSize>oldSize && FreeSpaceLow(handle) ) {
- ::SetHandleSize((Handle)handle,oldSize); // Back out the change
- return kMMFalse;
- }
-
- #if MMDebug
- // If block grew, zap new space at end:
- if( gValidate>0 )
- if( blkSize > oldSize )
- memset(OFFSET(*(Handle)handle,oldSize),0xBB,(size_t)(blkSize-oldSize)); // Fill new space with BB
- #endif
-
- return kMMTrue;
- }
-
- //----------------------------------------------------------------------------------------
- // MMLockHandle(MMHandle handle)
- //----------------------------------------------------------------------------------------
-
- void* MMLockHandle(MMHandle handle)
- {
- #if MMDebug
- if( gValidate>0 )
- if( !MMValidateHandle(handle) )
- return kODNULL;
- #endif
-
- HLock((Handle) handle);
- OSErr err = MemError();
- if( err ) {
- MM_WARN("MMLockHandle got err %d",err);
- return kMMNULL;
- }
-
- return *(Handle) handle;
- }
-
- //----------------------------------------------------------------------------------------
- // MMUnlockPtr(void* ptr)
- //----------------------------------------------------------------------------------------
-
- void MMUnlockPtr(void* ptr)
- {
- if( ptr==kMMNULL ) {
- MM_WARN("MMUnlockPtr(NULL)!");
- } else {
- MMHandle handle = (MMHandle) RecoverHandle((Ptr) ptr);
- if( MemError() )
- MM_WARN("MMUnlockPtr(%p) got err %d",ptr,MemError());
- else if (handle != kMMNULL) {
- #if MMDebug
- if( HGetState((Handle)handle) & 0x80) )
- MM_WARN("MMUnlockPtr(%p): Hdl %p already unlocked",ptr,h);
- #endif
- HUnlock((Handle) handle);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // MMUnlockHandle(MMHandle handle)
- //----------------------------------------------------------------------------------------
-
- void MMUnlockHandle(MMHandle handle)
- {
- #if MMDebug
- if( gValidate>0 )
- if( !MMValidateHandle(handle) )
- THROW(kMMErrMemoryProblem);
- #endif
-
- HUnlock((Handle) handle);
- if( MemError() )
- MM_WARN("MMUnlockHandle(%p) got err %d",handle,MemError());
- }
-
-
- //----------------------------------------------------------------------------------------
- // MMSystemFreeSpace
- //----------------------------------------------------------------------------------------
-
- void MMSystemFreeSpace( MMHeapLocation loc, size_t *total, size_t *contig )
- {
- size_t tempTotal, tempContig;
- if( !total ) total = &tempTotal;
- if( !contig) contig= &tempContig;
-
- Zone *zone = kMMNULL;
-
- switch( loc ) {
- case kMMSysMemory:
- zone = SystemZone();
- break;
-
- case kMMAppMemory:
- zone = ApplicationZone();
- break;
-
- case kMMTempMemory: {
- // Find the temp zone by allocating a handle in it and then getting its zone.
- // Cannot cache this value because the Process Mgr zone's header can move!
- OSErr err;
- Handle handle = ::TempNewHandle(1, &err);
- if( handle ) {
- zone = ::HandleZone(handle);
- ::DisposeHandle(handle);
- }
- }
- }
- MMSystemFreeSpace(zone,total,contig);
- }
-
-
- static void MMSystemFreeSpace( Zone *zone, size_t *total, size_t *contig )
- {
- if( zone ) {
- Zone *curZone = GetZone();
- SetZone(zone);
-
- *total = FreeMem();
- *contig = MaxBlock();
- size_t purgeTotal, purgeContig;
- PurgeSpace((long*)&purgeTotal,(long*)&purgeContig);
- if( purgeTotal > *total )
- *total = purgeTotal;
- if( purgeContig > *contig )
- *contig = purgeContig;
-
- // Return an unnaturally low number for Temp Mem availability, to make it easier
- // to debug and to reflect the fact that running out of temp mem is incredibly
- // dangerous to the whole system.
- if( kTempMemFudge > 0 && zone!=ApplicationZone() && zone!=SystemZone() ) {
- // (It would be nice to have a better way to detect the temp mem zone.)
- if( *total >= kTempMemFudge )
- *total -= kTempMemFudge;
- else
- *total = 0;
- if( *contig > *total )
- *contig = *total;
- }
-
- SetZone(curZone);
- } else
- *total = *contig = 0;
- }
-