-- File: VMPageOps.mesa -- Last edited by Levin: 30-Oct-81 16:21:03 DIRECTORY VMDefs USING [Page], VMPrivate USING [ AcquirePage, AddressToHandle, FileObject, PageHandle, ReleasePage, ValidatePageAddress, WaitUntilStable, Writable, WritePageToFS]; VMPageOps: PROGRAM IMPORTS VMPrivate EXPORTS VMDefs = BEGIN OPEN VMPrivate; -- This monitor synchronizes access to PageObjects by main memory address, and -- therefore is implicitly concerned with pages for which useCount > 0. For this -- reason, the AddressToHandle mapping is assumed to be stable and can be safely used -- outside the cache monitor. -- Miscellaneous Declarations -- BadPage: ERROR = CODE; FileReadOnly: ERROR = CODE; -- Procedures and Types Exported to VMDefs -- FileObject: PUBLIC TYPE = VMPrivate.FileObject; Mark: PUBLIC PROCEDURE [page: VMDefs.Page] = BEGIN p: PageHandle; [] ← ValidatePageAddress[AddressToHandle[page]]; p ← AcquireValidatedPage[page, FALSE]; CheckReadOnly[p]; p.dirty ← TRUE; ReleasePage[p]; END; Start: PUBLIC PROCEDURE [page: VMDefs.Page] = BEGIN p: PageHandle ← AcquireValidatedPage[page]; IF p.dirty THEN WritePageToFS[page: p, wait: FALSE] ELSE ReleasePage[p]; END; Wait: PUBLIC PROCEDURE [page: VMDefs.Page] = BEGIN p: PageHandle ← AddressToHandle[page]; IF p.useCount = 0 THEN ERROR BadPage; IF p.file = NIL THEN RETURN; IF WaitUntilStable[p, writing] = unstable THEN BEGIN -- write was never started; retry it synchronously ReleasePage[p]; StartWait[page]; END; END; MarkStart: PUBLIC PROCEDURE [page: VMDefs.Page] = BEGIN p: PageHandle ← AcquireValidatedPage[page]; CheckReadOnly[p]; p.dirty ← TRUE; WritePageToFS[page: p, wait: FALSE]; END; StartWait: PUBLIC PROCEDURE [page: VMDefs.Page] = BEGIN p: PageHandle ← AcquireValidatedPage[page]; IF p.dirty THEN WritePageToFS[page: p, wait: TRUE] ELSE ReleasePage[p]; END; MarkStartWait: PUBLIC PROCEDURE [page: VMDefs.Page] = BEGIN p: PageHandle ← AcquireValidatedPage[page]; CheckReadOnly[p]; p.dirty ← TRUE; WritePageToFS[page: p, wait: TRUE]; END; -- Internal Procedures -- AcquireValidatedPage: PROCEDURE [ page: VMDefs.Page, mustHaveFile: BOOLEAN ← TRUE] RETURNS [p: PageHandle] = -- does its best to check that 'page' is a valid address at this instant and -- returns the associated page object, marked unstable. BEGIN AcquirePage[p ← AddressToHandle[page]]; IF p.useCount > 0 AND (~mustHaveFile OR p.file ~= NIL) THEN RETURN; ERROR BadPage; END; CheckReadOnly: PROCEDURE [p: PageHandle] = -- ensures that 'p' comes from a file that permits writing. BEGIN IF p.file = NIL OR Writable[p.file] THEN RETURN; ERROR FileReadOnly; END; END.