YggLockInternal.mesa
Copyright Ó 1985, 1988 by Xerox Corporation. All rights reserved.
Last edited by
MBrown on January 30, 1984 12:19:25 pm PST
Kupfer, February 14, 1985 4:49:41 pm PST
Bob Hagmann May 3, 1988 10:05:42 am PDT
Carl Hauser, March 16, 1987 1:43:06 pm PST
DIRECTORY
YggEnvironment,
YggInternal,
BasicTime,
YggLock;
YggLockInternal: CEDAR DEFINITIONS = BEGIN
LockID: TYPE = YggLock.LockID;
LockMode: TYPE = YggLock.LockMode;
Lock: TYPE = REF LockRep;
Header: TYPE = REF LockRep.header;
Request: TYPE = REF LockRep.request;
GrantedRequest: TYPE = REF LockRep.request.granted;
WaitingRequest: TYPE = REF LockRep.request.waiting;
LockTransHeader: TYPE = REF LockRep.request.transHeader;
LockType: TYPE = {header, request};
RequestLockType: TYPE = {granted, waiting, transHeader};
LockRep: TYPE = RECORD [
requestList: Lock ← NIL,
circular list consisting of one LockRep.header, one or more LockRep.requests with granted or waiting variant.
body: SELECT type: LockType FROM
header => [
lockID: LockID ← YggLock.nullLockID,
next: Header ← NIL-- link field for hash table package
],
request => [
trans: YggInternal.TransHandle,
transList: Request,
circular list consisting of one LockRep.request.transHeader, zero or more LockRep.request.granted, all with same value of trans. all waiting requests are linked into a single list, through this field.
lockID: LockID ← YggLock.nullLockID,
mode: LockMode,
rest: SELECT type: RequestLockType FROM
granted => [
count: NAT
],
waiting => [
somethingChanged: CONDITION,
giveUp: BOOLFALSE,
whyGivingUp: WhyGivingUp ← TRASH, -- meaningful only if giveUp
isConversion: BOOLFALSE,
startTime: BasicTime.GMT
],
transHeader => [ -- requestList = NIL
nLocks: INT
],
ENDCASE
],
ENDCASE
];
WhyGivingUp: TYPE = { abort, timeout };
GetInfo: PROC [
generalInfoProc: GeneralInfoProc ← NIL,
lockEnumProc: LockEnumProc ← NIL,
waitingRequestEnumProc: WaitingRequestEnumProc ← NIL,
waitingRequestEnumProc2: WaitingRequestEnumProc ← NIL];
Enters YggLock monitor. If generalInfoProc # NIL, calls it with current values of its parameters. On return, if lockEnumProc # NIL, enumerates the locks calling lockEnumProc until it returns quit: TRUE or all locks have been enumerated. Then if waitingRequestEnumProc # NIL, enumerates the waiting requests in the same fashion. Then if waitingRequestEnumProc2 # NIL, enumerates the waiting requests again, in the same fashion. Finally returns, releasing the YggLock monitor. None of the proc parameters should not call into monitors that may be held while calling into the YggLock monitor (including the YggLock monitor itself).
GeneralInfoProc: TYPE = PROC [nLocks, nRequests, nSetCalls, nSetCallsWaited: INT];
LockEnumProc: TYPE = PROC [h: Header] RETURNS [stop: BOOL];
WaitingRequestEnumProc: TYPE = PROC [wr: WaitingRequest] RETURNS [stop: BOOL];
TimeoutWaitingRequest: PROC [wr: WaitingRequest];
Cause the YggLock.Set call to raise YggLock.Failed[timeout].
LockIDFromRH: PROC [r: Request] RETURNS [LockID] = INLINE {
Chases down pointers until it finds the header (which holds the LockID that "wr" is waiting for). You should have the YggLock monitor lock before calling this routine.
hCopy: Lock;
h: Lock ← r.requestList;
DO
IF h = r THEN ERROR;
hCopy ← h;
WITH hCopy^ SELECT FROM
hh: LockRep.header => RETURN [hh.lockID];
rr: LockRep.request => h ← hCopy.requestList;
ENDCASE => ERROR;
ENDLOOP;
};
END.
CHANGE LOG.
Edited on February 14, 1985 2:54:19 pm PST, by Kupfer
Added LockIDFromWRH. This is INLINE so that it can be defined in LockInternal, where anybody inside Alpine can use it (assuming they have the monitor lock for Lock).