CS452 - Real-Time Programming - Spring 2010
Public Interest Announcements
- Partners
Lecture 8 - Scheduling, Create( )
Scheduling
When to schedule
Whenever we leave the kernel. When do we enter the kernel?
- Tasks run to completion
- Event-driven pre-emption
- internal events, like Pass( ), or Send( ), which occur when a task
gets to a particular point in its code
- external events
- Time-slicing
- re-schedule only when the slice-timer times out
- on internal events
- two problems
- slices are too big => bad response
- slices are too small => kernel runs too much = bad
response
Who to Schedule
- active task decides = co-processes
- round robin
- everybody gets the same chance
- but usually long running time = unimportant
- priorities
- fixed at compile time
- fixed when task is created
- re-fixed every time task is scheduled
- Do you have a good algorithm
- hybrid
- round robin queues for each priority
- determined by type of kernel entry
- Send wakes Receiver
- interrupt wakes interrupt destination
What God has Decided
Hybrid
What you decide
- How many priorities
- Which task should have which priority
How to implement the queues
- one queue per priority
- fast insertion, but needs back pointer
- slow activation, but use a highest priority pointer
one sorted queue
- slow insertion, but can be speeded up
- fast activation
Tid Create( int priority, void (*func) ( ) )
You also need a Tid Create( int priority, void (*code) ( ) )
function to call from user tasks.
Although it's no more than a wrapper there are a few problems to solve.
- Passing arguments
- On entry the arguments are somewhere, usually r0 & r1
- You have to put them where the kernel can find them.
- gcc's function extry code immediately puts them on the stack.
- In assembly you can find them using the frame pointer.
- Jumping into the kernel
- Getting the return value from the kernel and returning it.
- You find it where the kernel put it
- gcc's function exit code expects it to be indexed off the frame
pointer
- from where it does into r0
Other Primitives
These primitives exist mostly so that we can ensure that task creation and
scheduling are working when there is not much else implemented.
Tid MyTid( )
Self-explanatory
- Doesn't block, but does reschedule.
A question, to which there is a correct answer, or more specifically, a
correct (answer, reason) pair.
- Should the Tid be stored in user space?
Tid MyParentTid( )
Self-explanatory
- Doesn't block, but does reschedule.
Where is the parent Tid, and how does the kernel find it?
void Pass( )
Doesn't block: task calling Pass( ) remains ready to
execute.
Does reschedule.
When is Pass( ) a NOP?
void Exit( )
Calling task is removed from all queues, but its resources are not
reclaimed or reused.
That is, the task goes into a zombie state, in which it cannot be active
or ready, but continues to own all its resources.
How Should Execution Terminate?
Return to: