CS452 - Real-Time Programming - Fall 2008
Lecture 20 - The Detective
Questions & Comment
- projects
- next Monday
Server Structure
The Detective
Simple Events
The notifier is a task that waits on events.
- AwaitEvent is like Send
It has two features
- a simple, kernel-defined event that it waits on
- hardware/kernel is like Receive/Reply
- can only serve one master
- The notifier needs to pass on that the event has happened
You could call a notifier a detective,
- who looks around on your behalf,
- and let's you know when something you care about happens,
- but really it is a detective's worker.
Complex Events
In an application there is likely to be lots of waiting on combinations of
events.
- form the combinations using Boolean operators
We use the detective to discover that a complex event has occurred.
- How does the detective work?
Conjunction
Code could be
FOREVER {
Send( part1 );
Send( part2 );
...
Send( master );
}
Disjunction
Code above doesn't work! Try instead
// InitializeDB;
// Create workers and synchronize;
// Synchronize with client;
FOREVER {
Receive( *requester, request );
if ( request.type == CLIENT ) {
parsedRequest = parse( request );
if ( happened( parsedRequest, DB ) ) Reply( requester );
else enqueue( parsedRequest );
}
else if (request.type == WORKER ) {
updateDB ( request );
Reply( requester );
foreach ( queuedRequest )
if ( happened( parsedRequest, DB ) ) {
dequeue( parsedRequest );
Reply( client );
}
}
}
This is the code of a detective.
Not
We can say that an event has not happened yet.
Only at the end of the universe can we say that an event simply has not
happened.
Time-outs are needed for NOT
- OR with Delay on the clock server.
Who is the client of the detective
- Initiator of a normal action
- Housekeeper of the system who will clean up pathologies
(Idletask?))
Pathologies
1. Deadlock
One or more tasks will never run again. For example
- Task sends to itself (local: rest of system keeps running, task itself
will never run)
- Every task does Receive( ) (global: nothing is running)
- Cycle of tasks sending around the cycle (local: other tasks keep
running)
Kernel can detect such things
Possible send-blocking can be detected at compile time
- cycle in the send graph of all sends that could happen
- doesn't necessarily occur at run-time
- that is, it's a necessary but not sufficient condition
Solutions
2. Livelock (Deadly Embrace)
Usually occurs in the context of resource contention. For example
- client1 needs resource1 & resource2; obtains resource1 from
propietor1; asks propietor2 for resource2
- client2 needs resource1 & resource2; obtains resource2 from
propietor2; asks propietor1 for resource1
- state:
- client1, client2: SEND-BLOCKED - can't release resources
- resource1, resource2: RECEIVE-BLOCKED - waiting for release
- propietor1 & propietor2 fail the requests
Kernel cannot easily detect this
Possible solutions
- both resources in one proprietor
- global order on resource requests
- ethernet algorithm
Could consider this a form of critical race.
3. Critical Races
Theory of relativity and the event horizon
One task tests a condition
- takes an action based on that condition
- which will remedy it
Another task tests the same condition
- takes an action to remedy the condition
And the two actions are incompatible.
That is, information about the action of the first task did not spread
instantaneously:
- that race between the information and the second task's test was won by
the test.
Concrete example.
Engineer sends to switchDetective
- gets back, 'No such task.'
- Creates a switchDetective
- starts interacting with switchDetective using the Pid returned by
Create
Before switchDetective does RegisterAs, a second Engineer sends to
switchDetective
- gets back, 'No such task.'
- Creates a switchDetective
- starts interacting with switchDetective using the Pid returned by
Create
Each switchDetective, or its courier, does Put and Get to find out about
switches.
This is only a little bad, you probably won't even notice it, except your
performance will be bad.
But it can be much worse
- consider having two copies of a task that does track reservations.
Symptoms
- Small changes in priorities change execution unpredictably, and
drastically.
- Debugging output changes execution drastically.
Solutions
- A protocol for using the name server
- e.g. RegisterAs returns the Pid of an existing task
- if it's the one that is known to be bad, then do
ForceRegisterAs
- otherwise use the existing one.
- At initialization it's a programming bug,
- which can be discovered by gating
4. Performance
Return to: