CS452 - Real-Time Programming - Fall 2011

Lecture 7 - Create

Pubilc Service Annoucements


Kernel Structure

main( ) {
    Initalize_kernel( );
    Create_First_User_Task( );
    FOREVER {
        active = Schedule( );
        request = Activate( active );
        Handle( request );
    }

Comments


Scheduling

There are two important issues for scheduling

  1. When do we reschedule?
  2. Who do we activate when we schedule

When to schedule

Every time we are in the kernel, so the issue is `When do we enter the kernel?'

Three possibilities

  1. Tasks run to completion, which means until they make a request for kernel services
  2. Event-driven pre-emption, which means when hardware makes a request for service
  3. Time-slicing

We do 1 & 2, but not 3, because our tasks co-operate. Time-slicing is needed when tasks are adversarial.

Who to Schedule

Whoever is needed to meet all the deadlines

Because this is not an easy problem, we don't want to solve it within the kernel. What the kernel does should be fast (=constant time) and not resource constrained.

Inexpensive (=constant time)ways to schedule

Least expensive first

  1. active task decides = co-routines
  2. round robin
  3. priorities
    1. fixed at compile time
    2. fixed when task is created
    3. re-fixed every time task is scheduled
      • Do you have a good algorithm?

The number of priorities should be small, but not too small.

Tasks at the same priority should have the same precedence.

Scheduling algorithm

  1. Find the highest priority non-empty ready queue.
  2. Schedule the first task in the queue.

    The state of the most recently scheduled (running) task is ACTIVE, not READY.

    The kernel maintains a pointer to the TD of the active task so it knows which task is making the current request.

  3. When a task is made ready it is put at the end of its ready queue.

Implementation

Array of ready queues, one for each priority.

Each ready queue is a list with a fornt pointer (for extraction)and a back pointer (for insertion).

Hint. The Art of Computer Programming (Donald Knuth) says that circular queues are better. Why?

Implementation decisions

  1. How many priorities
  2. Which task should have which priority

What to do when there is no ready task


Kernel Work for Create

Allocate Resources

Task ID

  1. 32-bit word to match architecture
  2. Possibly broken into TD index and generation.

Task Descriptor

  1. During initialization create an array of task descriptors
  2. Without task destruction

    With task destruction

Notice that because all task descriptors are the same same size allocation and re-allocation are constant time.

Memory

  1. During initialization break the spare memory into equal sized chunks
  2. Without task destruction

    With task destruction

You could create a more intimate relationship between TD and memory.

Initialize Memory

The principle is, `Make the memory (the stack) exactly ready to be processed by your kernel exit code.'

In practice,

  1. After running the kernel entry code the stack is exactly ready for the kernel exit code to be run.
  2. Make the stack look as though the kernel entry code has just been run.
  3. After runing the kernel exit code you must have

Fill in the Task Descriptor

For some state there is a choice between stack and task descriptor. The minimum is

  1. run state: READY to start with
  2. priority
  3. parent Tid
  4. SP
  5. Pointers for queues.

There could be more

Enter the Task into its Ready Queue

To do this we need to know how scheduling works.


The Create Function

You also need a int 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.

  1. Passing arguments
  2. Jumping into the kernel
  3. Getting the return value from the kernel and returning it.

What follows just seems to say the same thing again. But we might as well leave it here because some student might find it useful.

How do we implement the API for user code?

  1. This requires a bit of assembly language.
  2. In assembly language all arguments & return values are words.
  3. What happens when Create is called?

What happens when Create returns?

When the caller is next activated,

user code has to get it and put it in the compiler's special place, r0 for gcc.


Return to: