-- RTStopProcessImpl.Mesa -- last edited September 9, 1982 7:49 am by Paul Rovner DIRECTORY Process USING[Abort, Priority, priorityForeground], ProcessOperations USING[IndexToHandle], PSB USING[PDA], RTBasic USING[TV], RTProcess USING[Status, Valid, InvalidProcess, HandleToPSBI], RTProcessPrivate USING[ProcessObject]; RTStopProcessImpl: MONITOR LOCKS h USING h: Handle IMPORTS Process, ProcessOperations, RTProcess EXPORTS RTProcess = BEGIN OPEN RTProcess; -- types Handle: TYPE = REF Object; Object: PUBLIC TYPE = RTProcessPrivate.ProcessObject; -- SIGNALs NotStopped: PUBLIC SIGNAL[h: Handle] = CODE; InvalidPriority: PUBLIC SIGNAL[h: Handle, p: Process.Priority] = CODE; NIY: SIGNAL = CODE; -- PROCs GetStatus: PUBLIC PROC[h: Handle] RETURNS[RTProcess.Status] = { IF NOT Valid[h] THEN RETURN[invalid]; IF h.stopState = stopped THEN RETURN[stopped]; ERROR NIY }; Stop: PUBLIC PROC[h: Handle] = { IF NOT Valid[h] THEN ERROR InvalidProcess[h]; IF h.stopState # stoppable THEN RETURN; -- Wait for h's priority to be <= Process.priorityForeground, then grab it with the Sponge. -- Scan h's call stack until a client module is found, find the next clean point there and place a client BP h.stopState _ stopping; -- release the sponge -- NOTE: Some time later, when the client BP is hit by the client process, remove the BP, h.stopState _ stopped, and cause the client process to WAIT h.resume. }; Proceed: PUBLIC ENTRY PROC[h: Handle] = { IF NOT Valid[h] THEN ERROR InvalidProcess[h]; IF h.stopState = stopped THEN {h.stopState _ stoppable; NOTIFY h.resume} ELSE IF h.stopState = stopping THEN {h.stopState _ stoppable; -- remove the BP } ELSE SIGNAL NotStopped[h]; }; -- raises NotStopped ReturnFrom: PUBLIC ENTRY PROC[h: Handle, frameFromWhichToReturn: RTBasic.TV, result: RTBasic.TV _ NIL] = { IF NOT Valid[h] THEN ERROR InvalidProcess[h]; IF h.stopState = stopped THEN {h.stopState _ unwinding; --remember "frameFromWhichToReturn" and "result"; Process.Abort[HandleToPSBI[h]]} -- NOTE 1, NOTE 3 ELSE SIGNAL NotStopped[h]; -- NOTE 2 }; -- raises NotStopped Abort: PUBLIC ENTRY PROC[h: Handle] = { IF NOT Valid[h] THEN ERROR InvalidProcess[h]; IF h.stopState = stopped THEN {h.stopState _ aborting; Process.Abort[HandleToPSBI[h]]} -- NOTE 1, NOTE 3 ELSE IF h.stopState = stopping --and h is waiting on a CV THEN {--remove the BP; Process.Abort[HandleToPSBI[h]]} ELSE SIGNAL NotStopped[h]; -- NOTE 2 }; -- raises NotStopped TopFrame: PUBLIC PROC[h: Handle] RETURNS[RTBasic.TV--for a frame--] = { IF NOT Valid[h] THEN ERROR InvalidProcess[h]; IF h.stopState = stopped THEN RETURN[NIL--find h's top client frame (skip back over BP handler frames)--] ELSE IF h.stopState = stopping THEN ERROR ELSE ERROR NotStopped[h]; }; -- raises NotStopped, InvalidPriority, InvalidProcess ChangePriority: PUBLIC PROC[h: Handle, new: Process.Priority] RETURNS[old: Process.Priority] = { IF NOT Valid[h] THEN ERROR InvalidProcess[h]; IF new > Process.priorityForeground THEN ERROR InvalidPriority[h, new]; old _ PSB.PDA[ProcessOperations.IndexToHandle[HandleToPSBI[h]]].link.priority; IF h.stopState = stopped THEN SIGNAL NIY -- NOTE change h's priority: must its PSB be moved among system queues? ELSE SIGNAL NotStopped[h]; -- NOTE 2 }; -- NOTE 1: Current catch phrases in the frame where the client BP was placed will not be executed. -- In particular, ENABLE UNWIND => NULL in an ENTRY frame will not be executed, hence the monitor -- lock will not be released. This will be fixed when the new instruction set is installed. -- NOTE 2: The process may not have hit the BP yet, especially if it is still WAITing on a -- CV or to enter a MONITOR. -- NOTE 3: A catch phrase for ABORT in the stopper will -- IF h.stopState = unwinding -- THEN unwind frames through "frameFromWhichToReturn"; -- h.stopState _ stoppable; -- fix the PSB (which was marked "aborted"); -- stuff "result" into a result record and return to the caller of "frameFromWhichToReturn" -- ELSE IF h.stopState = aborting -- THEN NULL -- ELSE ERROR; END.