<> <> <> DIRECTORY BufferDefs USING [Buffer, Dequeue, Enqueue, Queue, QueueCleanup, QueueInitialize, QueueLength, QueueObject], CommFlags USING [doStats, doDebug], DriverDefs USING [GetGiantVector, Network, ReturnFreeBuffer, Router, RouterObject], Process USING [SetTimeout, MsecToTicks], SpecialCommunication USING [SpyProc], StatsDefs USING [StatIncr]; DispatcherImpl: MONITOR IMPORTS BufferDefs, DriverDefs, Process, StatsDefs EXPORTS BufferDefs, DriverDefs, SpecialCommunication SHARES BufferDefs = BEGIN <> Network: PUBLIC TYPE = DriverDefs.Network; mainFork: PROCESS; dispatcherPleaseDie: BOOLEAN; dispatcherReady: CONDITION; globalInputQueue: BufferDefs.Queue = NEW[BufferDefs.QueueObject]; globalOutputQueue: BufferDefs.Queue = NEW[BufferDefs.QueueObject]; pupRouter, oisRouter: PUBLIC DriverDefs.Router; dummyRouter: DriverDefs.Router; dummyRouterObject: DriverDefs.RouterObject _ [input: DummyInputer, broadcast: DummyBroadcaster, addNetwork: DummyAddDelete, removeNetwork: DummyAddDelete, stateChanged: DummyStateChanged]; <> bufferSpy: SpecialCommunication.SpyProc _ NIL; <> SetSpyProc: PUBLIC PROCEDURE [spy: SpecialCommunication.SpyProc] = BEGIN bufferSpy _ spy; END; DummyInputer: PROCEDURE [b: BufferDefs.Buffer] = BEGIN IF CommFlags.doStats THEN StatsDefs.StatIncr[statPacketsDiscarded]; b.requeueProcedure[b]; END; DummyBroadcaster: PROCEDURE [b: BufferDefs.Buffer] = BEGIN b.requeueProcedure[b]; END; DummyAddDelete: PROCEDURE [Network] = BEGIN END; DummyStateChanged: PROCEDURE [Network] = BEGIN END; SetPupRouter: PUBLIC PROCEDURE [router: DriverDefs.Router] = BEGIN IF router = NIL THEN router _ @dummyRouterObject; pupRouter _ router; END; SetOisRouter: PUBLIC PROCEDURE [router: DriverDefs.Router] = BEGIN IF router = NIL THEN router _ @dummyRouterObject; oisRouter _ router; END; GetPupRouter: PUBLIC PROCEDURE RETURNS [DriverDefs.Router] = BEGIN RETURN[pupRouter]; END; GetOisRouter: PUBLIC PROCEDURE RETURNS [DriverDefs.Router] = BEGIN RETURN[oisRouter]; END; DispatcherOn: PUBLIC PROCEDURE = BEGIN bufferSpy _ NIL; dispatcherPleaseDie _ FALSE; BufferDefs.QueueInitialize[globalInputQueue]; BufferDefs.QueueInitialize[globalOutputQueue]; mainFork _ FORK MainDispatcher[]; END; DispatcherOff: PUBLIC PROCEDURE = BEGIN DispatcherOffLocked[]; JOIN mainFork; BufferDefs.QueueCleanup[globalInputQueue]; BufferDefs.QueueCleanup[globalOutputQueue]; END; DispatcherOffLocked: ENTRY PROCEDURE = INLINE BEGIN dispatcherPleaseDie _ TRUE; NOTIFY dispatcherReady; END; <> MainDispatcher: PUBLIC PROCEDURE = BEGIN b: BufferDefs.Buffer; network: Network; UNTIL dispatcherPleaseDie DO WHILE BufferDefs.QueueLength[globalOutputQueue] # 0 DO <> b _ GrabOutputBuffer[]; IF b.allNets THEN SendToNextNetwork[b] ELSE b.requeueProcedure[b]; ENDLOOP; IF BufferDefs.QueueLength[globalInputQueue] # 0 THEN BEGIN b _ GrabInputBuffer[]; IF (bufferSpy = NIL) OR bufferSpy[b] THEN BEGIN network _ b.network; <> SELECT network.decapsulateBuffer[b] FROM pup => BEGIN b.type _ pup; pupRouter.input[b]; END; ois => BEGIN b.type _ ois; oisRouter.input[b]; END; rejected => dummyRouter.input[b]; processed => NULL; ENDCASE => ERROR; -- UnknownDecapsulation END; -- end of process input buffer clause LOOP; END; -- end of input queue not empty clause Wait[]; ENDLOOP; END; GrabOutputBuffer: ENTRY PROCEDURE RETURNS [BufferDefs.Buffer] = INLINE BEGIN RETURN[BufferDefs.Dequeue[globalOutputQueue]]; END; GrabInputBuffer: ENTRY PROCEDURE RETURNS [BufferDefs.Buffer] = INLINE BEGIN RETURN[BufferDefs.Dequeue[globalInputQueue]]; END; Wait: ENTRY PROCEDURE = INLINE BEGIN IF BufferDefs.QueueLength[globalInputQueue] = 0 AND BufferDefs.QueueLength[ globalOutputQueue] = 0 THEN WAIT dispatcherReady; END; SendToNextNetwork: PROCEDURE [b: BufferDefs.Buffer] = BEGIN network: Network _ b.network; b.network _ network _ network.next; <> IF network = NIL THEN BEGIN b.allNets _ FALSE; -- this is where it gets turned off b.requeueProcedure[b]; RETURN; END; SELECT b.type FROM pup => BEGIN pupRouter.broadcast[b]; -- this requeues b END; ois => BEGIN oisRouter.broadcast[b]; -- this requeues b END; ENDCASE => ERROR; -- dispatcher only sends out pups or ois's END; <> <> PutOnGlobalInputQueue: PUBLIC ENTRY PROCEDURE [b: BufferDefs.Buffer] = BEGIN BufferDefs.Enqueue[globalInputQueue, b]; NOTIFY dispatcherReady; END; PutOnGlobalDoneQueue: PUBLIC PROCEDURE [b: BufferDefs.Buffer] = BEGIN <> IF ~b.allNets AND b.requeueProcedure = DriverDefs.ReturnFreeBuffer THEN DriverDefs.ReturnFreeBuffer[b] ELSE PutOnGlobalDoneQueueLocked[b]; END; PutOnGlobalDoneQueueLocked: ENTRY PROCEDURE [b: BufferDefs.Buffer] = INLINE BEGIN BufferDefs.Enqueue[globalOutputQueue, b]; NOTIFY dispatcherReady; END; <> pupRouter _ @dummyRouterObject; oisRouter _ @dummyRouterObject; dummyRouter _ @dummyRouterObject; Process.SetTimeout[@dispatcherReady, Process.MsecToTicks[30000]]; IF CommFlags.doDebug THEN BEGIN DriverDefs.GetGiantVector[].globalInputQueue _ globalInputQueue; DriverDefs.GetGiantVector[].globalOutputQueue _ globalOutputQueue; END; END. -- DispatcherImpl module LOG Time: April 21, 1980 2:56 PM By: Dalal Action: created file for Pilot 5.0. Time: April 21, 1980 2:57 PM By: Dalal Action: merged the dispatchers. Time: May 7, 1980 10:34 AM By: BLyon Action: Made pupRouter & oisRouter PUBLIC (they are used by Boss). Time: May 8, 1980 1:24 PM By: BLyon Action: Made PutOnGlobalDoneQueue more efficient (hopefully it still works).