CS452 - Real-Time Programming - Winter 2015

Lecture 8 - Create

Public Service Annoucements

  1. Due date for kernel 1: 27 January, 2013
  2. Partners, groups.

Creating a Task

In creating a task you have to do two things

  1. Get and initialize resources needed by the task
  2. Make the task look as if it had just entered the kernel

Things you need to do

The code is given as an argument. Create's request includes a function pointer that points to the first instruction of the task: it goes into the link register.

Get an unused TD and memory for its stack

Mostly filling in fields in the TD. The items discussed below might be in the TD, and they might be somewhere else: where you put them is your decision.

  1. task id
  2. stack pointer
  3. SPSR: how should this be initialized?
  4. link register
  5. parent tid
  6. return value
  7. state, which is READY
  8. install in its ready queue
    	td->rdy-next = NULL;
    	pq[priority]->tail->next = td;
    	pq[priority]->tail  = td;
          

Must also initialize the stack


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.

Initializing the Kernel

Set up the Hardware

  1. busy-wait io
  2. low memory
  3. Turn off interrupts in the ICU

Prepare the Kernel Data Structures

Where is the kernel's stack pointer, right now? What does the stack look like?

The kernel data structures

  1. an array of empty ready queues
  2. a poimter to the TD of the active task
  3. an array of TDs
  4. a free list of pointers to free TDs

Prepare the Memory to be Used by Tasks

  1. Think about
  2. Could do some memory initialization at this point.

Create the First User Task

Can run with hardware interrupts turned off for now. But when hardware interrupts are turned on in kernel 3 interrupts in user tasks must be turned on, though they stay off in the kernel.

Reminder. The place where the kernel starts executing has the global name main, which cannot be re-used. The linker usually places main at the beginning of the load image.


Other Primitives

These primitives exist mostly so that we, which includes you, can ensure that task creation and scheduling are working when there is not much else implemented.

Tid MyTid( )

Doesn't block: task calling MyTid( ) makes a state transition from ACTIVE to READY.

A question, to which there is a correct answer, or more specifically, a correct (answer, reason) pair.

Tid MyParentTid( )

Doesn't block: task calling MyParentTid( ) makes a state transition from ACTIVE to READY.

Where is the parent Tid, and how does the kernel find it?

void Pass( )

Doesn't block: task calling Pass( ) makes a state transition from ACTIVE to READY.

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.


Return to: