FSLockImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Russ Atkinson, November 7, 1984 11:27:51 am PST
Schroeder, November 15, 1983 1:29 pm
DIRECTORY
FS USING [Lock],
FSBackdoor USING [Version],
FSLock USING [ActiveFile, LookupLock, RemoveLock],
Rope USING [ROPE];
FSLockImpl: CEDAR MONITOR
LOCKS a USING a: FSLock.ActiveFile
IMPORTS FSLock
EXPORTS FSLock
= {
ActiveFile: TYPE = FSLock.ActiveFile;
ROPE: TYPE = Rope.ROPE;
Version: TYPE = FSBackdoor.Version;
Procedures exported to FSLock
LockRecord: PUBLIC PROC [volumePrefix, nameBody: ROPE, version: Version] RETURNS [a: ActiveFile, ok: BOOL] = {
InnerLockRecord: ENTRY PROC [a: ActiveFile] RETURNS [{gotIt, wait, dead}] = {
IF a.nameBody = NIL THEN RETURN [dead];
IF a.recordLock THEN RETURN [wait];
a.recordLock ← TRUE;
RETURN [gotIt];
};
DO
a ← FSLock.LookupLock[volumePrefix, nameBody, version];
SELECT InnerLockRecord[a] FROM
gotIt => ok ← TRUE;
wait => ok ← FALSE;
dead => LOOP;
ENDCASE => ERROR;
EXIT;
ENDLOOP;
};
checkAgain: CONDITION;
LockAttachedToRecord: PUBLIC PROC [a: ActiveFile] = {
InnerLockAttachedToRecord: PUBLIC ENTRY PROC [a: ActiveFile] = {
ENABLE UNWIND => NULL;
WHILE a.recordLock DO WAIT checkAgain ENDLOOP;
IF a.nameBody = NIL THEN ERROR;
a.recordLock ← TRUE;
};
IF NOT a.recordLock THEN ERROR;
InnerLockAttachedToRecord[a.attachedTo];
};
WaitForRecord: PUBLIC ENTRY PROC [a: ActiveFile] = {
ENABLE UNWIND => NULL;
WHILE a.nameBody # NIL AND a.recordLock DO WAIT checkAgain ENDLOOP;
};
ReleaseRecord: PUBLIC PROC [a: ActiveFile] = {
InnerReleaseRecord: ENTRY PROC [a: ActiveFile] = {
ENABLE UNWIND => NULL;
IF a.recordLock THEN {
may be no record lock to release
a.recordLock ← FALSE;
IF a.fileLockCount = 0 THEN FSLock.RemoveLock[a];
BROADCAST checkAgain;
};
};
IF a = NIL THEN RETURN; -- release of NIL is a nop!
InnerReleaseRecord[a];
};
LockFile: PUBLIC ENTRY PROC [a: ActiveFile, lock: FS.Lock] RETURNS [ok: BOOL] = {
ENABLE UNWIND => NULL;
IF NOT a.recordLock THEN ERROR;
IF a.fileLockCount = 0
THEN a.fileLock ← (IF lock = write THEN write ELSE read)
ELSE { IF lock = write OR (lock = read AND a.fileLock = write) THEN RETURN [FALSE] };
a.fileLockCount ← a.fileLockCount + 1;
RETURN [TRUE];
};
GetAttachment: PUBLIC ENTRY PROC [a: ActiveFile] RETURNS [ActiveFile] = {
ENABLE UNWIND => NULL;
WHILE a.recordLock DO WAIT checkAgain ENDLOOP;
IF a.fileLockCount = 0 THEN ERROR;
RETURN [a.attachedTo];
};
ReportClose: PUBLIC PROC [a: ActiveFile] = {
ReleaseFile: ENTRY PROC [a: ActiveFile] RETURNS [attachedTo: ActiveFile] = {
ENABLE UNWIND => NULL;
WHILE a.recordLock DO WAIT checkAgain ENDLOOP;
IF a.fileLockCount = 0 THEN ERROR;
attachedTo ← a.attachedTo;
a.fileLockCount ← a.fileLockCount - 1;
IF a.fileLockCount = 0 THEN {
a.fileLock ← none;
IF NOT a.recordLock
THEN FSLock.RemoveLock[a];
};
};
att: ActiveFile ← ReleaseFile[a];
IF att # NIL THEN att ← ReleaseFile[att];
IF att # NIL THEN ERROR;
};
}.