Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 1635 → Rev 1634

/advdemos/trunk/slsh/slsh.h
0,0 → 1,204
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
 
/**
------------
CVS : $Id: slsh.h,v 1.1.1.1 2004-05-24 17:54:50 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:50 $
------------
Author: Tomas Lennvall, Date: Feb 2000.
 
This file contains the scheduling module for Slot shifting.
 
Title:
Slot Shifting
 
Task Models Accepted:
STATIC_TASK_MODEL - Periodic Hard tasks that are scheduled by
an off-line scheduler, so that all guarantees regarding precedence, mutex
deadline violation is taken care of. The tasks are in an executione schedule,
that is the order in when they become ready. They have the following fields:
est (earliest start time), wcet and absolute deadline.
HARD_TASK_MODEL - Hard Tasks (Hard aperiodic requests)
wcet field and drel field must be != 0. They are used to set the wcet
and deadline of the tasks.
periodicity field must be APERIODIC
mit field is ignored.
 
SOFT_TASK_MODEL - Soft Tasks (Unspecified tasks)
wcet field must be != 0. periodicity filed must be APERIODIC
period and met filed is ignored.
 
Guest Models Accepted:
NONE - Slot shifting handles all tasks by itself (at this moment).
 
Description:
This module schedules the offline scheduled tasks according to the slot-
shifting paradigm, dividing time into slots of a fixed length and assigning
tasks to execute in those slots. Slot-shifting also keeps track of the free
bandwidth in the schedule by using disjoint intervals and sc (spare capacity).
Each interval has a sc nr that represents the free bandwidth in that interval,
the sc can be used by hard aperiodic tasks, static tasks from later interval or
soft aperiodic tasks. Hard aperiodic tasks are guaranteed an incorporated in
the schedule by reduction of sc before they execute. No guarantee is
performed on the soft aperiodic tasks, they are run when no other task wants
to execute and sc is available.
 
Description:
This module implements the Slot shifting algorithm, by Gerhard Fohler. Slot shifting
schedules off-line scheduled tasks and also handles hard aperiodic requests by the
guarantee alorithm. Slot shifting can also handle soft aperiodic tasks,
called unspecified. That is tasks without a deadline.
 
Exceptions raised:
These exceptions are pclass-dependent...
XDEADLINE_MISS
If a task miss his deadline, the exception is raised.
 
XWCET_VIOLATION
If a task doesn't end the current cycle before if consume the wcet,
an exception is raised, and the task is put in the EDF_WCET_VIOLATED
state. To reactivate it, use EDF_task_activate via task_activate or
manage directly the EDF data structure. Note that the exception is not
handled properly, an XDEADLINE_MISS exeeption will also be raised at
the period end...
 
Restrictions & special features:
- This level doesn't manage the main task.
- At init time we can choose if the level have to activate
. the wcet check
(If a task require more time than declared, it is stopped and put in
the state EDF_WCET_VIOLATED; a XWCET_VIOLATION exception is raised)
. the task guarantee algorithm
(when all task are created the system will check that the task_set
will not use more than the available bandwidth)
- The level use the priority and timespec_priority fields.
- A function to return the used bandwidth of a level is provided.
- The guest tasks don't provide the guest_endcycle function
 
**/
 
/*
* Copyright (C) 2000 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
#ifndef __SLSH_H__
#define __SLSH_H__
 
#include <ll/ll.h>
#include <kernel/config.h>
#include <sys/types.h>
#include <kernel/types.h>
 
#define STATIC_PCLASS 0x0500
 
#define SLSH_LEVELNAME "Slot Shifting"
#define SLSH_LEVEL_CODE 5
#define SLSH_LEVEL_VERSION 1
 
 
 
/* -----------------------------------------------------------------------
STATIC_TASK_MODEL: offline scheduled Tasks
----------------------------------------------------------------------- */
/* Offline-scheduled tasks are hard periodic tasks that have been
scheduled before runtime. All guarantees are made by the off-
line scheduler so the tasks are already guaranteed.
*/
 
typedef struct {
TASK_MODEL t;
TIME est;
TIME wcet;
TIME dabs;
int interval; /* used in slot shifting */
} STATIC_TASK_MODEL;
 
#define static_task_default_model(m) \
task_default_model((m).t,STATIC_PCLASS), \
(m).est = -1, \
(m).dabs = 0, \
(m).wcet = 0, \
(m).interval = -1;
#define static_task_def_level(m,l) task_def_level((m).t,l)
#define static_task_def_arg(m,a) task_def_arg((m).t,a)
#define static_task_def_stack(m,s) task_def_stack((m).t,s)
#define static_task_def_group(m,g) task_def_group((m).t,g)
#define static_task_def_usemath(m) task_def_usemath((m).t)
#define static_task_def_system(m) task_def_system((m).t)
#define static_task_def_nokill(m) task_def_nokill((m).t)
#define static_task_def_ctrl_jet(m) task_def_ctrl_jet((m).t)
#define static_task_def_est(m,p) (m).est = (p)
#define static_task_def_dabs(m,d) (m).dabs = (d)
#define static_task_def_wcet(m,w) (m).wcet = (w)
#define static_task_def_interval(m,i) (m).interval = (i)
#define static_task_def_trace(m) task_def_trace((m).t)
#define static_task_def_notrace(m) task_def_notrace((m).t)
 
 
 
 
/*#define min(a, b) ((a) < (b) ? (a) : (b))*/
 
#define TIME2TIMESPEC(T, TS) \
( \
((TS).tv_sec = ((T)/1000000)), \
((TS).tv_nsec = (((T)%1000000) * 1000)), \
(TS) \
)
 
/* define the interval struct */
typedef struct {
int start; /* start of interval */
int end; /* end of interval */
int length; /* Length of interval */
int maxt; /* maximum execution time in interval */
int sc; /* spare capacity in interval */
} SLSH_interval;
 
/*+ Registration function: */
LEVEL SLSH_register_level();
 
void SLSH_set_interval(LEVEL l, int start, int end, int maxt);
void SLSH_set_variables(LEVEL l, TIME length);
 
#endif
 
/advdemos/trunk/slsh/slsh.c
0,0 → 1,750
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/**
------------
CVS : $Id: slsh.c,v 1.1.1.1 2004-05-24 17:54:50 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:50 $
------------
 
This file contains the scheduling module for Slot-Shifting.
 
Read slsh.h for further details.
 
**/
 
/*
* Copyright (C) 2000 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
#include "slsh.h"
#include <ll/stdio.h>
#include <ll/stdlib.h>
#include <ll/string.h>
#include <ll/math.h> /* for ceil(...) */
#include <ll/ll.h> /* for memcpy(...) */
#include <kernel/model.h>
#include <kernel/descr.h>
#include <kernel/var.h>
#include <kernel/func.h>
 
//#define eslsh_printf kern_printf
#define slsh_printf printk
 
/* Keeps information about static and guaranteed tasks */
typedef struct {
int est;
int dabs;
int interval;
} SLSH_task;
 
/*+ Status used in the level +*/
#define SLSH_READY MODULE_STATUS_BASE
#define SLSH_WAIT MODULE_STATUS_BASE + 1
#define SLSH_IDLE MODULE_STATUS_BASE + 2
#define SLSH_WCET_VIOLATED MODULE_STATUS_BASE + 3
 
/*+ defines +*/
#define MAX_INTERVALS 1000 /* 1000 intervals is max, for now */
 
/******+ the level redefinition for the SLOT SHIFT level +*******/
typedef struct {
level_des l; /*+ the standard level descriptor+*/
 
/* task lists */
SLSH_task tasks[MAX_PROC]; /* est and dl's for static and guaranteed task */
IQUEUE idle_statics; /* finished static tasks */
IQUEUE unspecified; /* tasks with only a wcet */
/* the Intervals list */
SLSH_interval intervals[MAX_INTERVALS];
int current; /* current interval */
int last; /* last interval */
int slot; /* slot shifting time */
TIME slot_length; /* slothlength in real system time*/
int LCM; /* length (in slots) of ofline schedule */
int slot_event; /* save the event */
} SLSH_level_des;
 
 
/* check if some tasks are ready, return 0 if ready, -1 otherwise */
static int SLSH_R(SLSH_task* tasks)
{
int s;
 
/* for all static tasks */
for(s = 0; tasks[s].est != -1; ++s)
{
if(proc_table[s].status == SLSH_READY)
return 0;
}
return -1;
}
 
/* check if unspecified exists, return 0 if it exists, -1 otherwise */
static int SLSH_T(IQUEUE *unspecified)
{
if(!iq_isempty(unspecified))
return 0;
else
return -1;
}
 
/* return the sc in an interval */
static int SLSH_sc(SLSH_interval* intervals, int i)
{
return intervals[i].sc;
}
/* return a static task from current interval or a guaranted task */
static PID SLSH_staticOrGuaranteed(SLSH_level_des* lev)
{
int lowest_dl = 0; /* lowest dl found */
PID pid = 0; /* static or guaranteed task */
int t;
 
/* Decide according to EDF, go through all static & guaranteed tasks */
for(t = 0; t < MAX_PROC; ++t)
{
/* static tasks */
if(proc_table[t].pclass == STATIC_PCLASS)
{
/* static task must belong to current interval */
if(lev->tasks[t].interval == lev->current)
{
/* only ready tasks */
if(proc_table[t].status == SLSH_READY)
{
/* a new lower dl was found */
if(lev->tasks[t].dabs < lowest_dl)
{
lowest_dl = lev->tasks[t].dabs;
pid = t;
}
}
}
} /* guaranteed tasks */
else if(proc_table[t].pclass == HARD_PCLASS)
{
/* only ready tasks */
if(proc_table[t].status == SLSH_READY)
{
/* a new lower dl was found */
if(lev->tasks[t].dabs < lowest_dl)
{
lowest_dl = lev->tasks[t].dabs;
pid = t;
}
}
}
}/* for all tasks */
return pid;
}
 
/* return a static task among the candidates, all ready statics */
static PID SLSH_candidates(SLSH_task* tasks)
{
int lowest_dl = 0;
PID pid = -1;
int t;
 
/* Use the EDL algorithm again to decide which task to run */
for(t = 0; t < MAX_PROC; ++t)
{
/* only static tasks */
if(proc_table[t].pclass == STATIC_PCLASS)
{
/* only ready tasks */
if(proc_table[t].status == SLSH_READY)
{
/* a new lower dl was found */
if(tasks[t].dabs < lowest_dl)
{
lowest_dl = tasks[t].dabs;
pid = t;
}
}/* all ready tasks */
}/* all static tasks */
}/* for all tasks */
return pid;
}
 
/* decrease the sc in a interval by amount */
void SLSH_decSc(SLSH_interval* intervals, int i, int amount)
{
intervals[i].sc -= amount;
}
 
void SLSH_incSc(SLSH_interval* intervals, int i, int amount)
{
intervals[i].sc += amount;
}
 
/* swap the sc between intervals, also consider intervals with negative sc */
void SLSH_swapSc(SLSH_interval* intervals, int current, int task_interval)
{
/* decrease the sc in the current interval */
SLSH_decSc(intervals, current, 1);
/* update the other interval(s) */
if(intervals[task_interval].sc < 0) /* negative sc */
{
/* special case, increase next interval sc by 1 and also current interval (borrowing) */
if(task_interval == current + 1)
{
SLSH_incSc(intervals, task_interval, 1);
SLSH_incSc(intervals, current, 1);
}
else /* increase every interval sc that is negative between current and task_interval */
{
while(task_interval > current && intervals[task_interval].sc < 0)
{
SLSH_incSc(intervals, task_interval, 1);
task_interval--;
}
}
}
else /* ordinary swapping */
SLSH_incSc(intervals, task_interval, 1);
}
 
/* The scheduler, decides which task to run. */
static PID SLSH_public_scheduler(LEVEL l)
{
SLSH_level_des* lev = (SLSH_level_des *)(level_table[l]);
PID pid;
/* The scheduler choses among static, guaranteed (hard aperiodic) and
unspecified (soft aperiodic) tasks */
/* no ready tasks and no sc, execute idle task */
if(SLSH_R(lev->tasks) == 0 && SLSH_sc(lev->intervals, lev->current) == 0)
return NIL;
/* must execute a static from current intervall or a guaranteed task */
else if(SLSH_R(lev->tasks) > 0 && SLSH_sc(lev->intervals, lev->current) == 0)
return SLSH_staticOrGuaranteed(lev);
/* sc available... */
else if(SLSH_R(lev->tasks) > 0 && SLSH_sc(lev->intervals, lev->current) > 0)
{
/* If unspecified exist, execute it according to FIFO order */
if(SLSH_T(&lev->unspecified) == 0)
{
SLSH_decSc(lev->intervals, lev->current, 1); /* decrease sc by 1 */
return iq_getfirst(&lev->unspecified);
}
else /* No unspecified, execute task from candidates (statics) */
{
pid = SLSH_candidates(lev->tasks);
 
/* sc needs to be swapped */
if(lev->tasks[pid].interval != lev->current)
SLSH_swapSc(lev->intervals, lev->tasks[pid].interval, lev->current);
return pid;
}
}
 
kern_printf("(SLSH s)");
return NIL;
}
 
/* not used, slot-shifting handles all guarantees itself, it handles all bandwidth */
static int SLSH_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
{
*freebandwidth = 0;
return 1;
}
 
/* get the interval that x is in */
static int SLSH_getInterval(SLSH_interval* intervals, int x, int last)
{
int i;
 
/* search through the intervals */
for(i = 0; i <= last; ++i)
{
/* I is in the interval where start is smaller or equal and end is bigger */
if(intervals[i].start <= x && x < intervals[i].end)
return i;
}
return -1;
}
 
/* get the start of the interval I */
static int SLSH_intervalStart(SLSH_interval* intervals, int I)
{
return intervals[I].start;
}
 
/* split interval I into two parts, slow because of copying. OBS!!! no check if there is
enough space in the intervals array */
static void SLSH_splitInterval(SLSH_level_des* lev, int I, int dabs)
{
SLSH_interval left_interval;
int i;
 
 
lev->last++;
/* move every interval above and including I */
for(i = lev->last; i > I; --i)
memcpy(&lev->intervals[i], &lev->intervals[i - 1], sizeof(SLSH_interval));
/* Left interval start, end and length */
left_interval.start = lev->intervals[I].start;
left_interval.end = dabs;
left_interval.length = left_interval.end - left_interval.start;
/* Right interval (uses old interval struct) start and length end remains as the old value */
lev->intervals[I + 1].start = dabs;
lev->intervals[I + 1].length = lev->intervals[I + 1].end - lev->intervals[I + 1].start;
/* check if sc still exists in the right interval */
if(lev->intervals[I + 1].length - lev->intervals[I + 1].maxt > 0)
{
lev->intervals[I + 1].sc = lev->intervals[I + 1].length - lev->intervals[I + 1].maxt;
left_interval.sc = left_interval.length; /* the whole interval is free, for now... */
}
else /* no sc in the right interval */
{
lev->intervals[I + 1].maxt = lev->intervals[I + 1].length;
left_interval.sc = lev->intervals[I + 1].sc; /* all sc in left interval */
lev->intervals[I + 1].sc = 0;
}
/* insert the new interval */
memcpy(&lev->intervals[I], &left_interval, sizeof(SLSH_interval));
}
 
/* Reduce the sc from back to front by the wcet amount, interval splitting may be neccesary */
static void SLSH_updateSc(SLSH_level_des* lev, HARD_TASK_MODEL* h)
{
int dabs = ceil((lev->slot + h->drel)/lev->slot_length); /* absolute deadline of request */
int dabs_interval = SLSH_getInterval(lev->intervals, dabs, lev->last); /* interval where dabs is */
int C = ceil(h->wcet/lev->slot_length); /* amount of sc to reduce */
int sc = 0;
int i;
 
/* check if interval splitting is neccesary */
if(lev->intervals[dabs_interval].end != dabs)
SLSH_splitInterval(lev, dabs_interval, dabs);
/* decrease sc in all intervals that are neccesary from dabs_interval o current */
for(i = dabs_interval; i >= lev->current && C > 0; --i)
{
if((sc = SLSH_sc(lev->intervals, i)) >= 0) /* only decrease where sc exists */
{
if(sc > C) /* the last sc dec */
{
SLSH_decSc(lev->intervals, i, C);
C = 0;
}
else /* to little sc in this interval, decrease it to 0 */
{
C -= SLSH_sc(lev->intervals, i);
SLSH_decSc(lev->intervals, i, SLSH_sc(lev->intervals, i));
}
}
}/* for all intervals */
}
 
/* the guarantee algorithm for hard aperiodic requests */
static int SLSH_guarantee(SLSH_level_des* lev, HARD_TASK_MODEL* h)
{
int total_sc = 0;
int temp, i;
int dabs = ceil((lev->slot + h->drel)/lev->slot_length); /* absolute deadline of request */
int dabs_interval = SLSH_getInterval(lev->intervals, dabs, lev->last); /* interval where dabs is */
/* check if the sc up until request deadline is >= request wcet */
/* 1. the sc of the current interal */
total_sc = SLSH_sc(lev->intervals, lev->current);
 
/* 2. the sc for all whole intervals between current and the interval
with the request deadline */
for(i = (lev->current) + 1; i < dabs_interval; ++i)
{
if((temp = SLSH_sc(lev->intervals, i)) > 0)
total_sc += temp;
}
/* 3. the min of sc or the execution need in the last interval */
total_sc += min(SLSH_sc(lev->intervals, dabs_interval),
dabs - SLSH_intervalStart(lev->intervals,
dabs_interval));
 
if(total_sc >= h->wcet)
{ /* update the sc in the intervals from back to front */
SLSH_updateSc(lev, h);
return 0;
}
else
return -1;
}
 
/* check if task model is accepted and store nessecary parameters */
static int SLSH_public_create(LEVEL l, PID p, TASK_MODEL *m)
{
SLSH_level_des *lev = (SLSH_level_des *)(level_table[l]);
STATIC_TASK_MODEL* s;
HARD_TASK_MODEL* h;
SOFT_TASK_MODEL* u;
 
 
/* Check the models */
switch(m->pclass)
{
case STATIC_PCLASS: /* offline scheduled tasks */
break;
case HARD_PCLASS: /* hard aperiodic tasks */
h = (HARD_TASK_MODEL *) m;
if (h->drel == 0 || h->wcet == 0) /* must be set */
return -1;
break;
case SOFT_PCLASS: /* soft aperiodic tasks */
u = (SOFT_TASK_MODEL *) m;
if(u->wcet == 0) /* must be set */
return -1;
break;
default:
return -1;
}
 
 
/* if the SLSH_task_create is called, then the pclass must be a
valid pclass. Slot-shifting accepts STATIC_TASK, HARD_TASK
and SOFT_TASK models with some restrictions */
 
/* est, dl and wcet is saved in slotlengths */
switch(m->pclass)
{
case STATIC_PCLASS: /* offline scheduled tasks */
s = (STATIC_TASK_MODEL *) m;
lev->tasks[p].est = ceil(s->est/lev->slot_length);
lev->tasks[p].dabs = ceil(s->dabs/lev->slot_length);
lev->tasks[p].interval = s->interval;
proc_table[p].avail_time = s->wcet;
proc_table[p].wcet = s->wcet;
break;
case HARD_PCLASS: /* hard aperiodic tasks */
h = (HARD_TASK_MODEL *) m;
if(SLSH_guarantee(lev, h) == 0)
{
/* convert drel to dabs */
lev->tasks[p].dabs = ceil((lev->slot + h->drel)/lev->slot_length);
proc_table[p].avail_time = h->wcet;
proc_table[p].wcet = h->wcet;
}
else /* task not guaranteed */
return -1;
break;
case SOFT_PCLASS:
u = (SOFT_TASK_MODEL *) m;
proc_table[p].avail_time = u->wcet;
proc_table[p].wcet = u->wcet;
iq_insertlast(p, &lev->unspecified); /* respect FIFO order */
break;
default: /* a task model not supported */
return -1;
}
/* enable wcet check in the kernel */
proc_table[p].control |= CONTROL_CAP;
return 0;
}
 
/************* The slot end event handler *************/
static void SLSH_slot_end(void* p)
{
SLSH_level_des* lev = (SLSH_level_des *) p;
PID pid;
int i;
/* increase slot "time" by 1 */
if(lev->slot < lev->LCM)
{
lev->slot++;
/* check if new statics are ready */
for(i = 0; lev->tasks[i].interval != -1; ++i)
{
if(lev->tasks[i].est <= lev->slot && proc_table[i].status == SLSH_WAIT)
proc_table[i].status = SLSH_READY;
}
/* check if current (interval) needs updating */
if(lev->current < SLSH_getInterval(lev->intervals, lev->slot, lev->last))
lev->current++;
}
else /* restart from the beginning of the offline schedule */
{
lev->slot = 0;
while((pid = iq_getfirst(&lev->idle_statics)) != NIL)
{
if(lev->tasks[pid].est <= lev->slot)
proc_table[pid].status = SLSH_READY;
else
proc_table[pid].status = SLSH_WAIT;
}
}
 
/* call for a rescheduling, reset event flag and increase slot by 1 */
lev->slot_event = -1;
kern_printf("*");
event_need_reschedule();
}
 
