Task Structure
// Initialize Hardware Receive( serverPid );// Find server Pid // could be parentPid Reply( ); // Should be last thing FOREVER
FOREVER { AwaitEvent( eventid ); //Should event ids be hard coded? // Acquire volatile data // Enable interrupts Send( serverPid, .... ) }
notifierPid = Create( notifier ); //Should notifier code name be hard coded? Send( notifierPid, { MyPid( ), eventId }, ... ); //On return notifier is okay RegisterAs( ); //On return requests can begin.
FOREVER { requesterPid = Receive( request ); switch ( request.type ) { case NOTIFIER: provideNotifierService( ); // may release queued clients doQueuedReplies( ); Reply( requester ); case CLIENT: if ( provideClientService( ) ) Reply( requesterPid ); else enQueue( requesterPid ); } }
Remember that all the calls provide error returns. You can/should use them for error recovery
Simplest is best
// Initialize Hardware Receive( requester, eventId ); Reply( requester ); // Should be the last thing before FOREVER
FOREVER { AwaitEvent( eventid ); //Should event ids be hard coded? // Acquire volatile data // Enable interrupts Receive( .... ) }
Receive( requester, { notifierId, serverId } ); // Now knows the the server/notifier Pids Reply( requester ); // Should be the last thing before FOREVER
FOREVER { Send( notifierPid ... ); Send( serverPid ... ); }
notifierPid = Create( notifier ); //Should notifier code name be hard coded? courierPid = Create( courier ); Send( courierPid, { notifierPid, MyPid( ) } ... ) // On return courier is okay Send( notifierPid, eventId, ... ); //On return notifier is okay RegisterAs( ); //On return requests can begin.
FOREVER { requesterPid = Receive( request ); switch ( request.type ) { case COURIER: provideCourierService( ); // may release queued clients doReplies( ); case CLIENT: if ( provideClientService( ) ) Reply( requesterPid ); else enQueue( requesterPid ); } }
This gets you through a bottleneck where no more than two events come too fast.
Remember that all the calls provide error returns. You can/should use them for error recovery
Add buffer before courier and server.
// Initialize Hardware Receive( bufferPid )// Find server Pid Reply( ) // Should be the last thing before FOREVER
FOREVER { AwaitEvent( eventid ); //Should event ids be hard coded? // Acquire volatile data // Enable interrupts Send( bufferPid, .... ) }
FOREVER { Receive( requesterPid, request ); switch ( request.type ) { case COURIER: enQueue( queue, request.data ); Reply( ); case SERVER: Reply( queue ); } }
Receive( requester, ..., bufferPid, ); // Now knows the the server/buffer Pids Reply( requester, ... ); // Should be the last thing before FOREVER
FOREVER { Send( bufferPid ... ); Send( serverPid ... ); }
notifierPid = Create( notifier ); //Should notifier code name be hard coded? courierPid = Create( courier ); bufferPid = Create( buffer ); Send( courierPid, { myPid, bufferPid } ... ); // On return courier is okay Send( notifierPid, { bufferPid }, ... ); //On return notifier is okay RegisterAs( ); //On return requests can begin.
FOREVER { requesterPid = Receive( request ); switch ( request.type ) { case COURIER: provideCourierService( ); // may release queued clients Reply( requesterPid ); doReplies( ); case CLIENT: if ( provideClientService( ) ) Reply( requesterPid ); else enQueue( requesterPid ); } }
This structure clears up problems when the notifier runs too fast for the server.
Two issues:
Define `bottleneck'.
Called a guard.
What this amounts to is
Return to: