FSLockImpl.mesa
Last Edited by: 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
= BEGIN
Procedures exported to FSLock
LockRecord: PUBLIC PROC [volumePrefix, nameBody: Rope.ROPE, version: FSBackdoor.Version] RETURNS [a: FSLock.ActiveFile, ok: BOOLEAN] =
BEGIN
InnerLockRecord: ENTRY PROC [a: FSLock.ActiveFile] RETURNS [{gotIt, wait, dead}] =
BEGIN
IF a.nameBody = NIL THEN RETURN [dead];
IF a.recordLock THEN RETURN [wait];
a.recordLock ← TRUE;
RETURN [gotIt];
END;
DO
a ← FSLock.LookupLock[volumePrefix, nameBody, version];
SELECT InnerLockRecord[a] FROM
gotIt => ok ← TRUE;
wait => ok ← FALSE;
dead => LOOP;
ENDCASE => ERROR;
EXIT;
ENDLOOP;
END;
checkAgain: CONDITION;
LockAttachedToRecord: PUBLIC PROC [a: FSLock.ActiveFile] =
BEGIN
InnerLockAttachedToRecord: PUBLIC ENTRY PROC [a: FSLock.ActiveFile] =
BEGIN
WHILE a.recordLock DO WAIT checkAgain ENDLOOP;
IF a.nameBody = NIL THEN ERROR;
a.recordLock ← TRUE;
END;
IF NOT a.recordLock THEN ERROR;
InnerLockAttachedToRecord[a.attachedTo];
END;
WaitForRecord: PUBLIC ENTRY PROC [a: FSLock.ActiveFile] =
{ WHILE a.nameBody # NIL AND a.recordLock DO WAIT checkAgain ENDLOOP };
ReleaseRecord: PUBLIC PROC [a: FSLock.ActiveFile] =
BEGIN
InnerReleaseRecord: ENTRY PROC [a: FSLock.ActiveFile] =
BEGIN
IF a.recordLock -- may be no record lock to release
THEN BEGIN
a.recordLock ← FALSE;
IF a.fileLockCount = 0 THEN FSLock.RemoveLock[a];
BROADCAST checkAgain;
END;
END;
IF a = NIL THEN RETURN; -- release of NIL is a nop!
InnerReleaseRecord[a];
END;
LockFile: PUBLIC ENTRY PROC [a: FSLock.ActiveFile, lock: FS.Lock] RETURNS [ok: BOOLEAN] =
BEGIN
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];
END;
GetAttachment: PUBLIC ENTRY PROC [a: FSLock.ActiveFile] RETURNS [FSLock.ActiveFile] =
BEGIN
WHILE a.recordLock DO WAIT checkAgain ENDLOOP;
IF a.fileLockCount = 0 THEN ERROR;
RETURN [a.attachedTo];
END;
ReportClose: PUBLIC PROC [a: FSLock.ActiveFile] =
BEGIN
ReleaseFile: ENTRY PROC [a: FSLock.ActiveFile] RETURNS [attachedTo: FSLock.ActiveFile] =
BEGIN
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 BEGIN
a.fileLock ← none;
IF NOT a.recordLock
THEN FSLock.RemoveLock[a];
END;
END;
att: FSLock.ActiveFile ← ReleaseFile[a];
IF att # NIL THEN att ← ReleaseFile[att];
IF att # NIL THEN ERROR;
END;
END.