mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 16:31:01 +00:00
550 lines
16 KiB
C
550 lines
16 KiB
C
|
/*
|
|||
|
File: Memory.c
|
|||
|
|
|||
|
Contains: Routines manage the Process Mgr's memory resources.
|
|||
|
|
|||
|
Written by: Erich Ringewald and his bestest buddy Philip York Goldman.
|
|||
|
|
|||
|
Copyright: <EFBFBD> 1986-1992 by Apple Computer, Inc., all rights reserved.
|
|||
|
|
|||
|
Change History (most recent first):
|
|||
|
|
|||
|
<12> 10/28/92 DTY Use new Get/Set macros to access ExpandMem.
|
|||
|
<11> 3/11/92 DTY 7 Up<EFBFBD>s patch to GMBlk doesn<EFBFBD>t respect the slop space in the
|
|||
|
system heap, so that the death notice session record will always
|
|||
|
be allocated. We do and we need to stop.
|
|||
|
<10> 11/22/91 DTY Check allocateGMBlkInSysHeap in GMBlk before trying to allocate
|
|||
|
the block in the Process Manager heap. This is one of the fixes
|
|||
|
from 7-Up.
|
|||
|
<9> 4/5/91 JWM DtY,#86193: GMBlk was fragmenting the system heap and did not
|
|||
|
honor emMinSysHeapFreeSpace. Added a ReserveMemSys call to help
|
|||
|
with the fragmentation problem. Added a check for leaving a
|
|||
|
minimum amount of space in the system heap.
|
|||
|
<8> 2/25/91 dba pm: set up A5 in SysZoneFloatSizes
|
|||
|
<7> 2/21/91 DFH dba,#82504, #82681, #83168, #83182, #83207: Temp mem heap calls
|
|||
|
are more accurate, now that we crawl the system heap to
|
|||
|
calculate the high free memory.
|
|||
|
<6> 2/9/91 JWM DFH,#79583:Restart and Shutdown don't work in low memory
|
|||
|
conditions. A new routine was defined -- GMBlk. It is modeled
|
|||
|
after ProcessMgrHiNewHandle but checks the system heap if
|
|||
|
ProcessMgrHiNewHandle returns a null handle.
|
|||
|
<5> 1/14/91 DFH (dba) Make system mode per process.
|
|||
|
<3> 11/5/90 DFH Correct names for TEMPTOPMEM and TEMPDISPOSEHANDLE.
|
|||
|
<0> 1/23/87 PYG New Today.
|
|||
|
|
|||
|
*/
|
|||
|
|
|||
|
#include <types.h>
|
|||
|
#include <errors.h>
|
|||
|
#include <memory.h>
|
|||
|
|
|||
|
#include "Glue.h"
|
|||
|
#include "Lomem.h"
|
|||
|
#include "Data.h"
|
|||
|
#include "Zone.h"
|
|||
|
#include "HList.h"
|
|||
|
|
|||
|
#ifdef MORE_SEGMENTS
|
|||
|
#pragma segment kernel_segment
|
|||
|
#endif MORE_SEGMENTS
|
|||
|
|
|||
|
/* The following routines implement selected Memory Manager functions
|
|||
|
* for the Process Mgr Zone.
|
|||
|
*
|
|||
|
* NOTE: Originally, the handle manipulation routines really did something
|
|||
|
* different from their "normal" counterparts. Now, only the allocation
|
|||
|
* routine (new handle) is special, and the normal call set has been
|
|||
|
* made to work with temp blocks.
|
|||
|
*/
|
|||
|
|
|||
|
/* c_TempMaxMem. This routine tries to calculate the size of the largest block we
|
|||
|
* could allocate in the Process Mgr zone. Unfortunately, it is inaccurate
|
|||
|
* because it does not determine how much of the SYSHEAP space can actually be
|
|||
|
* used (it assumes all free/purgeable space is at the top).
|
|||
|
*/
|
|||
|
pascal u_size
|
|||
|
c_TempMaxMem(u_size *pGrowSize)
|
|||
|
{
|
|||
|
u_size retval;
|
|||
|
unsigned long olda5;
|
|||
|
|
|||
|
olda5 = ProcessMgrA5SimpleSetup();
|
|||
|
retval = ProcessMgrMaxBlock();
|
|||
|
|
|||
|
/* Spec sez this is always zero if heap is not APPLZONE */
|
|||
|
if (pGrowSize != nil)
|
|||
|
*pGrowSize = 0;
|
|||
|
|
|||
|
A5SimpleRestore(olda5);
|
|||
|
return(retval);
|
|||
|
}
|
|||
|
|
|||
|
/* c_TempFreeMem. Potential free memory for Process Mgr heap also includes memory from
|
|||
|
* the top of the system heap. Fairly useless, really.
|
|||
|
* NOTE: Assumes that FreeMem can not cause ProcessMgrZone to move, in that it restores
|
|||
|
* THEZONE unconditionally, instead of using SafeSetZone and SafeRestoreZone.
|
|||
|
*/
|
|||
|
pascal u_size
|
|||
|
c_TempFreeMem(void)
|
|||
|
{
|
|||
|
u_size retval, lowPM;
|
|||
|
THz theZone;
|
|||
|
unsigned long olda5;
|
|||
|
|
|||
|
olda5 = ProcessMgrA5SimpleSetup();
|
|||
|
theZone = THEZONE;
|
|||
|
THEZONE = ProcessMgrZone;
|
|||
|
|
|||
|
/* Initially, calculate space as straddle block (top of system heap and bottom of
|
|||
|
* Process Mgr heap) plus the free memory in the Process Mgr heap. This is too much,
|
|||
|
* since the bottom space in the Process Mgr heap is counted twice, so we finish by
|
|||
|
* subtracting that much off. StraddleBlockSize returns 0 if the amount available
|
|||
|
* in the straddle is less than our threshold, but lowPM can still be non-zero.
|
|||
|
* NOTE: lowPM can be greater than FreeMem(), since the former includes purgeable
|
|||
|
* space but the latter does not. This is why we are careful when subtracting.
|
|||
|
*/
|
|||
|
if ((retval = StraddleBlockSize(&lowPM, nil, nil, nil) + FreeMem()) > lowPM)
|
|||
|
retval -= lowPM;
|
|||
|
else
|
|||
|
retval = 0;
|
|||
|
|
|||
|
THEZONE = theZone;
|
|||
|
A5SimpleRestore(olda5);
|
|||
|
return(retval);
|
|||
|
}
|
|||
|
|
|||
|
/* c_TempTopMem. Return the value of MEMTOP we saw at startup. This call is
|
|||
|
* obsolete in Process Mgr 7.0 and later, because Gestalt is better.
|
|||
|
*/
|
|||
|
pascal Ptr
|
|||
|
c_TempTopMem(void)
|
|||
|
{
|
|||
|
unsigned long olda5;
|
|||
|
Ptr retval;
|
|||
|
|
|||
|
olda5 = ProcessMgrA5SimpleSetup();
|
|||
|
retval = initMemTop;
|
|||
|
A5SimpleRestore(olda5);
|
|||
|
return(retval);
|
|||
|
}
|
|||
|
|
|||
|
/* c_SysZoneFloatSizes. Find the sizes of the blocks that form the straddle block
|
|||
|
* across the top of the system heap and bottom of the Temp Memory heap. This is
|
|||
|
* the area where the bottom of the Temp Memory heap can float when allocations from
|
|||
|
* one heap require abducting memory from the other heap.
|
|||
|
*/
|
|||
|
pascal OSErr
|
|||
|
c_SysZoneFloatSizes(unsigned long *hiSysRoom, unsigned long *lowTempRoom)
|
|||
|
{
|
|||
|
/* Set up A5 so that we can get at Process Mgr. globals */
|
|||
|
unsigned long savedA5 = ProcessMgrA5SimpleSetup();
|
|||
|
|
|||
|
/* Find space available at top of system zone */
|
|||
|
if (hiSysRoom != nil)
|
|||
|
*hiSysRoom = GetSystemHiFreeBytes();
|
|||
|
|
|||
|
/* Find space available at bottom of Process Mgr (aka Temp Memory) zone */
|
|||
|
if (lowTempRoom != nil)
|
|||
|
*lowTempRoom = GetProcessMgrLoFreeBytes(nil, nil);
|
|||
|
|
|||
|
/* For now, no error is possible */
|
|||
|
A5SimpleRestore(savedA5);
|
|||
|
return(noErr);
|
|||
|
}
|
|||
|
|
|||
|
/* GMBlk. Attempts to allocate a handle high in the ProcessMgrZone. If there is no
|
|||
|
* memory in the ProcessMgrZone, check the system zone for the space requested.
|
|||
|
* GMBlk pays attention to emMinSysHeapFreeSpace (denotes how much free we should
|
|||
|
* keep in the system zone.) If there is space in sysZone we call ReserveMemSys
|
|||
|
* (forces next block allocated to be low in the system heap), then NewHandleSys
|
|||
|
* for the memory. NOTE: FreeMemSys() - logicalSize is conservative. The ReserveMemSys
|
|||
|
* will rearrange the heap.
|
|||
|
* GMBlk is called by some puppet string routines, some routines in AppleEventExtensions
|
|||
|
* and most memory allocation paths in ePPC. Most of the memory will be locked due to being
|
|||
|
* accessed from interrupt level by the PPCToolbox.
|
|||
|
*/
|
|||
|
Handle
|
|||
|
GMBlk(u_size logicalSize, OSErr *error)
|
|||
|
{
|
|||
|
Handle aHdl;
|
|||
|
|
|||
|
// <11> If allocateGMBlkInSysHeap is set, it means that an application is quitting, and we<77>re trying to allocate
|
|||
|
// a session record for the appDiedEvent. In this case, always create this session record, even if it means
|
|||
|
// taking the system heap down below the gauranteed minimum free space. To save some
|
|||
|
// code, we<77>re going to do this with a skanky goto. This saves two tests of allocateGMBlkInSysHeap.
|
|||
|
|
|||
|
|
|||
|
if (allocateGMBlkInSysHeap) // <11>
|
|||
|
goto allocateBlock; // <11>
|
|||
|
|
|||
|
aHdl = ProcessMgrHiNewHandle(logicalSize, nil);
|
|||
|
if ((*error = MEMERROR) != noErr)
|
|||
|
{
|
|||
|
if ((FreeMemSys() - logicalSize) > GetExpandMemMinSysHeapFreeSpace())
|
|||
|
{
|
|||
|
allocateBlock:
|
|||
|
ReserveMemSys(logicalSize);
|
|||
|
if ((*error = MEMERROR) == noErr)
|
|||
|
{
|
|||
|
aHdl = NewHandleSys(logicalSize);
|
|||
|
*error = MEMERROR;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
*error = memFullErr;
|
|||
|
}
|
|||
|
return(aHdl);
|
|||
|
}
|
|||
|
|
|||
|
/* ProcessMgrNewHandle. Allocate a handle in the ProcessMgrZone.
|
|||
|
* Assumes A5 == PROCESSMGRGLOBALS
|
|||
|
*/
|
|||
|
Handle
|
|||
|
ProcessMgrNewHandle(u_size logicalSize)
|
|||
|
{
|
|||
|
Handle retVal;
|
|||
|
THz theZone;
|
|||
|
|
|||
|
SafeSetZone(theZone, ProcessMgrZone);
|
|||
|
retVal = NewHandle(logicalSize);
|
|||
|
SafeRestoreZone(theZone);
|
|||
|
|
|||
|
/* Be kind to the system heap and make sure we're not taking too much. */
|
|||
|
ReclaimSpaceIfSysHeapLow(&retVal);
|
|||
|
|
|||
|
return(retVal);
|
|||
|
}
|
|||
|
|
|||
|
/* c_TempNewHandle. Allocates a relocateable block from our zone for general use
|
|||
|
* by an application. We record the allocation so all such can be deallocated when
|
|||
|
* the application terminates. Allocates the block high in case the caller decides
|
|||
|
* to lock it without moving it high.
|
|||
|
*/
|
|||
|
pascal Handle
|
|||
|
c_TempNewHandle(u_size logicalSize, OSErr *pResultCode)
|
|||
|
{
|
|||
|
Handle retVal;
|
|||
|
HListHdl hList;
|
|||
|
unsigned long olda5;
|
|||
|
|
|||
|
olda5 = ProcessMgrA5SimpleSetup();
|
|||
|
assert((pCurrentProcess->p_pcb != nil) && ((*pCurrentProcess->p_pcb)->tempMemHListHdl != nil));
|
|||
|
|
|||
|
retVal = ProcessMgrHiNewHandle(logicalSize, nil);
|
|||
|
if ((*pResultCode = MEMERROR) == noErr)
|
|||
|
{
|
|||
|
hList = (pCurrentProcess->p_systemModeLevel == 0) ? (*pCurrentProcess->p_pcb)->tempMemHListHdl : SystemTempMemHList;
|
|||
|
if (AddToHList(hList,(HListElem)retVal) != noErr)
|
|||
|
{
|
|||
|
*pResultCode = MEMERROR;
|
|||
|
DisposHandle(retVal);
|
|||
|
retVal = nil;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
A5SimpleRestore(olda5);
|
|||
|
return(retVal);
|
|||
|
}
|
|||
|
|
|||
|
/* LikelyTempMemHList. Before we leap right into a semi-expensive scan of a guy's
|
|||
|
* temp memory lists, we can make couple of cheap checks to eliminate values that
|
|||
|
* can not be found. First, if the value is lower than the beginning of the Process Mgr
|
|||
|
* zone, it is out of bounds (like nil or in the system heap). Second, we make sure
|
|||
|
* the value is not within the application partition (this works even if its from a
|
|||
|
* zone-within-a-zone in the application).
|
|||
|
* IMPORTANT: Assumes the tElem has already been stripped, if necessary.
|
|||
|
* NOTE: The elimination checks should stay fairly modest, because many processes
|
|||
|
* won't have any temporary memory at all, meaning the list search is cheap anyway.
|
|||
|
* NOTE: Assumes a5 == PROCESSMGRGLOBALS
|
|||
|
*/
|
|||
|
Boolean
|
|||
|
LikelyTempMemHList(HListElem tElem, HListHdl *hList)
|
|||
|
{
|
|||
|
Boolean retVal;
|
|||
|
PEntryPtr theProc;
|
|||
|
|
|||
|
retVal = false;
|
|||
|
theProc = pCurrentProcess;
|
|||
|
if ( ((Ptr) tElem > ProcessMgrZone)
|
|||
|
&& (theProc != nil)
|
|||
|
&& (((Ptr)tElem < theProc->p_zone)
|
|||
|
|| ((Ptr)tElem >= ((Ptr)theProc->p_zone + theProc->p_size))) )
|
|||
|
{
|
|||
|
*hList = (*theProc->p_pcb)->tempMemHListHdl;
|
|||
|
retVal = true;
|
|||
|
}
|
|||
|
|
|||
|
return(retVal);
|
|||
|
}
|
|||
|
|
|||
|
/* InCurrTempMem. Takes a potential HListElem from the temporary memory allocations
|
|||
|
* of the current process, and verifies it. Returns an OSErr if we couldn't spot it.
|
|||
|
* NOTE: Assumes a5 == PROCESSMGRGLOBALS
|
|||
|
*/
|
|||
|
OSErr
|
|||
|
InCurrTempMem(HListElem hElem)
|
|||
|
{
|
|||
|
OSErr retval=qErr;
|
|||
|
HListHdl hList;
|
|||
|
|
|||
|
hElem = (HListElem) StripAddress((Ptr) hElem);
|
|||
|
if (LikelyTempMemHList(hElem,&hList))
|
|||
|
{
|
|||
|
if (HListExists(hList))
|
|||
|
retval = InHList(hList,hElem);
|
|||
|
|
|||
|
if (retval != noErr)
|
|||
|
retval = InHList(SystemTempMemHList, hElem);
|
|||
|
}
|
|||
|
|
|||
|
return(retval);
|
|||
|
}
|
|||
|
|
|||
|
/* RemoveCurrTempMem. Takes a potential HListElem from the temporary memory allocations
|
|||
|
* of the current process, and de-registers the allocation. Returns an OSErr if we didn't
|
|||
|
* deregister anything.
|
|||
|
* NOTE: Assumes a5 == PROCESSMGRGLOBALS
|
|||
|
*/
|
|||
|
OSErr
|
|||
|
RemoveCurrTempMem(HListElem hElem)
|
|||
|
{
|
|||
|
Boolean retval=qErr;
|
|||
|
HListHdl hList;
|
|||
|
|
|||
|
hElem = (HListElem) StripAddress((Ptr) hElem);
|
|||
|
if (LikelyTempMemHList(hElem, &hList))
|
|||
|
{
|
|||
|
if (HListExists(hList))
|
|||
|
retval = RemoveFromHList(hList, hElem);
|
|||
|
|
|||
|
if (retval != noErr)
|
|||
|
retval = RemoveFromHList(SystemTempMemHList, hElem);
|
|||
|
}
|
|||
|
|
|||
|
return retval;
|
|||
|
}
|
|||
|
|
|||
|
/* RecoverCurrTempHdl. Takes a potential master pointer of a temporary memory handle, and
|
|||
|
* returns the handle. It's similar to RecoverHandle.
|
|||
|
* NOTE: Assumes a5 == PROCESSMGRGLOBALS
|
|||
|
*/
|
|||
|
Handle
|
|||
|
RecoverCurrTempHdl(Ptr targetPtr)
|
|||
|
{
|
|||
|
Handle retVal;
|
|||
|
HListHdl hList;
|
|||
|
|
|||
|
retVal = nil;
|
|||
|
targetPtr = StripAddress((Ptr) targetPtr);
|
|||
|
if (LikelyTempMemHList((HListElem) targetPtr, &hList))
|
|||
|
{
|
|||
|
if (HListExists(hList))
|
|||
|
retVal = (Handle) RecoverHListElem(hList, targetPtr);
|
|||
|
|
|||
|
if (retVal == nil)
|
|||
|
retVal = (Handle) RecoverHListElem(SystemTempMemHList, targetPtr);
|
|||
|
}
|
|||
|
|
|||
|
return(retVal);
|
|||
|
}
|
|||
|
|
|||
|
/* These have to stay in seg Main since they call glue but don't set up a5 */
|
|||
|
#ifdef MORE_SEGMENTS
|
|||
|
#pragma segment Main
|
|||
|
#endif MORE_SEGMENTS
|
|||
|
|
|||
|
/* TempHLock. Lock the relocatable block, preventing it from being moved
|
|||
|
* within its heap zone.
|
|||
|
*/
|
|||
|
pascal void
|
|||
|
c_TempHLock(Handle hdl, OSErr *pResultCode)
|
|||
|
{
|
|||
|
HLock(hdl);
|
|||
|
*pResultCode = MEMERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/* TempHUnLock. UnLock the relocatable block, allowing it to be moved within
|
|||
|
* its heap zone.
|
|||
|
*/
|
|||
|
pascal void
|
|||
|
c_TempHUnLock(Handle hdl, OSErr *pResultCode)
|
|||
|
{
|
|||
|
HUnlock(hdl);
|
|||
|
*pResultCode = MEMERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/* TempDisposeHandle. Release the memory occupied by the relocatable block whose
|
|||
|
* handle is h.
|
|||
|
*/
|
|||
|
pascal void
|
|||
|
c_TempDisposeHandle(Handle hdl, OSErr *pResultCode)
|
|||
|
{
|
|||
|
DisposHandle(hdl);
|
|||
|
*pResultCode = MEMERROR;
|
|||
|
}
|
|||
|
|
|||
|
#ifdef MM_DEBUG
|
|||
|
/* Check for entries in the system resource map that have MPs in an application heap.
|
|||
|
* The check is enabled by holding down the command key (by itself).
|
|||
|
*/
|
|||
|
Boolean
|
|||
|
ToggleDoCheck(Boolean alreadyChecking)
|
|||
|
{
|
|||
|
EventRecord doCheckEventRec;
|
|||
|
Boolean doToggle;
|
|||
|
|
|||
|
#define noEventMask 0
|
|||
|
#define CHECK_SKIP_MODIFIERS (cmdKey+shiftKey+optionKey)
|
|||
|
#define DONT_SKIP_MODIFIERS (cmdKey+optionKey)
|
|||
|
(void)OSEventAvail(noEventMask, &doCheckEventRec);
|
|||
|
|
|||
|
if ( (doCheckEventRec.modifiers & CHECK_SKIP_MODIFIERS) == DONT_SKIP_MODIFIERS )
|
|||
|
{
|
|||
|
if (alreadyChecking = !alreadyChecking)
|
|||
|
dbmsg("Turning on sys map and MP checking...");
|
|||
|
else
|
|||
|
dbmsg("Turning off sys map and MP checking...");
|
|||
|
}
|
|||
|
return alreadyChecking;
|
|||
|
}
|
|||
|
|
|||
|
static Boolean doCheck = true;
|
|||
|
static Boolean isSafeNow = false;
|
|||
|
|
|||
|
void
|
|||
|
CheckSysMapForBadMPs(void)
|
|||
|
{
|
|||
|
short *pTypeList;
|
|||
|
TypeEntry *pCurType;
|
|||
|
RefEntry *pCurRef;
|
|||
|
short cTypes, cResources;
|
|||
|
u_long sysLimit;
|
|||
|
|
|||
|
isSafeNow = true;
|
|||
|
|
|||
|
if ((doCheck = ToggleDoCheck(doCheck)) == false)
|
|||
|
return;
|
|||
|
|
|||
|
pTypeList = *SYSMAPHANDLE + 24;
|
|||
|
pTypeList = *SYSMAPHANDLE + *pTypeList;
|
|||
|
pCurType = pTypeList + 1;
|
|||
|
cTypes = *pTypeList;
|
|||
|
sysLimit = StripAddress((Ptr) SYSZONE->bkLim);
|
|||
|
while (cTypes >= 0)
|
|||
|
{
|
|||
|
pCurRef = (Ptr)pTypeList + pCurType->refListOffset;
|
|||
|
|
|||
|
cResources = pCurType->cResources;
|
|||
|
while (cResources >= 0)
|
|||
|
{
|
|||
|
if ((StripAddress((Ptr) pCurRef) > sysLimit)
|
|||
|
dbmsg("Bad Resource!");
|
|||
|
pCurRef++;
|
|||
|
--cResources;
|
|||
|
}
|
|||
|
|
|||
|
pCurType++;
|
|||
|
--cTypes;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#define IS_HANDLE_IN_ZONE(theHdl, theZone) (((Ptr)(theHdl) > (Ptr)(theZone)) && ((Ptr)(theHdl) < (theZone)->bkLim))
|
|||
|
|
|||
|
/* Check that all (free) MPs in this zone fall within this zone */
|
|||
|
void
|
|||
|
CheckZoneForBadFreeMPs(THz theZone)
|
|||
|
{
|
|||
|
Ptr *pMP;
|
|||
|
|
|||
|
if (!doCheck)
|
|||
|
return;
|
|||
|
|
|||
|
theZone = StripAddress((Ptr) theZone);
|
|||
|
|
|||
|
for (pMP = theZone->hFstFree; pMP != nil; pMP = (Ptr *)*pMP)
|
|||
|
{
|
|||
|
pMP = StripAddress((Ptr) pMP);
|
|||
|
if (!(IS_HANDLE_IN_ZONE(pMP, theZone)))
|
|||
|
{
|
|||
|
dbmsg("Bad free MP list in given zone");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* Return the correct zone for the purged handle.
|
|||
|
* A5 world needed: PROCESSMGRGLOBALS
|
|||
|
*/
|
|||
|
THz
|
|||
|
GetCorrectZone(Handle purgedHdl)
|
|||
|
{
|
|||
|
PEntryPtr pProc;
|
|||
|
THz theZone;
|
|||
|
|
|||
|
if ((Ptr)purgedHdl < SYSZONE || (Ptr)purgedHdl > ProcessMgrZone->bkLim)
|
|||
|
return nil; /* Out of all bounds */
|
|||
|
|
|||
|
if ((Ptr)purgedHdl < SYSZONE->bkLim)
|
|||
|
return SYSZONE;
|
|||
|
|
|||
|
pProc = pProcessList;
|
|||
|
while (pProc != nil)
|
|||
|
{
|
|||
|
assert(IsProcessEntry(pProc));
|
|||
|
theZone = (THz)(StripAddess(pProc->p_zone));
|
|||
|
|
|||
|
if (IS_HANDLE_IN_ZONE(purgedHdl, theZone))
|
|||
|
return theZone;
|
|||
|
pProc = pProc->p_NextProcess;
|
|||
|
}
|
|||
|
|
|||
|
/* Couldn't find in any of the app zones so must be in Process Mgr zone */
|
|||
|
return ProcessMgrZone;
|
|||
|
}
|
|||
|
|
|||
|
/* Check if given handle is "bad" */
|
|||
|
void
|
|||
|
CheckBadHandle(Handle hdl)
|
|||
|
{
|
|||
|
unsigned long olda5;
|
|||
|
THz correctZone, GetCorrectZone(Handle);
|
|||
|
THz pZone = &correctZone;
|
|||
|
|
|||
|
olda5 = ProcessMgrA5SimpleSetup();
|
|||
|
|
|||
|
hdl = (Handle)(StripAddress((Ptr) hdl)); /* Strip! */
|
|||
|
|
|||
|
if (isSafeNow && doCheck)
|
|||
|
{
|
|||
|
if (hdl == nil)
|
|||
|
{
|
|||
|
dbmsg("Operating on nil handle");
|
|||
|
}
|
|||
|
else if (*hdl == nil)
|
|||
|
{
|
|||
|
/* Purged */
|
|||
|
if ((correctZone = GetCorrectZone(hdl)) == nil)
|
|||
|
dbmsg("Couldn't find a zone for purged handle");
|
|||
|
else if (correctZone != THEZONE)
|
|||
|
{
|
|||
|
if (THEZONE == ProcessMgrZone)
|
|||
|
{
|
|||
|
dbmsg("Purged handle op possibly trashing ProcessMgrZone MP list");
|
|||
|
}
|
|||
|
else if (THEZONE == SYSZONE)
|
|||
|
{
|
|||
|
dbmsg("Purged handle op possibly trashing sys zone MP list");
|
|||
|
}
|
|||
|
else if (!(THEZONE == APPLZONE && correctZone == SYSZONE))
|
|||
|
{
|
|||
|
dbmsg("Bad zone for operation on purged handle");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
A5SimpleRestore(olda5);
|
|||
|
}
|
|||
|
|
|||
|
#endif MM_DEBUG
|