<<>> <> <> <> <> <<>> DIRECTORY AsynchronousEvents, Process, UnixTypes; AsynchronousEventsImpl: CEDAR MONITOR IMPORTS Process EXPORTS AsynchronousEvents ~ BEGIN OPEN USignal: UnixTypes; UnixSignal: TYPE ~ USignal.Signal; Event: TYPE ~ AsynchronousEvents.Event; EventToSig: ARRAY Event OF UnixSignal = [ SIGHUP, SIGINT, SIGPIPE, SIGSTOP, SIGIO, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGLOST, SIGUSR2 ]; ProcessEventPair: TYPE = RECORD [ process: PROCESS, event: Event ]; Registrations: TYPE = RECORD [ nRegistrations: CARD ¬ 0, s: SEQUENCE maxRegistrations: CARD OF ProcessEventPair ]; registrations: REF Registrations ¬ NEW[ Registrations[10] ]; RegisterInterest: PUBLIC ENTRY PROC [event: Event, interested: BOOL] ~ { self: PROCESS ¬ Process.GetCurrent[]; IF Ok[event, interested, self] THEN RETURN; <> IF registrations.nRegistrations = registrations.maxRegistrations THEN MoreRegistrations[]; FOR i: CARD IN [0..registrations.maxRegistrations) DO IF registrations[i].process = NIL THEN { registrations[i].process ¬ self; registrations[i].event ¬ event; registrations.nRegistrations ¬ registrations.nRegistrations.SUCC; TellPCR[EventToSig[event]]; RETURN; }; ENDLOOP; ERROR; }; TellPCR: PROC [sig: UnixSignal] ~ { IF sig = SIGINT THEN UIORegisterInterestInINTEvent[TRUE] ELSE UIORegisterInterestInEvent[sig, TRUE]; -- PCR botch; UIORegisterInterestInEvent doesn't support SIGINT }; UIORegisterInterestInINTEvent: PROC[ BOOL ] ~ TRUSTED MACHINE CODE { "XR_UIORegisterInterestInINTEvent" }; UIORegisterInterestInEvent: PROC[ UnixSignal, BOOL ] ~ TRUSTED MACHINE CODE { "XR_UIORegisterInterestInEvent" }; Ok: PROC [event: Event, interested: BOOL, process: PROCESS] RETURNS [BOOL] ~ { FOR i: CARD IN [0..registrations.maxRegistrations) DO IF registrations[i].process = process AND registrations[i].event = event THEN { IF NOT interested THEN { registrations[i].process ¬ NIL; registrations.nRegistrations ¬ registrations.nRegistrations.PRED; }; RETURN[ TRUE ]; }; ENDLOOP; RETURN [ NOT interested ]; }; MoreRegistrations: PROC ~ { newRegistrations: REF Registrations ¬ NEW[ Registrations[registrations.maxRegistrations+10] ]; newRegistrations.nRegistrations ¬ registrations.nRegistrations; FOR i: CARD IN [0..registrations.maxRegistrations) DO newRegistrations[i] ¬ registrations[i]; ENDLOOP; registrations ¬ newRegistrations; }; UIOEvent: TYPE ~ RECORD [ <> seqNum: CARD, iopIndex: CARD, id: UnixSignal, info: REF ]; continue: BOOL ¬ TRUE; StopProcessingEvents: PROC ~ { continue ¬ FALSE; }; ProcessEvents: PROC ~ TRUSTED { myEvent: UIOEvent; WHILE continue DO UIOAwaitEvent[@myEvent]; ProcessOneEvent[myEvent]; ENDLOOP; }; UIOAwaitEvent: PROC [POINTER TO UIOEvent] ~ TRUSTED MACHINE CODE { "XR_UIOAwaitEvent" }; ProcessOneEvent: ENTRY PROC [eventInstance: UIOEvent] ~ { FOR i: CARD IN [0..registrations.maxRegistrations) DO IF registrations[i].process # NIL AND EventToSig[registrations[i].event] = eventInstance.id THEN { IF eventInstance.id # SIGINT OR eventInstance.iopIndex = 1 THEN Process.Abort[registrations[i].process ! Process.InvalidProcess => { registrations[i].process ¬ NIL; registrations.nRegistrations ¬ registrations.nRegistrations.PRED; CONTINUE }]; }; ENDLOOP; }; TRUSTED { Process.Detach[ FORK ProcessEvents[] ] }; END.