/* when a task becomes executing (EXE status) */
static void SLSH_public_dispatch(LEVEL l, PID pid, int nostop)
{
SLSH_level_des *lev = (SLSH_level_des *)(level_table[l]);
struct timespec t;
 
/* the task state is set EXE by the scheduler()
we extract the task from the unspecified queue.
NB: we can't assume that p is the first task in the queue!!! */
if(proc_table[pid].pclass == SOFT_PCLASS)
iq_extract(pid, &lev->unspecified);
 
/* also start the timer for one slot length */
lev->slot_event = kern_event_post(&TIME2TIMESPEC(lev->slot_length, t),
SLSH_slot_end, (void*) lev);
}
 
/* called when task is moved from EXE status */
static void SLSH_public_epilogue(LEVEL l, PID pid)
{
SLSH_level_des *lev = (SLSH_level_des *)(level_table[l]);
 
/* check if the wcet is finished... */
if (proc_table[pid].avail_time <= 0)
{
/* if it is, raise a XWCET_VIOLATION exception */
kern_raise(XWCET_VIOLATION, pid);
proc_table[pid].status = SLSH_WCET_VIOLATED;
}
else /* the end of a slot. the task returns into the ready queue... */
{
if(proc_table[pid].pclass == SOFT_PCLASS)
iq_insertfirst(pid,&lev->unspecified);
proc_table[pid].status = SLSH_READY;
}
}
 
/* when task go from SLEEP to SLSH_READY or SLSH_WAIT */
static void SLSH_public_activate(LEVEL l, PID pid)
{
SLSH_level_des *lev = (SLSH_level_des *)(level_table[l]);
WORD type = proc_table[pid].pclass;
 
/* Test if we are trying to activate a non sleeping task */
/* Ignore this; the task is already active */
if (proc_table[pid].status != SLEEP && proc_table[pid].status != SLSH_WCET_VIOLATED)
return;
 
/* make task ready or waiting, dependong on slot (the time) for static tasks only*/
if(type == STATIC_PCLASS && lev->tasks[pid].est <= lev->slot)
proc_table[pid].status = SLSH_READY;
else
proc_table[pid].status = SLSH_WAIT;
if(type == HARD_PCLASS)
proc_table[pid].status = SLSH_READY;
/* insert unspecified tasks in QQUEUE and make it ready */
if(type == SOFT_PCLASS)
{
iq_insertlast(pid ,&lev->unspecified);
proc_table[pid].status = SLSH_READY;
}
}
 
/* when a task i returned to module from a semaphore, mutex ... */
static void SLSH_public_unblock(LEVEL l, PID pid)
{
SLSH_level_des *lev = (SLSH_level_des *)(level_table[l]);
 
/* change staus of task */
proc_table[pid].status = SLSH_READY;
if(proc_table[pid].pclass == SOFT_PCLASS)
iq_insertfirst(pid ,&lev->unspecified);
}
 
/* when a semaphore, mutex ... taskes a task from module */
static void SLSH_public_block(LEVEL l, PID pid)
{
/* Extract the running task from the level
. we have already extract it from the ready queue at the dispatch time.
. the capacity event have to be removed by the generic kernel
. the wcet don't need modification...
. the state of the task is set by the calling function
. the deadline must remain...
 
So, we do nothing!!!
*/
}
 
/* the task has finihed its wcet, kill task (dont kill static tasks) */
static void SLSH_public_end(LEVEL l, PID pid)
{
SLSH_level_des *lev = (SLSH_level_des *)(level_table[l]);
 
if(proc_table[pid].pclass == SOFT_PCLASS)
{
if (proc_table[pid].status == SLSH_READY)
iq_extract(pid, &lev->unspecified);
}
else if(proc_table[pid].pclass == HARD_PCLASS)
{
if (proc_table[pid].status == SLSH_READY)
lev->tasks[pid].dabs = 0;
}
/* static tasks: put them in idle QUEUE, reset status and avail_time */
else if(proc_table[pid].pclass == STATIC_PCLASS)
{
proc_table[pid].avail_time = proc_table[pid].wcet;
proc_table[pid].status = SLSH_IDLE;
iq_priority_insert(pid, &lev->idle_statics);
}
proc_table[pid].status = FREE;
}
 
/* called when a task should sleep but not execute for awhile, mabe a mode change */
//static void SLSH_task_sleep(LEVEL l, PID pid)
//{
//
// /* the task has terminated his job before it consume the wcet. All OK! */
// proc_table[pid].status = SLEEP;
//
// /* we reset the capacity counters... only for static tasks */
// if (proc_table[pid].pclass == STATIC_PCLASS)
// proc_table[pid].avail_time = proc_table[pid].wcet;
//
//}
 
 
/** Guest Functions, slot shifing accepts no guests, so all generates exceptions **/
 
/******* Registration functions *******/
 
/*+ Registration function: */
LEVEL SLSH_register_level()
{
LEVEL l; /* the level that we register */
SLSH_level_des *lev; /* for readableness only */
PID i; /* a counter */
kern_printf("SLSH_register_level\n");
/* request an entry in the level_table */
l = level_alloc_descriptor(sizeof(SLSH_level_des));
lev = (SLSH_level_des *)level_table[l];
printk(" lev=%d\n",(int)lev);
/* fill the standard descriptor */
lev->l.public_scheduler = SLSH_public_scheduler;
lev->l.public_guarantee = SLSH_public_guarantee;
lev->l.public_create = SLSH_public_create;
lev->l.public_end = SLSH_public_end;
lev->l.public_dispatch = SLSH_public_dispatch;
lev->l.public_epilogue = SLSH_public_epilogue;
lev->l.public_activate = SLSH_public_activate;
lev->l.public_unblock = SLSH_public_unblock;
lev->l.public_block = SLSH_public_block;
/* fill the SLSH descriptor part */
for(i = 0; i < MAX_PROC; i++)
{
lev->tasks[i].est = -1;
lev->tasks[i].dabs = 0;
lev->tasks[i].interval = -1;
}
for(i = 0; i < MAX_INTERVALS; i++)
{
lev->intervals[i].start = -1;
lev->intervals[i].end = -1;
lev->intervals[i].length = 0;
lev->intervals[i].maxt = 0;
lev->intervals[i].sc = 0;
}
 
lev->current = 0;
lev->last = NIL;
lev->slot = 0;
lev->slot_length = 0;
lev->slot_event = -1;
 
return l;
}
 
 
void SLSH_set_interval(LEVEL l, int start, int end, int maxt)
{
SLSH_level_des* lev = (SLSH_level_des *)(level_table[l]);
static int i = -1;
i++;
lev->intervals[i].start = start;
lev->intervals[i].end = end;
lev->intervals[i].length = end - start;
lev->intervals[i].maxt = maxt;
lev->intervals[i].sc = lev->intervals[i].length - maxt;
lev->last = i;
}
 
void SLSH_set_variables(LEVEL l, TIME length)
{
SLSH_level_des* lev = (SLSH_level_des *)(level_table[l]);
lev->slot_length = length;
}
/advdemos/trunk/slsh/slshtest.c
0,0 → 1,173
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/**
------------
CVS : $Id: slshtest.c,v 1.1.1.1 2004-05-24 17:54:50 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:50 $
------------
 
Slot shifting test
**/
 
/*
* Copyright (C) 2000 Paolo Gai and Tomas Lennvall
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include <kernel/config.h>
#include "kernel/kern.h"
#include "slsh.h"
#include "drivers/keyb.h"
 
/* a slot length of 100 ms */
#define SLOT_LENGTH 100000
 
 
TASK static1(void)
{
int i = 0;
 
kern_printf("Static1\n");
while(sys_gettime(NULL) < 10000) i++;
 
return 0;
}
 
TASK static2(void)
{
int i = 0;
kern_printf("Static2\n");
while(sys_gettime(NULL) < 10000) i++;
 
return 0;
}
 
 
TASK static3(void)
{
kern_printf("Static3\n");
 
return 0;
}
 
void my_end(KEY_EVT *e)
{
sys_end();
}
 
int main(int argc, char** argv)
{
STATIC_TASK_MODEL s;
// HARD_TASK_MODEL h_aper;
// SOFT_TASK_MODEL u;
PID p1,p2,p3;
struct timespec x;
KEY_EVT emerg;
 
kern_cli();
x.tv_sec=5;
kern_event_post(&x,(void (*)(void *))sys_end,NULL);
kern_sti();
 
//keyb_set_map(itaMap);
emerg.ascii = 'x';
emerg.scan = KEY_X;
emerg.flag = ALTL_BIT;
keyb_hook(emerg,my_end);
 
/* set som variables in the scheduling level */
SLSH_set_interval(0, 0, 8, 5);
SLSH_set_interval(0, 8, 17, 7);
SLSH_set_interval(0, 17, 20, 1);
 
SLSH_set_variables(0, SLOT_LENGTH);
static_task_default_model(s);
static_task_def_group(s, 1);
/* define time i ms */
/* static1 task */
static_task_def_est(s, 0);
static_task_def_dabs(s, 800000);
static_task_def_wcet(s, 500000);
static_task_def_interval(s, 0);
 
kern_printf("In main, before task creation\n");
 
p1 = task_create("Static 1", static1, &s, NULL);
if(p1 == NIL)
kern_printf("Cannot create: Static1!\n");
/* Static2 task */
static_task_def_est(s, 800000);
static_task_def_dabs(s, 1700000);
static_task_def_wcet(s, 700000);
static_task_def_interval(s, 1);
p2 = task_create("Static 2", static2, &s, NULL);
if(p2 == NIL)
kern_printf("Cannot create: Static2!\n");
 
/* Static3 task */
static_task_def_est(s, 1700000);
static_task_def_dabs(s, 2000000);
static_task_def_wcet(s, 100000);
static_task_def_interval(s, 2);
 
p3 = task_create("Static3", static3, &s, NULL);
if(p3 == NIL)
kern_printf("Cannot create: Static3!\n");
 
 
/* End task */
/*hard_task_default_model(h_aper);
hard_task_def_wcet(h_aper, 100000);
*/
kern_printf("After task creation\n");
 
group_activate(1);
 
return 0;
}
/advdemos/trunk/slsh/readme.txt
0,0 → 1,6
This Example has been made by Tomas Lenvall.
 
There is not a lot of documentation available, so if you have problems please
send an e-mail to Tomas ( mailto:tlv@mdh.se )
 
Paolo
/advdemos/trunk/slsh/makefile
0,0 → 1,16
#
#
#
 
ifndef BASE
BASE=../..
endif
 
include $(BASE)/config/config.mk
 
PROGS=slshtest
 
include $(BASE)/config/example.mk
 
slshtest:
make -f $(SUBMAKE) APP=slshtest INIT= OTHEROBJS="slshinit.o slsh.o" OTHERINCL= SHARKOPT=__OLDCHAR__
/advdemos/trunk/slsh/slshinit.c
0,0 → 1,117
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/**
------------
CVS : $Id: slshinit.c,v 1.1.1.1 2004-05-24 17:54:50 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:50 $
------------
 
System initialization file
 
The tick is set to TICK ms.
 
This file contains the 2 functions needed to initialize the system.
 
These functions register the following levels:
 
a Slot Shifting level
a Dummy level
 
It can accept these task models:
 
STATIC_TASK_MODEL
HARD_TASK_MODEL(aperiodic)
SOFT_TASK_MODEL
 
**/
 
/*
* Copyright (C) 2000 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
 
#include "kernel/kern.h"
#include "slsh.h"
#include "modules/rr2.h"
#include "modules/sem.h"
#include "modules/hartport.h"
#include "drivers/keyb.h"
#include "modules/dummy.h"
 
/*+ sysyem tick in us +*/
#define TICK 300
 
/* define RR tick in us*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
SLSH_register_level();
RR2_register_level(RRTICK, RR2_MAIN_YES, mb);
dummy_register_level();
 
SEM_register_module();
 
return TICK;
}
 
NRT_TASK_MODEL nrt;
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS k = BASE_KEYB;
 
nrt_task_default_model(nrt);
keyb_def_task(k,&nrt);
 
 
 
HARTPORT_init();
 
KEYB_init(NULL);
 
__call_main__(mb);
 
return 0;
}