boot3/ProcessMgr/HList.c
Elliot Nunn 5b0f0cc134 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 10:02:57 +08:00

247 lines
6.5 KiB
C

/*
File: HList.c
Contains: Operations on HLists. An HList is a (handle to) a list of handle
elements, or nil entries.
Written by: Phil Goldman
Copyright: © 1988-1991 by Apple Computer, Inc., all rights reserved.
Change History (most recent first):
<0> 5/12/88 PYG New Today.
*/
#pragma segment kernel_segment
#include <types.h>
#include <errors.h>
#include <memory.h>
#include <toolutils.h>
#include <windows.h>
#include "Glue.h"
#include "Data.h"
#include "Lomem.h"
#include "HList.h"
/* Macro to return HListPtr of element at offset bytes into the given HList */
#define HLISTPTR_AT_OFFSET(hListHdl, offset) ((HListPtr)((Ptr)(*(hListHdl)) + (offset)))
/* AddToHList. Add hListElem to the list of which hListHdl is the handle. Returns
* memFullErr if there is not enough room for hListHdl to be grown by sizeof(hListElem).
*/
OSErr
AddToHList(HListHdl hListHdl, HListElem hListElem)
{
u_size hListHdlSize = GetHandleSize(hListHdl);
register HListPtr pHListElem, pHListElemMax;
OSErr osErr;
assert(hListHdl != nil && *hListHdl != nil);
/* Keep only stripped handles */
hListElem = (HListElem) StripAddress((Ptr) hListElem);
/* First look for an empty slot in the existing list */
pHListElem = *hListHdl;
pHListElemMax = (HListPtr)((Ptr)pHListElem + hListHdlSize);
while (pHListElem < pHListElemMax)
{
if (*pHListElem == nil)
{
/* Found an empty, so set it */
*pHListElem = hListElem;
return noErr;
}
pHListElem++;
}
/* If we got here there is no empty one, so make one */
SetHandleSize(hListHdl, hListHdlSize + sizeof(HListElem));
if ((osErr = MEMERROR) == noErr)
*HLISTPTR_AT_OFFSET(hListHdl, hListHdlSize) = hListElem;
return osErr;
}
/* InHList. Determine whether hListElem in the list of which hListHdl is the handle.
* Returns qErr if not.
*/
OSErr
InHList(HListHdl hListHdl, HListElem hListElem)
{
HListPtr pHListElem;
u_size hListHdlSize;
/* can do nothing if there is no HList! */
if (hListHdl == nil)
return qErr;
assert(*hListHdl != nil);
/* compare stripped target against the each element */
hListElem = (HListElem) StripAddress((Ptr) hListElem);
hListHdlSize = GetHandleSize(hListHdl);
pHListElem = HLISTPTR_AT_OFFSET(hListHdl, hListHdlSize);
while (hListHdlSize != 0)
{
hListHdlSize -= sizeof(HListElem);
if (*--pHListElem == hListElem)
return noErr;
}
/* fall through means no-find */
return qErr;
}
/* RecoverHListElem. Determine whether hListElemMP is a master pointer for a
* handle stored as an HListElem in hListHdl. Return the handle, or nil if not
* found.
*/
HListElem
RecoverHListElem(HListHdl hListHdl, Ptr hListElemMP)
{
HListPtr pHListElem;
u_size hListHdlSize;
/* can do nothing if there is no HList! */
if (hListHdl == nil)
return nil;
assert(*hListHdl != nil);
/* compare stripped target against the value pointed to by each element */
hListElemMP = (Ptr) StripAddress((Ptr) hListElemMP);
hListHdlSize = GetHandleSize(hListHdl);
pHListElem = HLISTPTR_AT_OFFSET(hListHdl, hListHdlSize);
while (hListHdlSize != 0)
{
if (hListElemMP == StripAddress((Ptr) *((Handle)*--pHListElem)))
return *pHListElem;
hListHdlSize -= sizeof(HListElem);
}
/* fall through means no-find */
return nil;
}
/* RemoveFromHList. Remove hListElem to the list of which hListHdl is the handle.
* Returns qErr if hListElem not found in the list. Will only delete one occurrence
* from the list.
* NOTE: Does not move memory if _Munger doesn't.
*/
OSErr
RemoveFromHList(HListHdl hListHdl, HListElem hListElem)
{
HListPtr pHListElem;
u_size hListHdlSize;
/* can do nothing if there is no HList! */
if (hListHdl == nil)
return qErr;
assert(*hListHdl != nil);
/* compare stripped target against the value pointed to by each element */
hListElem = (HListElem) StripAddress((Ptr) hListElem);
hListHdlSize = GetHandleSize(hListHdl);
pHListElem = HLISTPTR_AT_OFFSET(hListHdl, hListHdlSize);
while (hListHdlSize != 0)
{
hListHdlSize -= sizeof(HListElem);
if (*--pHListElem == hListElem)
{
(void)Munger(hListHdl, hListHdlSize, &hListElem, sizeof(hListElem), (Ptr)-1, 0);
return noErr;
}
}
/* fall through means no-find */
return qErr;
}
/* GetFirstHListElem. Find the first HListElem in the list to which hListHdl is
* the handle.
*/
HListElem
GetFirstHListElem(HListHdl hListHdl)
{
assert(hListHdl != nil && *hListHdl != nil);
return (GetHandleSize(hListHdl) >= sizeof(HListElem)) ? **hListHdl : nil;
}
/* ApplyToHListElems. Traverse the HList indirectly pointed to by hListHdl and
* apply (*pHListElemFnc)() to each element.
*/
void
ApplyToHListElems(HListHdl hListHdl, HListElemFnc *pHListElemFnc)
{
register HListPtr pHListElem;
HListElem hListElem;
assert(hListHdl != nil && *hListHdl != nil);
HLock(hListHdl);
/* Call routine on each element */
pHListElem = HLISTPTR_AT_OFFSET(hListHdl, GetHandleSize(hListHdl));
while (pHListElem > *hListHdl)
{
/* extract next element down */
hListElem = *--pHListElem;
/* Call routine on this element */
if (hListElem != nil)
(*pHListElemFnc)(hListElem);
}
HUnlock(hListHdl);
}
/* DestroyHList. Disposes each element in the list and then disposes the list itself.
* Sets THEZONE to ProcessMgrZone for the duration of the disposes. This is so that
* purged handles end up in the right place (we assume that all handles in the HList,
* and the HList block itself, are in ProcessMgrZone).
* NOTE: Assumes that DisposHandle does not move memory (HList block).
* NOTE: Assumes that if disposes can result in moving the ProcessMgrZone, the current
* zone is not ProcessMgrZone (otherwise, our restore at the end would be inconsistent
* with the new zone location). Could use SafeSetZone and SafeRestoreZone to be safe.
*/
void
DestroyHList(HListHdl hListHdl)
{
HListElem hListElem;
register HListPtr pHListElem;
THz saveZone;
assert(hListHdl != nil && *hListHdl != nil);
/* Set up ProcessMgrZone so MPs of purged handles go in its free list */
saveZone = THEZONE;
THEZONE = ProcessMgrZone;
/* Call disposal function on each element */
pHListElem = HLISTPTR_AT_OFFSET(hListHdl, GetHandleSize(hListHdl));
while (pHListElem > *hListHdl)
{
/* extract next element down */
hListElem = *--pHListElem;
/* dispose of it */
if (hListElem != nil)
{
DisposHandle((Handle) hListElem);
assert(MEMERROR == noErr);
}
}
/* Dispose HList */
DisposHandle(hListHdl);
assert(MEMERROR == noErr);
/* Restore the zone and leave */
THEZONE = saveZone;
}