-- Cedar Remote Debugging: MapLog handling -- WVMMapLog.mesa -- Andrew Birrell September 30, 1982 10:40 am DIRECTORY CPSwapDefs USING[ ExternalStateVector, SwapInfo ], PSB USING[ PDA ], VMMapLog, WorldVM USING[Address, CopyRead, World], WVMPrivate; WVMMapLog: MONITOR IMPORTS WorldVM, WVMPrivate EXPORTS WVMPrivate, WorldVM = BEGIN MapLogObject: PUBLIC TYPE = RECORD[ found: CARDINAL _ 0, -- maplog entries read in so far -- entries: REF Entries]; MapLog: TYPE = REF MapLogObject; Entries: TYPE = RECORD[ SEQUENCE length: CARDINAL OF Entry ]; Entry: TYPE = VMMapLog.Entry _ NULL; CreateMapLog: PUBLIC PROC[world: WorldVM.World] RETURNS[ MapLog ] = BEGIN RETURN[NEW[MapLogObject _ [0,NIL]]] END; ReadMapLog: PUBLIC PROC[world: WorldVM.World, log: MapLog] RETURNS[patchTable, loadState: WorldVM.Address] = BEGIN swapInfo: CPSwapDefs.SwapInfo; swapInfoAddr: WorldVM.Address = LOOPHOLE[@PSB.PDA.available]; esv: CPSwapDefs.ExternalStateVector; esvAddr: WorldVM.Address; descr: VMMapLog.Descriptor; descrAddr: WorldVM.Address; logBase: WorldVM.Address; logSize: CARDINAL; -- number of entries, excluding self -- WorldVM.CopyRead[world, swapInfoAddr, SIZE[CPSwapDefs.SwapInfo], @swapInfo]; esvAddr _ LOOPHOLE[swapInfo.externalStateVector]; WorldVM.CopyRead[world, esvAddr, SIZE[CPSwapDefs.ExternalStateVector], @esv]; loadState _ WVMPrivate.PageAddress[esv.loadstatepage]; descrAddr _ LOOPHOLE[esv.mapLog]; WorldVM.CopyRead[world, descrAddr, SIZE[VMMapLog.Descriptor], @descr]; patchTable _ LOOPHOLE[descr.patchTable]; logBase _ WVMPrivate.PageAddress[descr.self.page]; logSize _ LOOPHOLE[descr.limit, CARDINAL] / SIZE[VMMapLog.Entry]; log.entries _ NEW[Entries[logSize+1--self--]]; log.entries[0] _ descr.self; log.found _ 1; BEGIN used: CARDINAL = MIN[logSize, (descr.writer - descr.reader) / SIZE[VMMapLog.Entry] ]; IF logBase # 0 AND logSize > 0 THEN WorldVM.CopyRead[world, logBase, used*SIZE[VMMapLog.Entry], @log.entries[1]]; -- may call GetMapLogEntry -- log.found _ log.found+used; END; END; LocalPatchTable: PUBLIC PROC RETURNS[patchTable: WorldVM.Address] = BEGIN swapInfo: LONG POINTER TO CPSwapDefs.SwapInfo = LOOPHOLE[@PSB.PDA.available]; descr: LONG POINTER TO VMMapLog.Descriptor = swapInfo.externalStateVector.mapLog; RETURN[LOOPHOLE[descr.patchTable]] END; AddressFault: PUBLIC ERROR[mempage: WVMPrivate.PageNumber] = CODE; lastEntryIndex: CARDINAL _ 0; -- hint for log entry to try first -- GetMapLogEntry: PUBLIC ENTRY PROC[log: MapLog, mempage: WVMPrivate.PageNumber] RETURNS[ WVMPrivate.DiskAddress ] = BEGIN ENABLE UNWIND => NULL; entry: LONG POINTER TO Entry _ IF lastEntryIndex IN [0..log.found) -- lastEntryIndex may be for another log! THEN @log.entries[lastEntryIndex] ELSE NIL; IF entry = NIL OR entry.kind = nil OR mempage NOT IN [entry.page..entry.page+entry.count) THEN -- sigh! Need to search for it. -- BEGIN FOR i: CARDINAL IN [0..log.found) DO entry _ @log.entries[lastEntryIndex_i]; IF entry.kind # nil AND mempage IN [entry.page..entry.page+entry.count) THEN EXIT; REPEAT FINISHED => ERROR AddressFault[mempage] ENDLOOP; END; WITH e: entry SELECT FROM disk => RETURN[[e.driveTag, e.diskPage, mempage-e.page, e.labelCheck]]; ENDCASE => ERROR AddressFault[mempage] END; END.