CS452 - Real-Time Programming - Spring 2009
Lecture 26 - 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
- Concrete example:
- Join the tracks together with one set of tasks managing one track,
another set managing another
- i.e. Two track reservation servers
- What happens when a train moves from one track to the other?
- This is a real-life, many dollar problem in the mobile phone
industry.
Kernel(s) cannot easily detect livelock
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 Tid 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 Tid 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.
- Changes in train speeds change execution drastically.
Define `drastically'.
Solutions
- A protocol for using the name server
- e.g. RegisterAs returns the Tid 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
The hardest problem to solve
- You just don't know what is possible
- Ask a question like:
- Is my kernel code at the limit of what is possible in terms of
performance?
Priority
The hardest thing to get right
- Sizing stacks used to be harder, but now we have lots of memory
- NP-hard for the human brain
- Practical method starts with all priorities the same, then adjusts
- symptoms of good priority assignment
- The higher priority, the more likely the ready queue is to be
empty
- The shorter the run time in practice the higher the priority
Problems with priority
- Priority inversion
- One resource, many clients
- Tasks try to do too much
Congestion
- Too many tasks
- blocked tasks don't count,
- lowest priority tasks almost don't count
Layered abstraction are costly
e.g. Notifier -> SerialServer -> InputAccumulater -> Parser ->
TrackServer
Hardware
- Turn on optimization, but be careful
- There are places where you have done register allocation by
hand
- Turn on caches
- Size & align calibration tables by size & alignment of cache
lines
- Slowing and stopping
- each train has a built in velocity profile when stopping
- you can create your own velocity profile
Return to: