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: