83
http://shark.sssup.it - pyright © Paolo Gai 2005 - [email protected] ReTiS Lab Scuola Superiore S. Anna Pisa

- 1Copyright © Paolo Gai 2005 - [email protected] ReTiS Lab Scuola Superiore S. Anna Pisa

  • View
    216

  • Download
    0

Embed Size (px)

Citation preview

Page 1: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 1Copyright © Paolo Gai 2005 - [email protected]

ReTiS LabScuola Superiore S. Anna

Pisa

Page 2: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 2Copyright © Paolo Gai 2005 - [email protected]

kernel details

Paolo GaiEvidence Srl / ReTiS Lab

(SSSUP)

Page 3: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 3Copyright © Paolo Gai 2003 - [email protected]

summary

introduction to scheduling modules introduction to resource modules general purpose vs. compiling kernel kernel internal functions design of a scheduling module an example: the EDF module

Page 4: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 4Copyright © Paolo Gai 2005 - [email protected]

part I

introduction toscheduling modules

Page 5: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 5Copyright © Paolo Gai 2003 - [email protected]

objectives

handle a Scheduling Algorithm in a way independent to the other modules in the system

handle scheduling algorithms that depends on other scheduling algorithms (typically they depends on the queuing policy). For example, an Aperiodic Server using the services offered by another module (also called Master Module)

Aperiodic Server

Master Module

Page 6: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 6Copyright © Paolo Gai 2003 - [email protected]

Public Functions called by the Generic Kernel to implement the

primitives called by the application e.g. creation, dispatch,

end, …Application

module interface (1)

Generic Kernel

GenericPrimitives

ModulePublic f.

Page 7: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 7Copyright © Paolo Gai 2003 - [email protected]

Module Public f.Private f.

Private Functions called to implement the internal behavior of a

scheduling algorithm or…

Application

module interface (2)

Generic Kernel

GenericPrimitives

Page 8: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 8Copyright © Paolo Gai 2003 - [email protected]

Private Functions called by an Aperiodic Server for a task inserted into

the Master Module dispatch, epilogue, insert, extract

Application

module interface (3)

GenericKernel

GenericPrimitives

Master Module Public f.Private f.

AperiodicServer Public f.

Private f.

Page 9: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 9Copyright © Paolo Gai 2003 - [email protected]

module interface (4)

each task is assigned to a module whose number is written into proc_table[p].task_level

the task_level is used when calling the Public Functions

aperiodic servers use the master module

Page 10: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 10Copyright © Paolo Gai 2003 - [email protected]

example

the system is composed by 2 scheduling modules

m0: Master Module

m1: Aperiodic Server

2 tasks task t0: proc_table[t0].task_level = m0 task t1: proc_table[t1].task_level = m1

Page 11: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 11Copyright © Paolo Gai 2003 - [email protected]

example (2)

the Generic Kernel function schedule() calls level_table[m0].public_scheduler() the level scheduler can schedule the two tasks

to dispatch the task t0level_table[proc_table[t0].task_level].public_dispatch()

to dispatch the task t1level_table[proc_table[t1].task_level].public_dispatch()

that calls level_table[m0].private_dispatch()

Page 12: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 12Copyright © Paolo Gai 2005 - [email protected]

part II

introduction toresource modules

Page 13: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 13Copyright © Paolo Gai 2003 - [email protected]

objectives

the algorithms that implements resource sharing: should be modular can cohesist at the same time

the algorithms should, if possible, be independent from the module that owns the task that use the protocols

Page 14: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 14Copyright © Paolo Gai 2003 - [email protected]

mutex

each resource module exports a common interface

the protocols uses some generic mutex that are preallocated by the system

the link between mutex and protocol is defined at runtime when the mutex is initialized (as in POSIX)

Page 15: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 15Copyright © Paolo Gai 2003 - [email protected]

parameters and models

the protocols require some parameters that have to be given for each mutex that use the protocol for each task that uses a mutex of that type

the parameters are given to the system using models that are passed at mutex initialization at task creation (e.g., the last parameter of the task_create() primitive)

Page 16: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 16Copyright © Paolo Gai 2003 - [email protected]

priority inversion

there exist protocols where the task given by the scheduling mechanism is not the same task that is then dispatched

for example, protocols like that are: priority inheritance priority ceiling

Page 17: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 17Copyright © Paolo Gai 2003 - [email protected]

priority inversion (2)

a medium priority ready task is exchanged with a low priority ready task

exchange(push-throughblocking)

J1

J2

J3

normal executioncritical sectionExample (PI):

Page 18: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 18Copyright © Paolo Gai 2003 - [email protected]

problem

in a system organized in levels that solution can not be implemented because there is not a global concept of priority to be modular the implementation of each level have to

prescind from the implementation of the resource sharing algorithms

Page 19: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 19Copyright © Paolo Gai 2003 - [email protected]

a first solution

implement the scheduling modules and the resource modules in a way that the resource modules know the implementation details of

the scheduling modules the resource modules modifies the internal data

structures of the scheduling modules

advantages optimized implementation

disadvantages the use of these protocols is limited to the data

structures and the modules for that they have been written

Page 20: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 20Copyright © Paolo Gai 2003 - [email protected]

the S.Ha.R.K. solution

the inheritance mechanisms are supported directly by the Generic Kernel in a way independent from the module implementation

Page 21: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 21Copyright © Paolo Gai 2003 - [email protected]

basic idea

tradictional implementations were done inserting tasks out-of-order: the low priority ready task Tb is moved into the high priority position of the blocked task

Ta Tb

Ta blocks accessing the resource

Tb goes into the position of the high priority task

the idea is that...

Ta goes into the Blocked queue

Page 22: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 22Copyright © Paolo Gai 2003 - [email protected]

basic idea (2)

In the S.Ha.R.K. approach it is the high priority blocked task that, staying into the ready queue, indexes another shadow task that have to be executed in substitution at dispatch time

Ta Tb

Ta blocks accessing a resource

Ta index a shadow taskremaining into the ready queue

Tb does not feel anything

Page 23: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 23Copyright © Paolo Gai 2003 - [email protected]

the pointer to the running task (exec)

implementation

exec_shadow task really executed

EXEC

EXEC_SHADOW

EXEC

exec task given by the scheduler

is divided in two:

Page 24: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 24Copyright © Paolo Gai 2003 - [email protected]

implementation (2)

a shadow field is added to the task descriptor

Task i

shadow

the shadow field is the task that have to be executed in substitution

ShadowTask

shadow

Page 25: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 25Copyright © Paolo Gai 2003 - [email protected]

implementation (3)

at the start, proc_table[p].shadow = p (no substitution)

Task i

shadow

the shadow field is set when a task blocks

Blocked Task

shadow

Blocking Task

shadow

Page 26: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 26Copyright © Paolo Gai 2003 - [email protected]

implementation (4)

a wait DAG can grow

Blocked Task

shadow

Blocked Task

shadow

Blocked Task

shadow

Blocking Task

shadow

Page 27: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 27Copyright © Paolo Gai 2003 - [email protected]

implementation (5)

the schedulers of each modules index a task to be executed (prescinding from the shadows)

the function schedule store that task into the exec variable

the dispatch function follows the shadow chain until shadow = PID

exec_shadow is set to the last task of the shadow chain

Page 28: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 28Copyright © Paolo Gai 2003 - [email protected]

implementation (6)

EXEC

EXEC_SHADOW

Blocked Task

shadow

Blocked Task

shadow

Blocked Task

shadow

Blocking Task

shadow

Page 29: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 29Copyright © Paolo Gai 2003 - [email protected]

deadlock

using the shadow field, deadlocks can be easily detected

to detect if a deadloc occurred, the system should check if a cycle is inserted into the graph when a shadow field is modified

Page 30: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 30Copyright © Paolo Gai 2003 - [email protected]

overhead

the dispatch overhead is quite low (a list with integer indexes have to be examined, and usually that list is formed by 1-2 elements)

the blocking overhead can be high since to block a task more than one shadow field have to be modified (it depends from the protocol used)

Page 31: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 31Copyright © Paolo Gai 2005 - [email protected]

part III

two ways of implementing kernel primitives

Page 32: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 32Copyright © Paolo Gai 2003 - [email protected]

software interrupts

general purpose kernels usually provides memory protection separation between user and kernel space

primitives usually implemented using software interrupts needed to run untrusted applications

RT applications are typically trusted, and does not need memory protection

Page 33: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 33Copyright © Paolo Gai 2003 - [email protected]

interrupt disabling

for that reason, often RT kernels are compiling kernels: primitives are functions that works with interrupts

disabled eventually they can change context

memory is shared among all the threads and the kernel internal kernel data structures can be visible

S.Ha.R.K. uses this technique

Page 34: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 34Copyright © Paolo Gai 2003 - [email protected]

a (blocking) primitive

a typical structure is like that:

void a_blocking_primitive(...) {

disable_interrupts();

capacity_control();

record_JET_data();

Module_internal_Task_Call(...);

tracer_hook(...);

scheduler();

change_context(exec_shadow);

enable_interrupts();

}

is a typical C function!

the module implementsits behavior here, AFTERthe kernel accounted for

its computation time. example of functions are:

public_message,public_block

a tracer can be attachedto every primitive. some functions

are used to record task events

simply a CLI without changing stack!

account the time spent since the last ctx switch

now

now all is ready to choose the next task to be executed.note that this function will call other 2 module functions:

public_scheduler(): to choose the next taskpublic_dispatch(): to tell the module that

the task is really executed

Page 35: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 35Copyright © Paolo Gai 2005 - [email protected]

part IV

kernel functionsinterface

Page 36: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 36Copyright © Paolo Gai 2003 - [email protected]

kernel types

PID task index IQUEUE queue type TASK = (void *) LEVEL index for scheduling

modules bandwidth_t free system

bandwidth

Page 37: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 37Copyright © Paolo Gai 2003 - [email protected]

task descriptor

typedef struct { DWORD task_ID; progressive (unique) task number LEVEL task_level; task’s module level

CONTEXT context; CPU Register pointer BYTE *stack; task stack pointer TASK (*body)(); task body function char name[MAX_TASKNAME]; task name (e.g. “Goofy”) WORD status; task status (EXE,ready,…) WORD pclass; model type (SOFT/HARD/…) WORD group; task group (an int number) WORD stacksize; task stack size DWORD control; status flags (see kernel/model.h)

Page 38: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 38Copyright © Paolo Gai 2003 - [email protected]

task descriptor (2)

int frozen_activations; number of frozen activations

int sigmask; signals informations int sigpending;

int sigwaiting;

int avail_time; task available time (us) PID shadow; the shadow field struct _task_handler_rec *cleanup_stack;

cleanup handler pointerint errnumber; task’s errno() value

PID waiting_for_me; used in task_join() void *return_value; used in task_join()

Page 39: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 39Copyright © Paolo Gai 2003 - [email protected]

task descriptor (3)

TIME jet_table[JET_TABLE_DIM];

int jet_tvalid;

int jet_curr; JET informations TIME jet_max;

TIME jet_sum;

TIME jet_n; task specific data void *keys[PTHREAD_KEYS_MAX]; used with condition variables struct condition_struct *cond_waiting;

int delay_timer; a per-task timer int wcet;

} proc_des; task WCET

Page 40: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 40Copyright © Paolo Gai 2003 - [email protected]

scheduling level descriptor

typedef struct {

void (*private_insert )(LEVEL l, PID p, TASK_MODEL *m);

[…]

PID (*public_scheduler)(LEVEL l);

int (*public_guarantee)(LEVEL l, bandwidth_t *freebandwidth);

int (*public_create )(LEVEL l, PID p, TASK_MODEL *m);

void (*public_end )(LEVEL l, PID p);

[…]

} level_des;

Page 41: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 41Copyright © Paolo Gai 2003 - [email protected]

global variables

include/kernel/var.h proc_des proc_table[] task descriptor table level_des *level_table[] sched modules descr. table resource_des *resource_table[] res. modules descriptor table

PID exec task selected for scheduling PID exec_shadow RUNNING TASK

int cap_timer event n. for capacity control struct timespec schedule_time last time schedule() was

called struct timespec cap_lasttime previous value for

schedule_time

Page 42: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 42Copyright © Paolo Gai 2003 - [email protected]

global variables (2)

int task_counter number of user tasks int system_counter number of system tasks

int calling_runlevel_func set when shutdown is in progress

IQUEUE freedesc free descriptor queue

Page 43: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 43Copyright © Paolo Gai 2003 - [email protected]

event handling

events are generated by the system timer and by external interrupts

timer events int kern_event_post(const struct timespec *time,

void (*handler)(void *p), void *par); int kern_event_delete(int index); -1 is the invalid Event index

to reschedule the system inside an event handler(e.g., a task has been activated using an event) void event_need_reschedule(void);

Page 44: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 44Copyright © Paolo Gai 2003 - [email protected]

exceptions

to raise an exception void kern_raise(int n, PID p);

the exceptions are mapped in the real-time signal SIGHEXC

the signals are handled with interrupts enabled, into the context of a task that have the signal unmasked

Page 45: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 45Copyright © Paolo Gai 2003 - [email protected]

kernel memory management

generic memory void *kern_alloc(DWORD s); void kern_free(void *block, size_t size);

memory under 1Mb void *DOS_alloc(DWORD size); void DOS_free(void *ptr,DWORD size);

other functions exists the tasks should use malloc() and free()

these functions do not disable interrupts!

Page 46: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 46Copyright © Paolo Gai 2003 - [email protected]

kernel queues

(these functions have to be called with interrupt disabled) void iq_init(IQUEUE *q, IQUEUE *share, int flags); Typical usage: iq_init(&myqueue,NULL, 0);

setting task priorities before insertion struct timespec *iq_query_timespec(PID p,IQUEUE*q); DWORD *iq_query_priority (PID p, IQUEUE *q);

IQUEUE insertion void iq_priority_insert (PID p, IQUEUE *q); void iq_timespec_insert (PID p, IQUEUE *q); void iq_insertfirst (PID p, IQUEUE *q); void iq_insertlast (PID p, IQUEUE *q);

Page 47: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 47Copyright © Paolo Gai 2003 - [email protected]

kernel queues (2)

IQUEUE extraction void iq_extract (PID p, IQUEUE *q); PID iq_getfirst ( IQUEUE *q); PID iq_getlast ( IQUEUE *q);

first/last task into the queue PID iq_query_first(IQUEUE *q); PID iq_query_last(IQUEUE *q);

iterators and miscellaneous PID iq_query_next (PID p, IQUEUE *q); PID iq_query_prev (PID p, IQUEUE *q); int iq_isempty (IQUEUE *q);

Page 48: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 48Copyright © Paolo Gai 2003 - [email protected]

acceptance test

an on-line acceptance test is performed at creation time locally into public_create()

e.g., task set of the module has Utot >1

globally into guarantee()that calls public_guarantee()checks if the whole system is schedulableit uses the bandwidth_t type

• integer type (no floats inside the kernel!)• valid ranges into [0…MAX_BANDWIDTH]• 0 means 0.0; MAX_BANDWIDTH means 1.0

Page 49: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 49Copyright © Paolo Gai 2003 - [email protected]

acceptance test (2)

int guarantee() {

bandwidth_t num=MAX_BANDWIDTH;

int l;

for (l =0; l<MAX_SCHED_LEVEL &&

level_table[l]->public_guarantee; l++)

if (!level_table[l]->public_guarantee(l,&num))

return -1;

return 0; /* OK */

}

Num is decremented

The function stops when

level_guarantee is not specified!

That means 100% free bandwidth

Page 50: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 50Copyright © Paolo Gai 2005 - [email protected]

part V

tips & tricks

Page 51: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 51Copyright © Paolo Gai 2003 - [email protected]

let’s start!

the simplest way to create a new module is: look for a similar module that already exists

(look in the modules directory) copy it in your local directory (2 files .c + .h)

change the prefix of every symbol with a new one for example from EDF_public_create to

MYMODULE_public_create

add a new task model (if needed) into the .hadd your private data structures

example: deadlines, periods, …

finally, modify the source code

Page 52: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 52Copyright © Paolo Gai 2003 - [email protected]

OSLib events: periodic tasks

one OSLib event for each periodic task the event index should be kept in a private data

structure

post the event into public_activate when the event fires:

reactivates the task posts again an event for the next activation

delete the reactivation event when the task dies

Page 53: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 53Copyright © Paolo Gai 2003 - [email protected]

OSLib events: tick scheduler

one OSLib event for the whole module it can be used to divide the time in slots

in the module registration function, post a RUNLEVEL_INIT initialization function

the function should post an OSLib event when the event fires

increments the tick number re-post the event for the next tick

Page 54: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 54Copyright © Paolo Gai 2003 - [email protected]

OSLib events: temporal isolation

use task descriptor’s wcet and avail_time set the flag CONTROL_CAP into the control field of

the task descriptor put the available time into avail_time public_epilogue is called when the capacity is

exhausted time can reach negative values check if avail_time < 0

Page 55: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 55Copyright © Paolo Gai 2005 - [email protected]

part VI

design of a scheduling module

Page 56: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 56Copyright © Paolo Gai 2003 - [email protected]

strategy

first, a scheduling strategy is needed the strategy defines the behavior related to a set of

events synchronous events

the user called a system primitive asynchronous events

an external event arrived: an external interrupt, or an OSLib eventa (a deadlines, a capacity exhaustion,...)

FAST implementation needed(10-30 us for each event)

Page 57: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 57Copyright © Paolo Gai 2003 - [email protected]

task lifecycle

a task is a C function that is created is activated executes one or more instances

a task can block on a synchronization primitive a task can end an instance a task can be preempted by another task

finishes at the last }

Cr Act Sc+Disp Pre Sc+Disp Blk Sc+Disp Ecy Sc+Disp EndActUnBlk

Page 58: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 58Copyright © Paolo Gai 2003 - [email protected]

synchronous events

synchronous events describe the behavior of a task when it calls a primitive

task creationint (*public_create )(LEVEL l, PID p, TASK_MODEL *m);

task activationvoid (*public_activate )(LEVEL l, PID p);

blocking/unblocking at a synchronization pointvoid (*public_unblock )(LEVEL l, PID p);

void (*public_block )(LEVEL l, PID p);

endcycle (end of an instance)int (*public_message )(LEVEL l, PID p, void *m);

endvoid (*public_end )(LEVEL l, PID p);

Page 59: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 59Copyright © Paolo Gai 2003 - [email protected]

asynchronous events

a scheduling algorithm can create asynchronous events that interrupts the running task at a specific time:

to activate periodic/aperiodic tasks to control deadlines to monitor task execution time to implement scheduling slots

(e.g., every 1 ms)

Page 60: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 60Copyright © Paolo Gai 2003 - [email protected]

other events

a scheduling module have information about: when a task is dispatched or preempted

void (*public_dispatch )(LEVEL l, PID p, int nostop);

void (*public_epilogue )(LEVEL l, PID p);

when a task has failed its creationvoid (*public_detach )(LEVEL l, PID p);

finally, using all the information collected by the above elements, the scheduling algorithm provides:

a schedulerPID (*public_scheduler)(LEVEL l);

an acceptance testint (*public_guarantee)(LEVEL l, bandwidth_t *freebandwidth);

Page 61: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 61Copyright © Paolo Gai 2003 - [email protected]

an example: SIMPLEEDF

provides: hard periodic and aperiodic scheduling using the

EDF algorithm (Liu and Layland, 1973) on-line guarantee based on the utilization factor support for aperiodic servers deadline miss and wcet violation exceptions

the EDF module currently used has been written by Anton Cervin, University of Lund

Page 62: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 62Copyright © Paolo Gai 2003 - [email protected]

implementation

the level_des descriptor have to be redefined like a C++ class

since C is used, an extension to the descriptor is neededstruct {

level_des lev;

/* my data structures */

} SIMPLEEDF_level_des;

the Generic Kernel is NOT modified EDF_level_des contains all the data structures

private to the EDF module

Page 63: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 63Copyright © Paolo Gai 2003 - [email protected]

implementation (2)

think SIMPLEEDF_level_des as a C++ class the registration function (like a C++ constructor)

simply initialize the module and put a pointer to SIMPLEEDF_level_des into the first free available pointer into the level_table

there is not a standard level destructor if needed, sys_atrunlevel should be used

Page 64: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 64Copyright © Paolo Gai 2003 - [email protected]

SIMPLEEDF task states

Page 65: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 65Copyright © Paolo Gai 2003 - [email protected]

ready queue management

the SIMPLEEDF module use a ready queue to store its tasks

the ready queue is ordered by deadline, stored into the ready queue data structure

the running task (pointed also by the exec_shadow field) is extracted from the ready queue

Page 66: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 66Copyright © Paolo Gai 2003 - [email protected]

the level descriptor

typedef struct {

level_des l;

TIME period[MAX_PROC];

int deadline_timer[MAX_PROC];

int flag[MAX_PROC];

IQUEUE ready;

int flags;

bandwidth_t U;

} SIMPLEEDF_level_des;

Page 67: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 67Copyright © Paolo Gai 2003 - [email protected]

scheduler

static PID SIMPLEEDF_public_scheduler(LEVEL l)

{

SIMPLEEDF_level_des *lev =

(SIMPLEEDF_level_des *)(level_table[l]);

return iq_query_first(&lev->ready); }

}Using the level number lthe module get the correct

pointer to its data structures.lev can be thougth as

the field “this” in C++ classes...

An EDF scheduler returns the first task in the ready queue!

Page 68: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 68Copyright © Paolo Gai 2003 - [email protected]

dispatch

static void SIMPLEEDF_public_dispatch(LEVEL l, PID p,

int nostop)

{

SIMPLEEDF_level_des *lev =

(SIMPLEEDF_level_des *)(level_table[l]);

iq_extract(p, &lev->ready);

}

The running task is extracted from the ready queue

Page 69: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 69Copyright © Paolo Gai 2003 - [email protected]

task creation

static int SIMPLEEDF_public_create(LEVEL l, PID p,TASK_MODEL *m)

{ SIMPLEEDF_level_des *lev =

(EDF_level_des *)(level_table[l]); HARD_TASK_MODEL *h;

if (m->pclass != HARD_PCLASS) return -1; if (m->level != 0 && m->level != l) return -1;

h = (HARD_TASK_MODEL *)m; if (!h->wcet || !h->mit) return -1;

Model Type Identification(A Model can be handled if

it is of the right pclassand it has the right level number)

Cast to the right type(only after checking the real type!)

Check if all the data inthe Model is filled in the right way

Page 70: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 70Copyright © Paolo Gai 2003 - [email protected]

task creation (2)

if (lev->flags & SIMPLEEDF_ENABLE_GUARANTEE) { bandwidth_t b; b = (MAX_BANDWIDTH / h->mit) * h->wcet; if (MAX_BANDWIDTH - lev->U > b) lev->U += b; else return -1; }

lev->period[p] = h->mit; if (h->periodicity == APERIODIC) lev->flag[p] = SIMPLEEDF_FLAG_SPORADIC; else lev->flag[p] = 0;

lev->deadline_timer[p] = -1; Fill Module private data

A check is done to see ifthe tasks allocated to EDF

uses a bandwidth >1

Here we know that the task can be accepted by the EDF

module. We do not know yet if it can be accepted

systemwide. To know that the task creation primitive

will call guarantee()

The guarantee failedbecause the Utot of the EDF tasks >1

Page 71: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 71Copyright © Paolo Gai 2003 - [email protected]

task creation (3)

if (lev->flags & SIMPLEEDF_ENABLE_WCET_CHECK) { proc_table[p].avail_time = h->wcet; proc_table[p].wcet = h->wcet; proc_table[p].control |= CONTROL_CAP; }

return 0;}

Enable the monitoring of the execution timeof the task. The CONTROL_CAP features

are provided by the Generic Kernel. A module canalso implement its own temporal isolation,

as for example the Polling Server (kernel/modules/ps.c)

Page 72: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 72Copyright © Paolo Gai 2003 - [email protected]

guarantee

static int SIMPLEEDF_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)

{

SIMPLEEDF_level_des *lev = (SIMPLEEDF_level_des *)(level_table[l]);

if (*freebandwidth >= lev->U) {

*freebandwidth -= lev->U;

return 1;

}

else

return 0;

}

There is enough bandwidthto schedule all the EDF tasks

There is not enough bandwidth

Page 73: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 73Copyright © Paolo Gai 2003 - [email protected]

task activation

static void SIMPLEEDF_public_activate(LEVEL l, PID p)

{

SIMPLEEDF_level_des *lev =

(SIMPLEEDF_level_des *)(level_table[l]);

struct timespec *temp;

if (proc_table[p].status == SIMPLEEDF_WAIT) {

kern_raise(XACTIVATION,p); return;

}

if (proc_table[p].status != SLEEP &&

proc_table[p].status != SIMPLEEDF_WCET_VIOLATED)

return;

Task activated too early

Task already activated

Page 74: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 74Copyright © Paolo Gai 2003 - [email protected]

task activation (2)

temp = iq_query_timespec(p, &lev->ready);

kern_gettime(temp);

ADDUSEC2TIMESPEC(lev->period[p], temp);

/* Insert task in the correct position */

proc_table[p].status = SIMPLEEDF_READY;

iq_timespec_insert(p,&lev->ready);

/* Set the deadline timer */

lev->deadline_timer[p] = kern_event_post(temp, SIMPLEEDF_timer_deadline, (void

*)p);

}

Compute the deadline

Insert the activated task into the ready queue

Set the Deadline Timer

Page 75: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 75Copyright © Paolo Gai 2003 - [email protected]

deadline event

static void SIMPLEEDF_timer_deadline(void *par)

{

PID p = (PID) par; SIMPLEEDF_level_des *lev;

struct timespec *temp;

lev = (SIMPLEEDF_level_des *) level_table[proc_table[p].task_level];

switch (proc_table[p].status) {

case SIMPLEEDF_ZOMBIE:

proc_table[p].status = FREE;

iq_insertfirst(p,&freedesc);

lev->U -= (MAX_BANDWIDTH/lev->period[p]) * proc_table[p].wcet;

break;

Free the task descriptorif the task ended

correctly

Page 76: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 76Copyright © Paolo Gai 2003 - [email protected]

deadline event (2)

case SIMPLEEDF_IDLE:

temp = iq_query_timespec(p,&lev->ready);

ADDUSEC2TIMESPEC(lev->period[p], temp);

proc_table[p].status = SIMPLEEDF_READY;

iq_timespec_insert(p,&lev->ready);

lev->deadline_timer[p] = kern_event_post(temp, SIMPLEEDF_timer_deadline, (void *)p);

event_need_reschedule();

break;

Automatically activatethe task at the startof the next period

Create again thedeadline timer

Since the ready queue has changed,the scheduler need to be called

to check for preemption

Compute again thenext deadline

Page 77: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 77Copyright © Paolo Gai 2003 - [email protected]

deadline event (3)

case SIMPLEEDF_WAIT:

proc_table[p].status = SLEEP;

break;

default:

kern_raise(XDEADLINE_MISS,p);

}

}

The task was aperiodic

What ?!?

Page 78: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 78Copyright © Paolo Gai 2003 - [email protected]

preemption or wcet exaustion

static void SIMPLEEDF_public_epilogue(LEVEL l, PID p)

{

SIMPLEEDF_level_des *lev =

(SIMPLEEDF_level_des *)(level_table[l]);

if ((lev->flags & SIMPLEEDF_ENABLE_WCET_CHECK) && proc_table[p].avail_time <= 0) {

kern_raise(XWCET_VIOLATION,p);

proc_table[p].status = SIMPLEEDF_WCET_VIOLATED;

}

else {

iq_timespec_insert(p,&lev->ready);

proc_table[p].status = SIMPLEEDF_READY;

}

}

Wcet check

Ok, the task was preempted, the module reisert it into the ready queue

Page 79: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 79Copyright © Paolo Gai 2003 - [email protected]

synchronization points

static void SIMPLEEDF_public_block(LEVEL l, PID p)

{

}

The task has already been extracted from the ready queueby public_dispatch().

NOTE: The blocked queue will be handled by thesynchronization point function (e.g., sem_wait, not by

the scheduling modules!

Page 80: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 80Copyright © Paolo Gai 2003 - [email protected]

synchronization points (2)

static void SIMPLEEDF_public_unblock(LEVEL l, PID p)

{

SIMPLEEDF_level_des *lev = (SIMPLEEDF_level_des *)(level_table[l]);

proc_table[p].status = SIMPLEEDF_READY;

iq_timespec_insert(p,&lev->ready);

}

When the task exit from a synchronization point(e.g., sem_post), the task is put again in the ready state.

Page 81: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 81Copyright © Paolo Gai 2003 - [email protected]

end of the current instance

static int SIMPLEEDF_public_message(LEVEL l, PID p, void *m)

{

SIMPLEEDF_level_des *lev=(SIMPLEEDF_level_des *)(level_table[l]);

if (!lev->flag[p] & SIMPLEEDF_FLAG_SPORADIC)

proc_table[p].status = SIMPLEEDF_IDLE;

else

proc_table[p].status = SIMPLEEDF_WAIT;

if (lev->flags & SIMPLEEDF_ENABLE_WCET_CHECK)

proc_table[p].avail_time = proc_table[p].wcet;

jet_update_endcycle();

return 0;

}

Set the correct state

Recharge the wcet

Update JET informations

Page 82: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 82Copyright © Paolo Gai 2003 - [email protected]

task end

static void SIMPLEEDF_public_end(LEVEL l, PID p)

{

proc_table[p].status = SIMPLEEDF_ZOMBIE;

}

Simply set the state,the deadline event will finish

Page 83: - 1Copyright © Paolo Gai 2005 - pj@evidence.eu.com ReTiS Lab Scuola Superiore S. Anna Pisa

http://shark.sssup.it - 83Copyright © Paolo Gai 2003 - [email protected]

contact info

Paolo Gai

[email protected]

(please use the Shark Forum for SHaRK related questions!)

http://feanor.sssup.it/~pj