Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 1623 → Rev 1624

/advdemos/branches/advdemos/cbs_ft/cbs_ft.c
0,0 → 1,811
/*
* Project: S.Ha.R.K.
*
* Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@hartik.sssup.it>
*
* Authors : Marco Caccamo and Paolo Gai
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/**
------------
CVS : $Id: cbs_ft.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 server CBS_FT
 
Read CBS_FT.h for further details.
 
**/
 
/*
* Copyright (C) 2000 Marco Caccamo and 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 "cbs_ft.h"
 
/*+ Status used in the level +*/
#define CBS_FT_IDLE APER_STATUS_BASE /*+ waiting the activation +*/
#define CBS_FT_ZOMBIE APER_STATUS_BASE+1 /*+ waiting the period end +*/
 
/* structure of an element of the capacity queue */
struct cap_queue {
int cap;
struct timespec dead;
struct cap_queue *next;
};
 
/*+ the level redefinition for the CBS_FT level +*/
typedef struct {
level_des l; /*+ the standard level descriptor +*/
 
/* The wcet are stored in the task descriptor, but we need
an array for the deadlines. We can't use the timespec_priority
field because it is used by the master level!!!...
Notice that however the use of the timespec_priority field
does not cause any problem... */
 
struct timespec cbs_ft_dline[MAX_PROC]; /*+ CBS_FT deadlines +*/
 
TIME period[MAX_PROC]; /*+ CBS_FT activation period +*/
 
 
int maxcap[MAX_PROC]; /* amount of capacity reserved to a primary+backup
couple */
PID backup[MAX_PROC]; /* Backup task pointers, defined for primary tasks */
 
char CP[MAX_PROC]; /* checkpoint flag */
char P_or_B[MAX_PROC]; /* Type of task: PRIMARY or BACKUP */
 
struct timespec reactivation_time[MAX_PROC];
/*+ the time at witch the reactivation timer is post +*/
 
int reactivation_timer[MAX_PROC]; /*+ the recativation timer +*/
 
struct cap_queue *queue; /* pointer to the spare capacity queue */
 
int flags; /*+ the init flags... +*/
 
bandwidth_t U; /*+ the used bandwidth by the server +*/
 
int idle; /* the idle flag... */
struct timespec start_idle; /*gives the start time of the last idle period */
LEVEL scheduling_level;
 
} CBS_FT_level_des;
 
 
 
/* insert a capacity in the queue capacity ordering by deadline */
 
static int c_insert(struct timespec dead, int cap, struct cap_queue **que,
PID p)
{
struct cap_queue *prev, *n, *new;
 
prev = NULL;
n = *que;
 
while ((n != NULL) &&
!TIMESPEC_A_LT_B(&dead, &n->dead)) {
prev = n;
n = n->next;
}
 
new = (struct cap_queue *)kern_alloc(sizeof(struct cap_queue));
if (new == NULL) {
kern_printf("\nNew cash_queue element failed\n");
kern_raise(XINVALID_TASK, p);
return -1;
}
new->next = NULL;
new->cap = cap;
new->dead = dead;
if (prev != NULL)
prev->next = new;
else
*que = new;
 
if (n != NULL)
new->next = n;
return 0;
 
}
 
/* extract the first element from the capacity queue */
 
int c_extractfirst(struct cap_queue **que)
{
struct cap_queue *p = *que;
 
 
if (*que == NULL) return(-1);
*que = (*que)->next;
kern_free(p, sizeof(struct cap_queue));
return(1);
}
 
/* read data of the first element from the capacity queue */
 
static void c_readfirst(struct timespec *d, int *c, struct cap_queue *que)
{
*d = que->dead;
*c = que->cap;
}
 
/* write data of the first element from the capacity queue */
 
static void c_writefirst(struct timespec dead, int cap, struct cap_queue *que)
{
que->dead = dead;
que->cap = cap;
}
 
 
static void CBS_FT_activation(CBS_FT_level_des *lev,
PID p,
struct timespec *acttime)
{
JOB_TASK_MODEL job;
int capacity;
/* This rule is used when we recharge the budget at initial task activation
and each time a new task instance must be activated */
if (TIMESPEC_A_GT_B(acttime, &lev->cbs_ft_dline[p])) {
/* we modify the deadline ... */
TIMESPEC_ASSIGN(&lev->cbs_ft_dline[p], acttime);
}
 
if (proc_table[p].avail_time > 0)
proc_table[p].avail_time = 0;
 
 
/* A spare capacity is inserted in the capacity queue!! */
ADDUSEC2TIMESPEC(lev->period[p], &lev->cbs_ft_dline[p]);
capacity = lev->maxcap[p] - proc_table[ lev->backup[p] ].wcet;
c_insert(lev->cbs_ft_dline[p], capacity, &lev->queue, p);
/* it exploits available capacities from the capacity queue */
while (proc_table[p].avail_time < proc_table[p].wcet &&
lev->queue != NULL) {
struct timespec dead;
int cap, delta;
delta = proc_table[p].wcet - proc_table[p].avail_time;
c_readfirst(&dead, &cap, lev->queue);
if (!TIMESPEC_A_GT_B(&dead, &lev->cbs_ft_dline[p])) {
if (cap > delta) {
proc_table[p].avail_time += delta;
c_writefirst(dead, cap - delta, lev->queue);
}
else {
proc_table[p].avail_time += cap;
c_extractfirst(&lev->queue);
}
}
else
break;
}
/* If the budget is still less than 0, an exception is raised */
if (proc_table[p].avail_time <= 0) {
kern_printf("\nnegative value for the budget!\n");
kern_raise(XINVALID_TASK, p);
return;
}
 
 
/*if (p==6)
kern_printf("(act_time:%d dead:%d av_time:%d)\n",
acttime->tv_sec*1000000+
acttime->tv_nsec/1000,
lev->cbs_ft_dline[p].tv_sec*1000000+
lev->cbs_ft_dline[p].tv_nsec/1000,
proc_table[p].avail_time); */
 
 
 
 
 
#ifdef TESTG
if (starttime && p == 3) {
oldx = x;
x = ((lev->cbs_ft_dline[p].tv_sec*1000000+lev->cbs_ft_dline[p].tv_nsec/1000)/5000 - starttime) + 20;
// kern_printf("(a%d)",lev->cbs_ft_dline[p].tv_sec*1000000+lev->cbs_ft_dline[p].tv_nsec/1000);
if (oldx > x) sys_end();
if (x<640)
grx_plot(x, 15, 8);
}
#endif
 
/* and, finally, we reinsert the task in the master level */
job_task_default_model(job, lev->cbs_ft_dline[p]);
job_task_def_yesexc(job);
level_table[ lev->scheduling_level ]->
private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
}
 
 
/* this is the periodic reactivation of the task... */
static void CBS_FT_timer_reactivate(void *par)
{
PID p = (PID) par;
CBS_FT_level_des *lev;
struct timespec t;
 
lev = (CBS_FT_level_des *)level_table[proc_table[p].task_level];
 
if (proc_table[p].status == CBS_FT_IDLE) {
/* the task has finished the current activation and must be
reactivated */
/* request_time represents the time of the last instance release!! */
TIMESPEC_ASSIGN(&t, &lev->reactivation_time[p]);
/* If idle=1, then we have to discharge the capacities stored in
the capacity queue up to the length of the idle interval */
if (lev->idle == 1) {
TIME interval;
struct timespec delta;
lev->idle = 0;
SUBTIMESPEC(&t, &lev->start_idle, &delta);
/* length of the idle interval expressed in usec! */
interval = TIMESPEC2NANOSEC(&delta) / 1000;
 
/* it discharges the available capacities from the capacity queue */
while (interval > 0 && lev->queue != NULL) {
struct timespec dead;
int cap;
c_readfirst(&dead, &cap, lev->queue);
if (cap > interval) {
c_writefirst(dead, cap - interval, lev->queue);
interval = 0;
}
else {
interval -= cap;
c_extractfirst(&lev->queue);
}
}
}
 
CBS_FT_activation(lev,p,&lev->reactivation_time[p]);
 
/* Set the reactivation timer */
TIMESPEC_ASSIGN(&lev->reactivation_time[p], &lev->cbs_ft_dline[p]);
lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
CBS_FT_timer_reactivate,
(void *)p);
event_need_reschedule();
}
else {
/* this situation cannot occur */
kern_printf("\nTrying to reactivate a primary task which is not IDLE!\n");
kern_raise(XINVALID_TASK,p);
}
}
 
 
 
static void CBS_FT_avail_time_check(CBS_FT_level_des *lev, PID p)
{
/*+ if the capacity became negative the remaining computation time
is diminuished.... +*/
/* if (p==4)
kern_printf("(old dead:%d av_time:%d)\n",
lev->cbs_ft_dline[p].tv_sec*1000000+
lev->cbs_ft_dline[p].tv_nsec/1000,
proc_table[p].avail_time); */
 
 
int newcap = proc_table[p].wcet / 100 * 30;
if (newcap <= 0)
newcap = proc_table[p].wcet;
/* it exploits available capacities from the capacity queue */
while (proc_table[p].avail_time < newcap
&& lev->queue != NULL) {
struct timespec dead;
int cap, delta;
delta = newcap - proc_table[p].avail_time;
c_readfirst(&dead, &cap, lev->queue);
if (!TIMESPEC_A_GT_B(&dead, &lev->cbs_ft_dline[p])) {
if (cap > delta) {
proc_table[p].avail_time += delta;
c_writefirst(dead, cap - delta, lev->queue);
}
else {
proc_table[p].avail_time += cap;
c_extractfirst(&lev->queue);
}
}
else
break;
}
 
 
 
/*if (p==6)
kern_printf("(ATC dead:%d av_time:%d)\n",
lev->cbs_ft_dline[p].tv_sec*1000000+
lev->cbs_ft_dline[p].tv_nsec/1000,
proc_table[p].avail_time); */
 
 
/* if the budget is still empty, the backup task must be woken up.
Remind that a short chunk of primary will go ahead executing
before the task switch occurs */
if (proc_table[p].avail_time <= 0) {
lev->CP[p] = 1;
proc_table[p].avail_time += proc_table[ lev->backup[p] ].wcet;
}
 
 
/*if (p==6)
kern_printf("(ATC1 dead:%d av_time:%d)\n",
lev->cbs_ft_dline[p].tv_sec*1000000+
lev->cbs_ft_dline[p].tv_nsec/1000,
proc_table[p].avail_time); */
 
 
}
 
 
/*+ this function is called when a killed or ended task reach the
period end +*/
static void CBS_FT_timer_zombie(void *par)
{
PID p = (PID) par;
CBS_FT_level_des *lev;
 
lev = (CBS_FT_level_des *)level_table[proc_table[p].task_level];
 
/* we finally put the task in the FREE status */
proc_table[p].status = FREE;
iq_insertfirst(p,&freedesc);
 
 
/* and free the allocated bandwidth */
lev->U -= (MAX_BANDWIDTH / lev->period[p]) * (TIME)lev->maxcap[p];
}
 
static PID CBS_FT_public_scheduler(LEVEL l)
{
CBS_FT_level_des *lev = (CBS_FT_level_des *)(level_table[l]);
/* it stores the actual time and set the IDLE flag in order to handle
the capacity queue discharging!!! */
lev->idle = 1;
kern_gettime(&lev->start_idle);
 
/* the CBS_FT don't schedule anything...
it's an EDF level or similar that do it! */
return NIL;
}
 
 
/* The on-line guarantee is enabled only if the appropriate flag is set... */
static int CBS_FT_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
{
CBS_FT_level_des *lev = (CBS_FT_level_des *)(level_table[l]);
 
if (lev->flags & CBS_FT_FAILED_GUARANTEE) {
*freebandwidth = 0;
kern_printf("guarantee :garanzia fallita!!!!!!\n");
return 0;
}
else if (*freebandwidth >= lev->U) {
*freebandwidth -= lev->U;
return 1;
}
else {
kern_printf("guarantee :garanzia fallita per mancanza di banda!!!!!!\n");
kern_printf("freeband: %d request band: %d", *freebandwidth, lev->U);
return 0;
}
}
 
 
static int CBS_FT_public_create(LEVEL l, PID p, TASK_MODEL *m)
 
{
CBS_FT_level_des *lev = (CBS_FT_level_des *)(level_table[l]);
FT_TASK_MODEL *s;
 
if (m->pclass != FT_PCLASS) return -1;
if (m->level != 0 && m->level != l) return -1;
s = (FT_TASK_MODEL *) m;
//kern_printf("accept :FAULT TOLERANT TASK found!!!!!!\n"); */
if (!(s->type == PRIMARY && s->execP > 0 && s->budget < (int)s->period
&& s->backup != NIL)) return -1;
if (!(s->type == BACKUP && s->wcetB > 0))
return -1;
/* now we know that m is a valid model */
/* Enable budget check */
proc_table[p].control |= CONTROL_CAP;
 
proc_table[p].avail_time = 0;
NULL_TIMESPEC(&lev->cbs_ft_dline[p]);
 
 
if (s->type == PRIMARY) {
proc_table[p].wcet = (int)s->execP;
lev->period[p] = s->period;
lev->maxcap[p] = s->budget;
lev->backup[p] = s->backup;
lev->CP[p] = 0;
lev->P_or_B[p] = PRIMARY;
 
/* update the bandwidth... */
if (lev->flags & CBS_FT_ENABLE_GUARANTEE) {
bandwidth_t b;
b = (MAX_BANDWIDTH / lev->period[p]) * (TIME)lev->maxcap[p];
/* really update lev->U, checking an overflow... */
if (MAX_BANDWIDTH - lev->U > b)
lev->U += b;
else
/* The task can NOT be guaranteed (U>MAX_BANDWIDTH)...
(see EDF.c) */
lev->flags |= CBS_FT_FAILED_GUARANTEE;
}
}
else {
proc_table[p].wcet = (int)s->wcetB;
lev->P_or_B[p] = BACKUP;
 
/* Backup tasks are unkillable tasks! */
proc_table[p].control |= NO_KILL;
}
return 0; /* OK, also if the task cannot be guaranteed... */
}
 
 
static void CBS_FT_public_detach(LEVEL l, PID p)
{
/* the CBS_FT level doesn't introduce any dynamic allocated new field.
we have only to reset the NO_GUARANTEE FIELD and decrement the allocated
bandwidth */
 
CBS_FT_level_des *lev = (CBS_FT_level_des *)(level_table[l]);
 
if (lev->flags & CBS_FT_FAILED_GUARANTEE)
lev->flags &= ~CBS_FT_FAILED_GUARANTEE;
else
lev->U -= (MAX_BANDWIDTH / lev->period[p]) * (TIME)lev->maxcap[p];
}
 
 
static void CBS_FT_public_dispatch(LEVEL l, PID p, int nostop)
{
CBS_FT_level_des *lev = (CBS_FT_level_des *)(level_table[l]);
level_table[ lev->scheduling_level ]->
private_dispatch(lev->scheduling_level,p,nostop);
}
 
static void CBS_FT_public_epilogue(LEVEL l, PID p)
{
CBS_FT_level_des *lev = (CBS_FT_level_des *)(level_table[l]);
 
/* check if the budget is finished... */
if (proc_table[p].avail_time <= 0) {
 
/* A backup task cannot ever exhaust its budget! */
if (lev->P_or_B[p] == BACKUP) {
kern_printf("\nBACKUP wcet violation!\n");
kern_raise(XWCET_VIOLATION,p);
/* we kill the current activation */
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level, p);
return;
}
 
/* we try to recharge the budget */
CBS_FT_avail_time_check(lev, p);
 
/* The budget must be greater than 0! */
if (proc_table[p].avail_time <= 0) {
kern_printf("\nBackup task starting with exhausted budget\n");
kern_raise(XINVALID_TASK, p);
lev->CP[p] = 0;
/* we kill the current activation */
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level, p);
return;
}
}
/* the task returns into the ready queue by
calling the guest_epilogue... */
level_table[ lev->scheduling_level ]->
private_epilogue(lev->scheduling_level,p);
}
 
 
static void CBS_FT_public_activate(LEVEL l, PID p)
{
CBS_FT_level_des *lev = (CBS_FT_level_des *)(level_table[l]);
struct timespec t;
 
kern_gettime(&t);
 
if (lev->P_or_B[p] == BACKUP) {
kern_printf("\nTrying to activate a BACKUP task!\n");
kern_raise(XINVALID_TASK, p);
}
else {
/* If idle=1, then we have to discharge the capacities stored in
the capacity queue up to the length of the idle interval */
if (lev->idle == 1) {
TIME interval;
struct timespec delta;
lev->idle = 0;
SUBTIMESPEC(&t, &lev->start_idle, &delta);
/* length of the idle interval expressed in usec! */
interval = TIMESPEC2NANOSEC(&delta) / 1000;
/* it discharge the available capacities from the capacity queue */
while (interval > 0 && lev->queue != NULL) {
struct timespec dead;
int cap;
c_readfirst(&dead, &cap, lev->queue);
if (cap > interval) {
c_writefirst(dead, cap - interval, lev->queue);
interval = 0;
}
else {
interval -= cap;
c_extractfirst(&lev->queue);
}
}
}
CBS_FT_activation(lev, p, &t);
/* Set the reactivation timer */
TIMESPEC_ASSIGN(&lev->reactivation_time[p], &lev->cbs_ft_dline[p]);
lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
CBS_FT_timer_reactivate,
(void *)p);
// kern_printf("act : %d %d |",lev->cbs_ft_dline[p].tv_nsec/1000,p);
}
}
 
static int CBS_FT_public_message(LEVEL l, PID p, void *m)
{
CBS_FT_level_des *lev = (CBS_FT_level_des *)(level_table[l]);
 
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level,p);
 
proc_table[p].status = CBS_FT_IDLE;
 
if (lev->P_or_B[p] == PRIMARY) {
if (lev->CP[p]) {
JOB_TASK_MODEL job;
/* We have to start the backup task */
TIMESPEC_ASSIGN(&lev->cbs_ft_dline[ lev->backup[p] ],
&lev->cbs_ft_dline[p]);
proc_table[ lev->backup[p] ].avail_time = proc_table[p].avail_time;
lev->CP[p] = 0;
 
/* and, finally, we insert the backup task in the master level */
job_task_default_model(job, lev->cbs_ft_dline[p]);
job_task_def_yesexc(job);
level_table[ lev->scheduling_level ]->
private_insert(lev->scheduling_level, lev->backup[p],
(TASK_MODEL *)&job);
}
else {
/* A spare capacity is inserted in the capacity queue!! */
proc_table[p].avail_time += proc_table[ lev->backup[p] ].wcet;
if (proc_table[p].avail_time > 0) {
c_insert(lev->cbs_ft_dline[p], proc_table[p].avail_time,
&lev->queue, p);
proc_table[p].avail_time = 0;
}
}
}
else {
/* this branch is for backup tasks:
A spare capacity is inserted in the capacity queue!! */
if (proc_table[p].avail_time > 0) {
c_insert(lev->cbs_ft_dline[p], proc_table[p].avail_time,
&lev->queue, p);
proc_table[p].avail_time = 0;
}
}
 
jet_update_endcycle(); /* Update the Jet data... */
 
return 0;
}
 
 
static void CBS_FT_public_end(LEVEL l, PID p)
{
CBS_FT_level_des *lev = (CBS_FT_level_des *)(level_table[l]);
 
/* A backup task cannot be killed, this behaviour can be modified
in a new release */
if (lev->P_or_B[p] == BACKUP) {
kern_printf("\nKilling a BACKUP task!\n");
kern_raise(XINVALID_TASK, p);
return;
}
 
/* check if the capacity becomes negative... */
/* there is a while because if the wcet is << than the system tick
we need to postpone the deadline many times */
while (proc_table[p].avail_time < 0) {
/* the CBS_FT rule for recharging the capacity */
proc_table[p].avail_time += lev->maxcap[p];
ADDUSEC2TIMESPEC(lev->period[p], &lev->cbs_ft_dline[p]);
}
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level,p);
 
 
/* we delete the reactivation timer */
kern_event_delete(lev->reactivation_timer[p]);
lev->reactivation_timer[p] = -1;
 
/* Finally, we post the zombie event. when the end period is reached,
the task descriptor and banwidth are freed */
proc_table[p].status = CBS_FT_ZOMBIE;
lev->reactivation_timer[p] = kern_event_post(&lev->cbs_ft_dline[p],
CBS_FT_timer_zombie,
(void *)p);
}
 
/* Registration functions */
 
/*+ Registration function:
int flags the init flags ... see CBS.h +*/
LEVEL CBS_FT_register_level(int flags, LEVEL master)
{
LEVEL l; /* the level that we register */
CBS_FT_level_des *lev; /* for readableness only */
PID i; /* a counter */
 
printk("CBS_FT_register_level\n");
 
/* request an entry in the level_table */
l = level_alloc_descriptor(sizeof(CBS_FT_level_des));
 
lev = (CBS_FT_level_des *)level_table[l];
 
printk(" lev=%d\n",(int)lev);
 
/* fill the standard descriptor */
lev->l.public_scheduler = CBS_FT_public_scheduler;
 
if (flags & CBS_FT_ENABLE_GUARANTEE)
lev->l.public_guarantee = CBS_FT_public_guarantee;
else
lev->l.public_guarantee = NULL;
 
lev->l.public_create = CBS_FT_public_create;
lev->l.public_detach = CBS_FT_public_detach;
lev->l.public_end = CBS_FT_public_end;
lev->l.public_dispatch = CBS_FT_public_dispatch;
lev->l.public_epilogue = CBS_FT_public_epilogue;
lev->l.public_activate = CBS_FT_public_activate;
lev->l.public_message = CBS_FT_public_message;
 
/* fill the CBS_FT descriptor part */
for (i=0; i<MAX_PROC; i++) {
NULL_TIMESPEC(&lev->cbs_ft_dline[i]);
lev->period[i] = 0;
NULL_TIMESPEC(&lev->reactivation_time[i]);
lev->reactivation_timer[i] = -1;
lev->maxcap[i] = 0;
lev->backup[i] = NIL;
lev->CP[i] = 0;
lev->P_or_B[i] = PRIMARY;
}
 
lev->U = 0;
lev->idle = 0;
lev->queue = NULL;
lev->scheduling_level = master;
 
lev->flags = flags & 0x07;
 
return l;
}
 
 
 
bandwidth_t CBS_FT_usedbandwidth(LEVEL l)
{
CBS_FT_level_des *lev = (CBS_FT_level_des *)(level_table[l]);
 
return lev->U;
}
 
 
 
void CBS_FT_Primary_Abort()
{
PID p;
CBS_FT_level_des *lev;
 
kern_cli();
p = exec_shadow;
lev = (CBS_FT_level_des *)level_table[proc_table[p].task_level];
lev->CP[p] = 1;
kern_sti();
}
 
 
char CBS_FT_Checkpoint()
{
char f;
PID p;
CBS_FT_level_des *lev;
kern_cli();
p = exec_shadow;
lev = (CBS_FT_level_des *)level_table[proc_table[p].task_level];
f = lev->CP[p];
kern_sti();
return f;
}
/advdemos/branches/advdemos/cbs_ft/initfile.c
0,0 → 1,112
/*
* Project: S.Ha.R.K.
*
* Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@hartik.sssup.it>
*
* Authors : Marco caccamo and Paolo Gai
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/**
------------
CVS : $Id: initfile.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 server CBS_FT
 
Read CBS_FT.h for further details.
 
**/
 
/*
* Copyright (C) 2000 Marco Caccamo and 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 <modules/edf.h>
#include <modules/rr.h>
#include "cbs_ft.h"
#include <modules/cbs.h>
#include <modules/dummy.h>
#include <drivers/keyb.h>
#include <modules/hartport.h>
#include <modules/sem.h>
#include <modules/cabs.h>
 
/*+ system tick in us +*/
#define TICK 300
#define RRTICK 5000
 
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
EDF_register_level(EDF_ENABLE_ALL);
CBS_FT_register_level(CBS_FT_ENABLE_ALL, 0);
RR_register_level(RRTICK, RR_MAIN_YES, mb);
CBS_register_level(CBS_ENABLE_ALL, 0);
dummy_register_level();
 
SEM_register_module();
CABS_register_module();
// periodic timer
return TICK;
// one-shot timer
// return 0
}
 
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
HARTPORT_init();
 
KEYB_init(NULL);
 
__call_main__(mb);
 
return (void *)0;
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/advdemos/branches/advdemos/cbs_ft/cbs_ft.h
0,0 → 1,166
/*
* Project: S.Ha.R.K.
*
* Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@hartik.sssup.it>
*
* Authors : Marco Caccamo and Paolo Gai
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/**
------------
CVS : $Id: cbs_ft.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 $
------------
 
This file contains the server CBS_FT
 
Read CBS_FT.h for further details.
 
**/
 
/*
* Copyright (C) 2000 Marco Caccamo and 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 __CBS_FT__
#define __CBS_FT__
 
 
 
#include <ll/string.h>
#include <kernel/model.h>
#include <kernel/descr.h>
#include <kernel/var.h>
#include <kernel/func.h>
 
 
 
 
 
 
/*+ flags... +*/
#define CBS_FT_ENABLE_GUARANTEE 1 /*+ Task Guarantee enabled +*/
#define CBS_FT_ENABLE_ALL 1
 
#define CBS_FT_FAILED_GUARANTEE 8 /*+ used in the module, unsettable
in EDF_register_level... +*/
 
 
#define PRIMARY 1
#define BACKUP 2
#define FT_PCLASS 0x0700 // Nuova classe di task, quelli fault_tolerant
 
#define CBS_FT_LEVELNAME "CBSFT base"
#define CBS_FT_LEVEL_CODE 110
#define CBS_FT_LEVEL_VERSION 1
 
 
/* The Fault-Tolerant Task model extends the base task model
This model cannot be APERIODIC, only PERIODIC tasks are allowed.
A faut-tolerant application is composed by two different tasks (primary and
backup). The backup task is characterized by its WCET and its type (BACKUP).
The primary task must define the task period, its average execution time
(used as sort of prediction in order to recharge the budget using the
capacity cash queue!), the budget (budget / period = U that is, the
bandwidth assigned to the fault-tolerant application), its type (PRIMARY)
and finally the PID of the corresponding backup task. */
typedef struct {
TASK_MODEL t;
TIME wcetB; // WCET of the backup job (BACKUP TASK ONLY)
 
TIME execP; // average exec. time of the primary job (PRIMARY TASK ONLY)
 
TIME period; // period of the fault-tolerant task (PRIMARY TASK ONLY)
 
int budget; // amount of guaranteed capacity (PRIMARY TASK ONLY)
 
char type; // PRIMARY or BACKUP
 
PID backup; // (PRIMARY TASK ONLY)
} FT_TASK_MODEL;
 
 
#define ft_task_default_model(m) \
task_default_model((m).t,FT_PCLASS), \
(m).period = 0, \
(m).wcetB = 0, \
(m).execP = 0, \
(m).budget = 0, \
(m).type = BACKUP, \
(m).backup = NIL
 
#define ft_task_def_level(m,l) task_def_level((m).t,l)
#define ft_task_def_arg(m,a) task_def_arg((m).t,a)
#define ft_task_def_stack(m,s) task_def_stack((m).t,s)
#define ft_task_def_stackaddr(m,s) task_def_stackaddr((m).t,s)
#define ft_task_def_usemath(m) task_def_usemath((m).t)
#define ft_task_def_ctrl_jet(m) task_def_ctrl_jet((m).t)
#define ft_task_def_group(m,g) task_def_group((m).t,g)
#define ft_task_def_period(m,o) (m).period = (o)
#define ft_task_def_budget(m,o) (m).budget = (o)
#define ft_task_def_backup(m) (m).type = BACKUP
#define ft_task_def_primary(m) (m).type = PRIMARY
#define ft_task_def_backup_task(m,b) (m).backup = b
#define ft_task_def_backup_wcet(m,b) (m).wcetB = b
#define ft_task_def_primary_exec(m,b) (m).execP = b
 
/************************************************************************/
LEVEL CBS_FT_register_level(int flags, LEVEL master);
 
 
bandwidth_t CBS_FT_usedbandwidth(LEVEL l);
 
 
 
/* This function notifies to a primary task that the task itself has to
suspend its execution (the task has to suspend itself with a
task_endcycle() */
char CBS_FT_Checkpoint(void);
 
 
 
/* This function sets the checkpoint flag! hence, at the next checkpoint,
that is:
 
if (CBS_FT_Checkpoint()) {
task_endcycle();
continue;
}
 
the primary task will suspend itself switching to the backup task */
void CBS_FT_Primary_Abort(void);
 
/***************************************************************************/
 
 
 
 
#endif
/advdemos/branches/advdemos/cbs_ft/prova.c
0,0 → 1,429
/*
* Project: S.Ha.R.K.
*
* Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@hartik.sssup.it>
*
* Authors : Marco Caccamo and Paolo Gai
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/**
------------
CVS : $Id: prova.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 $
------------
 
testcash.c
test for the CASH Module, directly derived from Test Number 13 (D)
 
**/
 
/*
* Copyright (C) 2000 Marco Caccamo and 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 <modules/edf.h>
#include "cbs_ft.h"
#include <math.h>
#include <stdlib.h>
 
#define ASTER_LIM 60
#define DISPLAY_MAX 15
 
#define STAT_Y 9
 
#define INPUT 0.5
 
 
 
#define MAX_STAT 10000
#define RVAL 1
#define XVAL 2
#define DVAL 3
 
 
struct statistic {
TIME r_time;
TIME ex_time;
long dead_post;
};
 
 
 
struct statistic stat[MAX_STAT];
TIME val[MAX_STAT];
 
int n_stat = 0;
 
TASK hard_aster1p(void)
{
int i;
int y = 1;
int load1,j;
 
char s[2];
 
s[0] = 'P'; s[1] = 0;
for (;;) {
i = 1;
while (i < ASTER_LIM) {
load1 = 20000; //+ rand() % 25000;
for (j=0; j<load1; j++) {
if (CBS_FT_Checkpoint())
break;
puts_xy(i,y,rand()%15+1,s);
}
//kern_cli();
//stat[n_stat].r_time = CBSGHD_get_response_time(1, exec_shadow);
//jet_gettable(exec_shadow, &stat[n_stat].ex_time, 1);
//kern_sti();
//n_stat++;
task_endcycle();
puts_xy(i,y,WHITE," ");
i++;
}
}
}
 
 
TASK hard_aster1b(void)
{
int i;
int y = 1;
 
int load1,j;
 
char s[2];
 
s[0] = 'B'; s[1] = 0;
 
for (;;) {
i = 1;
while (i < ASTER_LIM) {
load1 = 20000;// + rand()%4000;
for (j=0; j<load1; j++) {
puts_xy(i,y,rand()%15+1,s);
}
//kern_cli();
//stat[n_stat].r_time = CBSGHD_get_response_time(1, exec_shadow);
//jet_gettable(exec_shadow, &stat[n_stat].ex_time, 1);
//kern_sti();
//n_stat++;
task_endcycle();
puts_xy(i,y,WHITE," ");
i++;
}
}
}
 
 
TASK hard_aster2p(void)
{
int i;
int y = 3;
 
int load1,j;
 
char s[2];
 
s[0] = 'P'; s[1] = 0;
 
for (;;) {
i = 1;
while (i < ASTER_LIM) {
load1 = 20000 + rand() % 20000;
for (j=0; j<load1; j++) {
if (CBS_FT_Checkpoint())
break;
puts_xy(i,y,rand()%15+1,s);
}
//kern_cli();
//stat[n_stat].r_time = CBSGHD_get_response_time(5, exec_shadow);
//jet_gettable(exec_shadow, &stat[n_stat].ex_time, 1);
//kern_sti();
//n_stat++;
task_endcycle();
puts_xy(i,y,WHITE," ");
i++;
}
}
}
 
TASK hard_aster2b(void)
{
int i;
int y = 3;
 
int load1,j;
 
char s[2];
 
s[0] = 'T'; s[1] = 0;
 
for (;;) {
i = 1;
while (i < ASTER_LIM) {
load1 = 20000;
for (j=0; j<load1; j++) {
puts_xy(i,y,rand()%15+1,s);
}
//kern_cli();
//stat[n_stat].r_time = CBSGHD_get_response_time(5, exec_shadow);
//jet_gettable(exec_shadow, &stat[n_stat].ex_time, 1);
//kern_sti();
//n_stat++;
task_endcycle();
puts_xy(i,y,WHITE," ");
i++;
}
}
}
 
 
TASK clock()
{
int s = 0, m = 0;
 
while(1) {
printf_xy(62,1,WHITE,"%2d:%2d",m,s);
printf_xy(62,2,WHITE,"Utot=%12u",MAX_BANDWIDTH);
printf_xy(62,3,WHITE,"Uedf=%12u",EDF_usedbandwidth(0));
printf_xy(62,4,WHITE,"Ucbs=%12u",CBS_FT_usedbandwidth(1));
task_endcycle();
if (++s > 59) {
s = 0;
m++;
}
printf_xy(62,1,WHITE,"%2d:%2d",m,s);
printf_xy(62,2,WHITE,"Utot=%12u",MAX_BANDWIDTH);
printf_xy(62,3,WHITE,"Uedf=%12u",EDF_usedbandwidth(0));
printf_xy(62,4,WHITE,"Ucbs=%12u",CBS_FT_usedbandwidth(1));
task_endcycle();
}
}
 
 
 
/* we consider the first ASTER_MAX + 2 tasks from the PID 2
and plot on the screen the elapsed times... */
TASK jetcontrol()
{
int i; /* a counter */
TIME sum, max, curr, last[5];
int nact;
int j; /* the elements set by jet_gettable */
PID p;
 
 
kern_cli();
printf_xy(0,STAT_Y,WHITE,"PID ³ Mean T.³ Max T. ³ N.A. ³ Curr. ³ Last1 ³ Last2 ³ Last3 ³ Last4 ³ Last5");
kern_sti();
 
for (;;) {
for (i=0,p=0; i<DISPLAY_MAX+5 && p<MAX_PROC; p++) {
if (jet_getstat(p, &sum, &max, &nact, &curr) == -1) continue;
 
for (j=0; j<5; j++) last[j] = 0;
jet_gettable(p, &last[0], 5);
kern_cli();
printf_xy(0,STAT_Y+i+1,WHITE,"%-3d ³ %-6ld ³ %-6ld ³ %-4d ³ %-7ld ³ %-5ld ³ %-5ld ³ %-5ld ³ %-5ld ³ %-5ld", p, sum/(nact==0 ? 1 : nact), max,
nact, curr, last[0], last[1], last[2], last[3], last[4]);
kern_sti();
i++;
}
task_endcycle();
}
}
 
 
void save_stat(struct statistic p[], int n, char *name, int type)
{
DOS_FILE *f;
int i;
char outstring[500];
for(i = 0; i < 500; i++)
outstring[i] = '0';
f = DOS_fopen(name, "w");
if (!f) {
cprintf("Cannot open %s!!!", name);
goto end1;
}
for(i = 0; i < n; i++) {
if (type == RVAL)
val[i] = p[i].r_time;
if (type == XVAL)
val[i] = p[i].ex_time;
if (type == DVAL)
val[i] = p[i].dead_post;
}
memset(outstring, 0, 300);
sprintf(outstring, "%ld \n", (long int)n);
cprintf("%s", outstring);
DOS_fwrite(outstring, 1, strlen(outstring), f);
 
for(i = 0; i < n; i++) {
memset(outstring, 0, 300);
sprintf(outstring, "%ld %lu\n", (long int)i, val[i]);
//cprintf("%s", outstring);
DOS_fwrite(outstring, 1, strlen(outstring), f);
}
DOS_fclose(f);
end1:cprintf("OK?");
}
 
 
void result_save(void *p)
{
save_stat(stat, n_stat, "stat1.tim", RVAL);
}
 
 
void fine()
{
ll_abort(666);
}
 
int main(int argc, char **argv)
{
PID p1,p2,p3, p4, p5, p6;
 
HARD_TASK_MODEL m;
FT_TASK_MODEL ftb;
FT_TASK_MODEL ftp;
// int i;
struct timespec fineprg;
 
 
//sys_atrunlevel(result_save, NULL, RUNLEVEL_AFTER_EXIT);
srand(7);
 
hard_task_default_model(m);
hard_task_def_wcet(m,500);
hard_task_def_mit(m,500000);
hard_task_def_periodic(m);
hard_task_def_group(m,1);
hard_task_def_ctrl_jet(m);
 
 
p1 = task_create("Clock",clock,&m,NULL);
if (p1 == -1) {
perror("testhd.c(main): Could not create task <Clock> ...");
sys_end();
}
 
 
hard_task_def_wcet(m,500);
hard_task_def_periodic(m);
hard_task_def_mit(m,100000);
p2 = task_create("JetControl",jetcontrol,&m,NULL);
if (p2 == -1) {
perror("testhd.c(main): Could not create task <JetControl> ...");
sys_end();
}
 
 
ft_task_default_model(ftb);
ft_task_def_usemath(ftb);
ft_task_def_backup(ftb);
ft_task_def_ctrl_jet(ftb);
ft_task_def_backup_wcet(ftb, 7000);
 
p3 = task_create("Hard_aster1b", hard_aster1b, &ftb,NULL);
if (p3 == -1) {
perror("testhd.c(main): Could not create task <aster1b> ...");
sys_end();
}
 
ft_task_default_model(ftp);
ft_task_def_usemath(ftp);
ft_task_def_ctrl_jet(ftp);
ft_task_def_group(ftp, 1);
ft_task_def_period(ftp, 50000);
ft_task_def_budget(ftp, 15000);
ft_task_def_primary_exec(ftp, 7300);
ft_task_def_primary(ftp);
ft_task_def_backup_task(ftp, p3);
p4 = task_create("Hard_aster1p", hard_aster1p, &ftp, NULL);
if (p4 == -1) {
perror("testhd.c(main): Could not create task <aster1p> ...");
sys_end();
}
 
 
ft_task_def_backup_wcet(ftb, 6700);
 
p5 = task_create("Hard_aster2b", hard_aster2b, &ftb, NULL);
if (p5 == -1) {
perror("testhd.c(main): Could not create task <aster2b> ...");
sys_end();
}
 
 
ft_task_def_period(ftp, 100000);
ft_task_def_budget(ftp, 8000);
ft_task_def_primary_exec(ftp, 11000);
ft_task_def_backup_task(ftp, p5);
p6 = task_create("Hard_aster2p", hard_aster2p, &ftp, NULL);
if (p6 == -1) {
perror("testhd.c(main): Could not create task <aster2p> ...");
sys_end();
}
 
 
printf_xy(0,STAT_Y + 15,WHITE,"Hard asteroide PID= %-3d ",p3);
printf_xy(0,STAT_Y + 17,WHITE,"Clock PID= %-3d ",p1);
printf_xy(0,STAT_Y + 18,WHITE,"JetControl PID= %-3d ",p2);
 
task_nopreempt();
fineprg.tv_sec = 10;
fineprg.tv_nsec = 0;
kern_event_post(&fineprg,fine,NULL);
group_activate(1);
return 0;
}
 
/advdemos/branches/advdemos/cbs_ft/readme.txt
0,0 → 1,6
This Example has been made by Marco Caccamo.
 
There is not a lot of documentation available, so if you have problems please
send an e-mail to Marco ( http://gandalf.sssup.it/~caccamo/ )
 
Paolo
/advdemos/branches/advdemos/cbs_ft/makefile
0,0 → 1,17
#
#
#
 
ifndef BASE
BASE=../..
endif
include $(BASE)/config/config.mk
 
PROGS= prova
 
include $(BASE)/config/example.mk
 
prova:
make -f $(SUBMAKE) APP=prova INIT= OTHEROBJS="initfile.o cbs_ft.o" OTHERINCL= SHARKOPT="__OLDCHAR__ __GRX__"
 
 
/advdemos/branches/advdemos/mesaref/test.png
0,0 → 1,373
‰PNG

+IHDRÈÈ":9ÉbKGDÿÿÿ ½§“ pHYs. . ÕtIMEÓ ÿÅ IDATxœì¼ùómÙUط֞Ît‡ï÷ûæîVOzjµf 4€(3ÉNÇ®Æ8ÓONŠ vå—üI¥R•TBœCBœªT\6B˜l™…µ‰žÇ×ݯß{ßáÞ{¦=®µòÃ}ï©5`‚ ¨ÜhÕ÷{ëÞ[ûܳÏޟ³ÖÚk¯uPDà­&ûkÂòÏüÌÏ~Ó7}ã}÷]AõÕîÔ_0yˎ·ˆ@)¿Ú½ù‹'oM°˜xžg"úWþòÖ öjŠ™ßŠ¶þ_y˂…ÀÌÌüÕîË_Dykƒ%D$ò5°¾
+ò–ë ¶ïkë«%oI°¾ _ó±¾ZòKäv ‹ˆJÉøµÖWCނƒŽ"""9ç”2"~Meýù‹ùjwàÏBP)¹m
+åk1Ò?oyëi,¹» üšƒõU”·X"p—%PJ)õV»Æ%ä-9è"€ˆÎ9­5~Íþ¹Ë[¬Û!*cŒÖú«Û›¿˜òÿƒóþÇú1øGk `Ü7¹Ó
+€œ@)û›Uà „_|¸ñµì— €òÅ÷:ßþâîúC„ PÁ~ЀH¢VÀˆ·Jî !Âz‚„PˆŒÖ,‚w¦Fö.€B`±ê+iäÎ_JRYw¦¾TGý™¯
+³ÞOÔÝs "
+@ÉÙßÔŠ²
+ÊÔN±zù¹§·7Ÿ7h꺑R
+>(EÎ9"R(Z"U
+ÄDR[hkMLT n”sÎJ(9ëF#’)•;[¦Ö¸B2o|‰DdSA"¡R ӁK­mmaS+£1„R'‘©ªª¬í©Ud Ð\i® ØJ9
+„ VZ‡ëÆ*«¢ä‹‚2†Drݶ˜eš³°(&¥QȤRäJ‰`¡"èKfÿÏ
+¬½™“7ɛ?Ò*
+ ueQ"E¡ÄiDA`ÇLY͡ԍžcĊqJžKªœA`d­8'¡âœ[/L¬B“àì£Odk•D-›V@â¶m9ykM×u)%f®*£AŽÑk*Æ؅s ç8禪÷›cÀœS¢B ,M»ŠTQ
+`Hkur¶5¦®êöÏ ¬7côfãµÿ¸7@D$% %x“zʁ)ß±–·ùRpÇxQ)Ä,̉øntïQ)lPR.¬ÂD
+ƒTUM¥0@Îe¿K–
+Bí
+˜8£«Ê#±Á„ì–m֜‘L[é
+5ÃnܬœµÊŸìòT<•“~K…D&d–£­QW(Z|Œ…8g,Ji0T$ÆbLÕ¶õ<Ï»'°TR[kš}Uk·\”qljÔ͗&½ýKj¬/‹ÝÖ7w”ŒhÄRÊ]ëFDDYC&–œ ƒòÞO>å\Yƒœ(6H9Î>(¥ *ÌD” BÐZ‹H¿ë)g\,BûŠÓ®xU öaB<=)›[7j73Û˜¹ªª‚bnË1R(…R@Î+F*¹¬W«RJˆ!ÇÄuUWm‰¾¤P‚ÏDÑÏÖVP(Ffkµ¶”RÊÙº…caUréû‘šºÑ bµʔ£¡…r,iÑuBُýj½ŽsŠ!H!%hµQPr)¹­¬Ñj³Ý8ÉRxŽá… 9¥Íé®ëºR‚ºqUs6x?Ž  ¦çP5N¡iºVˆ je•ÕŠxf‚‚¶ÎXìws!i«vÇq7)ÑõaŒR •<ù]½Ð­«£8Ѳ]TVçþT`}Š›ý§½W.ÌàŽ/tÇ~QFŽ,3e’ižÇٗR(ggµ.iö(”Ål´.”RŒˆP(ÅÛÚ óTÊ4MÖXcÌØ襤)¦ÄDܶ¾ïA Á‹à¼ f£‹Q TDؔÑ¥[…%†¼Aœ’ŸKÉе%†4ÏD4î¶J¸¶¦$M9Qaƒ`
+•Ñõªî,©œ
+°&@¥YJÊY!¬sÉÞS9D®juv6@TYh]kk›óæd·3Ö*­´Ñ
+!à4ŘÈ4Ñç¹$aîÚÖÙÚFß-¬ Œc4Ö± 6M‡Êìú‘YÖ«ƒâËöd@VÎãn¨šÖi•BúSõå0ÝýxW]ÝՈì×ØwE˜€CÊ%äbö>Ì1¦”JŠV«JcŽ³âL9aJJ ”S`&¢äý|txÂ^1d¨ªŠ™‚ÑÏû3†y†A£ò
+Å1šú\ŒB£tô¡ C)¨výˆ" pš§˜’³ÖÇ8oCôsÐÆ6m7 ãÙv×Ö5‘Œ£'A MS ©
+)öÞS!Ô*)SkیÉ07«&ÌÁƒU,‚ bʅX)]4Q™BÞöór¹œCâݘ2©
+­³µhT0úÂ,((Ä@"(Æd†$öµ[­µsÍà©[ÕsŠ4LÞԈ ÑÇ8ÇΚ£ 1ŠP5ËÕîx¢]•cÈRHXRÓê]ßǜ‡!SJ©ëLˆ‹ÔM—JÙn·Î¹ƒz(€ŠYH %ò#Kí¬ñO ֗¾Ü%ß+()¥ÄSJDB”gbHyò!Æ …r
+ ±˜â 9göˆA8Sb"@Ž!Páyž•Rû’ÖÞ97Íó¾$•Y`œF«mm,;žR?ö:f´±Àͳ @œãªªˆôœ2@KŠˆX €=ÞÌ9烃ƒ¦ZúÍF¿^™!H.‘mUK’ÍgæÌ
+­Ê‘´±ËÕ¡62‡b”b|.ÅÂ>¶]„Y!§ª^lNN6þXDT‹S?”$‰8‹Š1¹a$¥cŒ>„˜Ù9nëF”îÇÙk$U>ÇÖëP Œó¶šŽ ЅèoÛ¦Ù{K)f¡A¨äm
+d0ÛÊ{:i›ŽJلDÛd®ëåÈ܇ ´aÈ Žó\rc‹@zO¨êšõT¢@I)­í9ó¥²bçýËåMƎöʉJáE$çBˆ1–R„K
+Új;¦Pk$NÆ(¥ ¹U'3•ÅbAm¶žYŒs™‹¾l6¢Õ8Í%§ ±*ÄxôÞ: M,ºnF¥sάԨ´/d¬%m¦TI1gTi•)‚”%ø1±g9ÔÚZQz;{*Ô3dT‘yB¥@g–ÊDdÒØ6 2"²‚¢=hÕ¹Š¹”\°mÝ¢ûӁõÅhí—g9ç»ê*çœK¡Râ8îÁòއr)ÂŏۘS&gB )Ç(璓w*…™S0
+¦!¥È®29ǜ“±šJ™¦¡ª*£c.ÅÏsÓ4
+ZK&â£RègO…¶C4:َκÓÁaFŒ™mƒõ4Mû3Ÿ?wè ŸÚÖ JL%"McJ:ã¦>ZϹ€6퍛·Úv¡´žcÒAªºNbD!P)!ÆNkmm¦òڍ›G Gp·uÍC$2Z@RË ,!$Ó.O§4³ªêeT.$Ii«ØXŸ’P%Q–~j@ÅsŒJƒ©êî`í ‚³ ÑX³X.—MS˜•Ö¦­½S
+Ó<#'@ÛìbX,šÕ¥‹ÞOþ´¯—KH…<*[WÜDµZP@Œ«Û–P«œƒ1f¹\„BJ‹Å¢[,ú1Œ·¶»)Ýxé܅ 5Mg}oW hÿ°ÞG¸+w]õ/ Bw
+ªQ@H˜Hr¡˜bÌ9æäcL9©Ì£Ÿ#å)øÄäSœç¹L>¡Ì)¦¾ß¦Ñ[Aa)ª6c…Úšde
+#†’CàBV.êÎX+…„dŠ ƒ¯meZ=Ž±Bĺ®ÆœEÒ GªqÑh¸Ñ‚[]Ò¥ºfqìaÕ­¹…˜âŒº;Zn·»VE¨9<ðMM:MÞßbÊZ/¦äÒÑ;=@˜æ샤rÔvÔ4#¬§Mß×ΐˆgŒR÷ž÷ÆúiѺzšF£u1þyæ\_:P€4y¥Ûõò€D¦n=k%
+Ñâá•wsŽ³o«\cŸ¦©—S)(¡ÌFÝwoY.^öÓÄ<ÎÑ&Q¶™$Ÿ;X­zÛ­×^âeÝ‚9f¶­Œ}[¹¤øù×ßxàÝïcfÛlu2¢Öë~núpéÒúún÷ÒÞ7_¯zè¡[·n]¿~}Uw)#2.H'ÑQôåf1ª¦XkÚÏ®uzq´cëÐE\þËh¬»îÔݺõ»Á¤RJ
+)Ǻm‘­>wî܍ëoÄB³”œCœ'®ô–³qF4²”›Ó®F\¬W%Dh«ZFïmSS.§ý®ÖÖu­'Ó¶ƒŸKÝ4Ï.gý1£RvóÈ(®ivÓ¨S
+•'ÎeÕ-^+Eˆ‰|Š T1è›Úø˜GÉzÙBã"2—˜…—m­ëêO ÖÅÍîºSw=ª˜
+³¦œsˆÁ‡Sœ†qšç")ÑϳŸ}?O9 ³Ã8ÂÉ뮉)IŽ¢ÐZÛTM§“~·^­“°€”¥Ä"MÅV¢™(p±
+6U£•òeöTŠmÓ*çÆyY·ïzඪ¶ý®ŸÒMÛ®–\ˆs!æyö•s–0í|ãªÖ5n½X¶‹ÍæÌK¶UCsl–mÚ1DR˜A„Š˜§ ­vv‘| Y S·è€T µ\(†¦iÀYpFˆvó$’—‹EÈØkº«­Òu×Ã`œó9§œ˜¹ÖzêLjØ."œbŒ1èºY.”ö[Já\²6¬©l¥­æIçÜ-º8M”²Óf&©´‡jë KŽéâŋçW몪ÞvéÊf³ ™8³-,·=–9ÅÜv]eÝns¡,Ž.
+Ñà§?X{žnÇ<E˜9SÉ9çœïj¬œsfITbLsôÓ<÷ã0{ÏÌ$B(!§až‡yúq·Ù% Òj±\ÄL±p&6»ÊÚ¦²•®łœ²R­„,P¹ÊÛoz»X6u»¬ÛÆVã8ž½0¨BR
+•’KÙívÿ¿ÿûßû=ß½\.ôGôÒ¥Kÿáÿ0‹üèOüħŸ}J<@¡š÷ßøïúøw|ê³OüÿËO\Z¯ÿ³þ»GëÉÏh ù©Ÿÿ~ãñO°¾|I(w²Uö©vû (a.…r¡\(•bòÞÇï7ÛÝ4ϱ$Â0Ž»¾ÏÈ>„LT€Må|ˆ1¥ «£zÑíÂT
+Íã˜üÜTÕáúmÎÚ³ã
+ÓèCð>ö}Ï"Êê˜Ò<Ï)%öq
+^[Û¶m&PR‚×ÏNÞ؞úµ³½ŸŒµ‚ ´žü¹d*ž’[v©÷Y0 2Bˆ‰ÐtέÖk¥a±ê–Ë…s¶ŽÒ²·§ÓÉIÒZ
+BJ[¼+¾&1Ii2®R•5ÎTÚZ¥ÕÁŚH¬s ô4‡˜ÊüæÖIÉIJQ
+ã8ŽcÁY TŠŸfÜõ‚8ÞÍ%ÿí~øå×_ý…_øù¿ñWÿõ‹/l>û;ûˆÄ˜BJ¢µ5&û©ß­WTògŸüüÙv³emÈ)£¸¶a£tL)å„ZýêoüÆ÷ý›í?ü¿ý[ÆÚoyì±ÍnûÒSO^xÇP×µÄOÏNUšq6çòe%v_äc}Ñþ SþbªˆHD`a³Ùl‡~œ¦ižç9ìv;VÖøÇq )Æ~œ§©n›Æ8QYb’\6ÉRN™h·ÛicúÁLÞûœs™Jâbj'sÎ"1…ÆZM™R–ÆÙ¶ª4[2ŒI˜ã6N>QκrÐ8ö™f5)eÓ´÷8UÉSN‚Z)­³ÆYeŒ©«е‹f¢– IDAT±Ô¨.¬Wp°~Û¹óÁû·nÞ<¾sn¬n­qÆ´]§Œ9=;+1ÕuÅ,ÊÙ2û0LuUuU“­óPP´JÂèLgŒ!ˆkö[æ¥d­uL±Ÿ'VÖ`e0Î>Ŝµ«ÞñÎwV‹îc} ý ¿ôKÈÂDZéw=ú®ïüøwrçÆà_øü3¯¼üÒ}÷]ùà‡¿ážøì§ÿýïþøwÞwß½J©Ã4M1¥œs¤”³TJ;™ƒêÚèçÓí)£D.u×f¦~ ¶­Kʬ¸äœJ1•ûüÓO~{ü¾÷¿ë=æqíìG>ü‘k×®m¶Ûóðྖ$~ä‘G{ì1ªŒQæ7û·WŽþH°îRu#æ”Óݝ¾Û
+3)ƒhµÖÖ\½ïsõÒ>}íÅt—ï¹ò‘÷¼oq¸~öüó¯^{uÝtM7çøʍ7ú~èºVk[
+圸î. 목ëæá‡ßþØÇ;=;þ/ÿ»ÿö÷ÿÌ×àCÿÑßù÷¿çû¾÷þÒÏÖÎåX~ùŸ}òõWn…áú­›Û7NJHßð óËÏ>?ôۗž{á»?ñ‰«W¯þÎïüŽµÖãœ5ÕÊÜ{áÂ7}ðC
+ñ•›¯=þÔçn܈˶sJu¶úºw½7!>ùÌÓ]]G‚¦iLå2õûæ±üwέ>ôþ(¥üñw½ý* žw]HåÇÿçðýâÏéU‹¢^¼öÊ=ÝÿÀzsžÂÞäåœsÉ>„½­ !Œã8ŽãÊév»ëûÂ4 Ãv·E…óìSJژªm®\8ïªê•×^úátØ"[9J%¤˜J¶Ùp4Ð=nߐkE3ÅaRF¯ÚEÛ.ªº²ÙÇ0̛±ä„1]hË£¥±„•f+dJR‰€H
+j·«Ã£"”R  ˜Xˆ‹$³I¹ßžigÛÅâèÜÑÑáÑzyîêƒOÑ~~íÆE81¤’oÞ¸YÜ`AÍÃT×uœæWŸz®^/Cœ×M·²õåÅÁµÓ[Z› .P‘Rx»Ý¥T4B*̂ĐS)¥¼ôüKO?ûìoðÖññsÏ='ÄðŽw>²øv¹X®WK«µòó|zó8îÆ«<ô‘~ÝAÓþ{ûßR"W.\vÖ.—˺®µ6Z«¦iªº
+!Þºy³Ñö±oþÆ˽ŸyÛó_ý×R4ÇJ°f¬¬{àÂe·Ëw«`NñÚk¯ÍÃøMùèÕG}ⳟDZ†B”r.ªh…›ÍÙ /¼`Öݸ.Ýwߗ?ÇàN
+9 Q)D…8•s1Ìó<Žó<Ï)çqŽýàûÙ÷Ó´†BҐs 1ŽãÈÌm×vMsß=÷v‹…Ñú¥W^q'•C¬›ÆX3 îßqÎ {Ä^¡Ç7"t‹õásև|È2¢øƚºS®®–¬$ރÏD™™A$šŒ…}õ±Úç@µ¥TSc½h")9§B$Ä""À‚¹¢b₨4 ¦’ršæi»9{£m»ÃÕÁÁáÑѹ££Ãƒƒínwëôd˜ý'»©nÛ®=îÏ¢Åa@ã‰NŽ3SÛ4»²Ûmú76·Š…ûο­­»œ‹¦©,›•J>”œç~è§)å2õ£SFJ,M·HS
+!Žã¸ŸR*¹”” ¦¸ú¦ªœsËåòúõë¾µA"šæ*c;[Umc¨„m_bhëzÑAmœÐ̊ÎI]¥,èۏ-@©¥”VZïí 2bæ†T–êèâš1QÁ”SÉeÿäœC*6—”sN A@ˆÊ>¦Ç"‚˜¤dJq7œß8]œ¿ty}xxÏÑù£nyãÖ7óÉgnL±ˆ
+gߐA)Å̾ð4MÖZ¢¹âÔT®¶º2ŠSPh$—PŠµ¶®kT:&ãäX!†9”X4j¥´Æ"ý¶Ï¹ž;÷àƒºUsëôô¥ç_~û;®vm÷s?÷óϾøÂéØ÷›³aÿæüÀ¹váç ^:þ[>øá~žDä¥k¯\ö©º©‡q<\ÖΩÚõ9¾vzSiBa˒·Cœ£ r†át÷ùçžþà7}¤ŸÆ_|±ªêª®Ï5Ý{¯¼mÓïœ1WßõÈG¾ñËÃCDýÒõ×ë/߄އ«
+ñ~{&…C ý^Y;‡yò›Mï}Ã8ÎÓ8Ž9çív;Ž#ìŸ1Æq¯_¿NDUU3{cû”b…DSŠmëºj*wÔ­¹ÄPr.­ƒ +»lt¢™A3JÑ
+´V¦TN´VZ­µ1Zk¥Ð!(¥´ÖJ©}!†Çy€º®)»sçÏ75"ï :øn%
+1MÓ´_ÕïCŒY´² €V™T(yšç7nÞê–Ë˗ï¹péâÃ=|xîÜÍӓPò²jÀ(òiê{ç¬1V •ª’µ¼þúo¼ú†åG|Ìû‡6^¾|¹”rýúõ®[ø”±ÅwýØuÝÞË6V}ûwü¥¯ûƯ×Î\?=þ§¿øÏÞÿ®wÏ!>ðàƒ÷=üà¯üÖ¯ß|íÕ§ž|JP}Ë·~ë3Ï<3ŒãÇ>ö±÷}à“Àô~ú§?óÙÇcJÕ}÷ôÑ÷xïSH±”(”s%E‡31ÅZm¦‘ Î\>óÔ~Ûñ͗_~éÕë¯Ç’ØÏܬ–Õj Ö~ß_ù«û¶o7Z‡Rþ§ŸøñO}ö÷¿,œ¦‰™S¢˜bH)•4?NÓ®ïÇqÇi'fúišæÝØŸ—Rö F˜æ¹®ë”Ò8Ž{˜bJÎ¥”´ÖûõišêºZ¤VmsáÜ!pQ ~Pòª©N-+hŒ`IšX£å«
+y_*¨îNc8Ù¼ê¬M¡šFz÷{l+±wÒ™¥PùÂFgʹäcß÷ý®¿µócH1%F­´1Êè²R‰µuݲ{Ç;Y,—¦r>Å×®_æéôt3ûÔ¶-37MCDÞ{4°:X¤TÂäK,À€ öªhšæ‘GyßûÞÇÌO<ñÄË/<{õêÕgŸ}6Æh­}ûÓȋ×^×Õ«ßò‘æ2”Óqûò믝o*ԍ¶Ο?¼xá÷?÷Äk¯¼²lÚ˗¯„àoݺuõêÕår§éҥ˟øÄ'^»ñÆéæìÕ×^cïùÆoÆq¦ßüÌï>ñ̓fÑܺñƇ?ðÁÚUŸý½ÇEÔ#ï~×s/½ÌÀÎáÕû¼qýúÙé©kšÃ‹çÏ-V7^z…ˆºúv¬ëzÇÕzýÌË//þÓ_û"°v»ǔ}Œ>Ÿâ4MÃ8î†~†aœ*W]¾|B3MóÉÙÉgÿÌÓO?­µN)m6@¥´ÖûLŒýŠ:¦¤kçœÛW€µmÛ÷}NåÂÑÅE[/k %λSgteÕ²­ÛÚAXBe@eÀ6ƵbkÖš”ujÿ\¼ý¢[äý7ú¶¥tŠe˜oߧ'Ç?ú>g’½»4aÚë#b¦RˆIX
+û‹jWû•
+jŸLÆD€¨”á»*«”¢m[wçJÎ)MÞOó´íwǧ§›íf7g*D¨Ik´VÈ~ž‚Ÿâ4‘äÃo{ç£ëvIüY­õ}÷\yà¶ÛíµW^ñ¯Æ)%$æ¢ÓÎZ¢ßï¡Ý¼yóääd¯×«J·]ç½÷!Ló¼^¯A)ÕµÏ>÷ì Ï<cµjWmTäêzL“Óúðüù³ÓSp­‘BژåjÕ±TMKÄh”}6ìcðÑûãt#Šuî¬ß®Ž¬¶$p¸>êÓnµèÞùÐÛßÿèûžù¥'žnã{«UæÞû.7®ŠžxñY0fYwyöuÝ"h`Q
+aL0Á(BÆVǔpe‘&c\ðÀ!°ˆäÒ2Æ¥„ûG18g´1Fi¥”ÖJcP™¨²¨Ä¡ÔÕñ±æÄÄx’$+á`8èF…T€%` µªt֕yvùâ…l4šÝ·/®Õg§§‹¢èw»ép¨”ÚÜÜôú$
+Ýyìd¥ÙúÁ‹ÏäÃQ‹£söMM_\Y0EIbj²² £˜
+“Q‚cBüí‚@㜓Rú%xSí©"k(c‚Ѐ2„ ívõ`¹‰z(Bd©Ò9ËÄ0¢ s¡u3Œ1BØ9F©ßÀÁ¡xý§­
+qÁ1ÆÃáÐÙ#ŽS+‡´6Ji+Y`´2KÒ(vQTÍ+ùäXžæùÊÚÆêúæÖvßmю’4(Ïóþ(¹±²2>ޞÝ`ßԔTòҕ+›€1Å`¥¬×›wßvrj|"¥çΞÛX[¤¬UœÅÈ@ÄY-Ë0Ä(!È9)eˆl”
+e-çoVâ¤yžçy‘¤iVäIšfY6HFÃÑ0IÓÑh”ç¹Ö:I’Á`à±#_
+œMGC=FS!g¥”VËHð4I9
+ȝŽ†Œ1dÍ ÛqÕëõj½¢KF£ŸlXY‘’d˜Œ†i2LFƒÑ(Ͳa’¤I¤ÖYQ8ä8á^ŠÎ»
+sR!çZÕÚ©S'û۽ͭn¿Fá‰ûîÝ·o8.-/K«SU¾uª -v$I†Þ¶F£,Ï Y¦yšd;¬)¨(KPðû›½aÙ]7èœ ÃÐ9A¥R¯…ݍžÉ†ÍJÐ®Ä ³l”PÎaÀÄE¨Bˆ8K£]íT´;r×"»'üïu=ù“1r€•R¾VÀE῁Rš%i¯×«Õë„ÀØþK|yQ–åæææÙ³g«µxs]¿¶°oßÜì윒Ë\„¡”jyu•bR­Ö(çš8Ž £Š1RJkLEµZmb||©¾²º¾Ñë¤RÁÄ:k¬]¸~­,‹ƒ‡NO"ËC©Ô`4TZ—e©”ŠÂcìk(‹Â/ŒÁ`àóÔ$Iî¹ûîÏ|úS·ßþ6­¥ô駟þwÿîߟ¾ÿþÏ|êW>ÿùÏ?ùä“õjuvvö·~ë·þæoþF•å§?ýéÓ§OûGðòË/ÿþÿûǓ33¿ò«¿
+ÖÕ¢J£Vëw{©Ñ_ýêW·;Ýßùíߎ£(KRŒñF1üêŸý9ÕöŸýÆo´ÆZñø㹒„ÅŅ×ΝÿØ÷ÑÇ>úÑååå?ÿòŸŸ9wöãìxÄ{Ùõõõ?ý/ÿùåó¯NLM½%yOÓ,/¼£ò¬âþpP*Y;ñ‘(i­‚ck­–Ú»(¯ë;žÑl69çQQBòؚͅ V³Z**–ˆRǘlœ¶Èa„bÞ®º¹ƒÑx¼Ó²ÖA µÎË 9çb´§´æ½·ïÌʲ4ÆpÎcBð"/ŒÑ”Rkʽ¾¡^­ÅÝn×Çn\8‡BHáP\©
+Æ)〳ç™,2ã
+!AIGÈ9Áh†ÕJeaqy}cSj²Za¨”¼~õrž%·Ývg½Ö:2³}k´¦£’PĐô¾|ö…—ƒCyÙjµú裏¾ãí§¿üÕ¯\¾|ù§úƒþéŸùîßÿývg«V­<øÀéüþ÷ŒVï~×;§&'—ßóîw}ô#ù¾ðê™3¼óþЇÏ]¿òý§žúŸ~¡Q©~äg=0³ïñ¯üå•õÕs¯¾zôð‘ãǎýýßyùŗ8çe€¶ÖWÎ˜žh·Ûí>ò¿ûÎÖU`Í{ßó®±FM9§Ôé{ïý…Ç{öÙçžxâ‰|òé½ï|ç…Ë—ÞªÝM‹¢È²l8%YšæY’¦£$QZeE‘æY)wUD00ÁÁa)¥ŸøàcJyž{t2ŽcŸ"l÷{#‰ âÕ¥2”`*"Ë+@Àb§AÈ
+F°ÅVÛðvvÃrJ&¾aî÷ïsÎc9BJkg­Ú}ûÜjy÷5„·6Ƙ±ÆGY(oX¾CàE¶Š¢˜™™ñù™CŽx,µ
+£øȑc”-rŽA8̲¼‡³ss ’…Ö†RJ ‹ãj­V£xmks˜$c£ÁXpÖïu_yþ…ãGN=v̔2äÂ*¹Ôk<ùëñ·Ž Q…Ÿ£aŒ‡qßqÇÝ­­o~ó7nÜȲôÓŒµ~ðýï¿üÒK÷Ý{×ÖÖ>øS?õ쏟¹qýÚÏü1¥äW¾òå¥ÅÅ4Ïî½ûîÉ©É4Mo¤×:¢Š2¥g_9óò¥ JëÛNž€žþ™§¤µÆ`{}óøþƒƒþ`iqiöðÁ—_ziiii0èŸ:qrvzæÉxò¾{ïéw:'Ž?ØûÆã?ýôÓ333§Ž¯×j”ÒŸ
+³"Ïó¼ÌËd˜Ã</­qE^–y)ˆV&£$g8p”h
+
+‡©2Žñ°ÑÀJJ¥JÎc4Ã@0.è…ËW–ÖÖ­A4 µ¡4O¯\¾¤­9vüTµv‡Öv©Ó¢ÁXg4
+œµÆ¡ ”:甔aåiöŸ¿ôgþåÌïþÎï\½péÚõë—®7šæ õÜ />÷ ìコgŸ}öüÅK˜³'¾÷ä¡£G~ïwïþò_ÿÕ¥×(F›gŸ}îêå+ŒÀäÄ8— cJ(rî¡÷¾÷£iÀ/_½º¾¾îRZ½~፠ïø}_ÿö߶[c÷¿ýí?þÑ3ÃáЧ§ßûþ÷oûë¯}ⱏaø¹Ï}nkk ( bñVå:Ó$ FÃá(KÓÁp¨–Jù’ÕGw«˜¶sk@BXçXTêÁ–È2ÄdœÜZí4‚ A„ì]pÈù"ðæÁ½pvsšsÀçCžX’e™OãªÕj2¥iÒ¨7¼ì-c””þ
++•ŠÁ^òç¥=.ìCg’$£dT‰ãÑh4>ޞ˜h{˜ƒ‚€X FkB@©’|åê¥çž{îðþùWϞŸœ8|ô8••5]µ8ŠE5Ž"ƨ·zG@90¾ÙÝÖÎ
+ ÚY«e·»%µn6Æö˜?x`N9×ÙÞÖ ƒ àŒ”eYJGdIB†³ö̙3ÿößü›O|ì±Gzˆ ñÔ³Ï\½r•Á ?øñ³?þÐïþ.#øsÿå˪,ãV}m»ó•¿úK+õϼÿ‘#‡áϾôÔs/@·Óéoo÷kíh4rÖæyN)!&&ڙ,c½ññ( BQQJøÃ~øÑGï¾ýŽÉ‰‰}“S_ûê_ÆQèBollüɟüÉÖÖÖ'éo;uêñÇÿΓßMµ4Zÿ„ä=I³Ñh”eiQ–eQhc´5ތ|=¿‡)XcŠ¢ ”ªReQ‰ã0 ãjXäIÑïUmryŽÓ@„%@(ÂØ9ì[¿;CFö4'½áúÄÈ>`{ÀŒ1&„ð¹Ñp8œœœ¬T«Eš:çâ(΋!Ê9”繧."C»IL­^"°Öë¤I"K)ZÍÞhûèÔd£Ñ4|÷Ð!ŒEÆ9gýþK/½EA¯½öÚCÓSqQR.¯¬4ªÕj­æ8JET œ;tèhT©_¸tiayQM „(F£~ïüùWµQcã탳³`,ãüÐÑ#ýÁàÒÕËëkëÎÚfkl~ÿ~Œq–eN—`üú… ÿößþï/<óÜ/}ò—þég?{c}õêâb†Þ…ôºýÍÍJ­&µnOMNMO_¹|Y§ù±ãÇÿÇßüôÿûÓ'¾û$‚`†¡‡ñ8ù`(¥,
+ùÕ¯þåwžü{ˆRÊÍ­­#‡y2Ï /¼ðéÏ|æŸýÚo0Ɯ±W¯\¹çž{†0
+½ç´ì-êHÞ¦õneŽ1Ã!4”RzZEE¾í]E)%c<‚jµºof_E> 5Í0 0x¸ÕB’4Å;ë¬ucããƒsΫ•]5çÔYC)¾~ýêöööá#777§gfŽ=*„À0ÆkO0.&Â0Šƒ¨DÕ0ªNOO;rhßD›ƒÅβ X2ì-\¿6ì÷ZµÚ¡¹¹GßuÇíGªÕ*ˆ"#u»ÕºÿÞûÞ~ïýãͱf½þ ÿùN?¦é_í¯¿ø¥/ÍÏÏ¿ï}SBŠ<ïm÷úýÞõ7Ö×× @@èƒ÷Ýúžûdš÷»ßýãÿôŸ²ï~Ï»cmñhÙn£‚`L„‹‹‹—.]^\XØØÜôëÜ×I‹‹‹K7ÌÌÎÏÌ^zýÂúúz^äA¥Z}ä‘G>ö±Åqü /üÁüÁÕk×Þ÷ðÃSZ©7V–eišùñy–yõ<Ï}õça·‹æYcsÎX‚q­ZmÔêQ&›$ÏÇy#„µ!£17@q`rvLÊ7ÿÞH´ß;$»û}JäeÇιá`À9ã(Ë2C„/)¡µ@í‰öØØ£ÔƒòŒqB‰w¢ŒeYÊk)­ !1Æ!‡‚;°kk«çοZ«Wü­xÇ;lµZžû%„Ø7»¯ÞlaÊDsE ˜ÆÕZ­ÖŒâJ(¢}ÓÓ·8¾f&
+˜µÚÍ£ÃAïúÕ+ùh0^¯úýþàôÌÓ[Û[q5²Ö úƒ…ë7®\¾ÜítãŸøùO¼ï}—E‘§é…¢,i–YçF£Q–eI’ † 8æÁƒwÜslÿo~ýëßþö·Ïžus0 ”ùŒÅ_¶WoÑFSεVÞÇSƲÑHkí9>2t»Ý_|±WBÆ/_¸˜¥YžÆÙþpp÷ÝwÿÚ¯ý¥4I’­N§»½Mõ*o…eYyžE^¥’VÊCŽQy?á‘$„5Öû³3ÆÒ4M·»û[cUB@„aiµ2Ȳx7w~f8ðg·÷òVå;ŒØ ƒ1ñd˜½¦‡¢V«Y>%ã­±(Š†ƒ¡R2ŽãZ­^«Õ ”!çŒÆ„E Á„%µÑ†`W9¥$Ëó¨5›MOXÃÚZd0%œÒ¥âÜùsW¯^¾í¶S/¿üÒCï|ߝwÞ%æ„…bŒZ‹*•j‚'¤ÛݼtõÚüì¾F«%Ôæ¬G0£(8x”–eRt1`UËI–å*“§O?
+‡C')¥ ¡A §íf½‰Îújˆ6%Ô8l1ŒÎ4Ãغ½„éæAnviö?¸Ñû-ßøÛíî¯rAǔsÎ9ˆ‚0
+CŒ€Q¡¯þöܸ5®Uo8œ"„Ö–“óç®>ðàµz…à€P»ÕYþ‡ï~ç=ï~øöÛîæ"
+“áµk—Y(*µÆôD»74êµ¢(5„p‚±µÈ"”¤ép4²ÎY^«×Â(ocÆV¥\\XˆÃh~~¾Ùl@háFgs“267³o¬Ù £hu}-Ësk,¦D½¾¹á¬ã(G2+Ëë 7œsI‘úý½ùhmap n§ãœ ÂÐÏÖ[\\dœ,,• ‡ªÈ©8ça#Æ¡ðÕÕ­™>|tyyyc}ͽoß¾æÃ0Èó¼ÓëöFC„¡,K„6ȉ0¨V¢F­Jê4«
+Ν£`‹±%ÔŠ0~ *¼q’ÅŽŒé-©:Ú¥Ìã[fÍ{[ñ¿eŒ…aìšŸVê1Û,#„øñIADQT‰«Œ¥2ÆØæú@It×Ý·sN­A„¢K—^p'ŽŸTÊPʃ Ü!í"v„Âæ榵6KÓµµ‡zøè±ãJaƘwicÎ9£t»³ùÝï~§ÛÝ<tèÀ¹ógûýíÇȲ\\Z€z½n¬#˜"k¬Ra3!zý~2J1`Æ(!$/ò²(ÚãíƒTãJW†Ã¡*ËF£~èÀýs³adEfBxTªÕ¬ÌOÝ~ûô¾™~¯Õkõûî¹÷h·Ö·6G£¤R©œ8yâ®;ïäœoúÛýžEŽrAY…”Q)­)¥åLJɁ…qä*dY©V¥ÒžÌsò,&@œq–2F/eéâa@«Ök¿þØ'Þà±——:Ý-­Ê²(֖â8J³¬,
+ ¢0§<
+ZkÀöر£ss³/¾øbµZ?pਖØ!ä¯Á·öcÝNç©ïÿ·«—/ž<y|yé§À¼øÂsûff£(ˆã<¤˜ck±³8ËggfzýÑ(ɤÖÖYB vv4äÉpß䝷Ÿ8ùÌùsëë+E6Š?uòØÄÄę3g¶û=©‡ªÔq[䔔Ú%•/ž´Ö¾ˆ»²p½ÛïQÎJ)—–ª•êúÚZQ–Rëjµê5Ã@\‰ó¢ˆâØST€¶†NœC˜¼(Š²dœ‘(¹ËŒÀÄ9WJé{š!ã,`àœ ñ¢ßØD[Z…9¤iª¤”à ƒ8®‹
+XCÐé÷9 ˆq¢u±°F#Ä&  7Z•^{¾ÚqW·Hb|³íC›¯–ý¬s˜ǘRÊÃ)ó•¿RÊ7<2¢”´cËRyø-IÓR&ZÙ^o;IFss3”±j•eYfìV½^÷j`8§F㡇J’ŒQÎY¨åN)îÿ¢•••ïý·'_|þ™'Nlm¬¥Ùèرcׯ_ÍÓôÔ©“íñ BøhY‹ id6Æ:‹êǏɊâÚÂB©
+¬‰ÃIé§Z; À:d-´Ã#ö³Ówf¹»QøÝÙêàv:„;cэ1;ÌvÓ)B<Üï‘'ŸÖ8çœuFk­´sÎGÇ0³,óô
+Ÿœc)ÃHQH„0 „ ¡Îé,ϬƒJ¥@*Õ
+çÜh4€jµš%iQ–QaB¡J¥šçYY¨Rë 
+G܂$
+·mUÛ[ÝËK÷øٜs?ãJ…s!8wÛ] ¶Åã1Ãï<uÛäÄdÐßÞ\W²ôÁÔRbÀ9£µCˆX·orúm'N½¶puqqcƱgJ¶ÆƓ$µÆhc‘µ­Fóη½íâ•ËK뫾ÉF1Ás.´Ö¥”µ·i*Ë2ŽâãGOÔjÕ8Ž¥Tׯ_;{öl^J„ Æ~–
+¸(‹Â”9,õù6"`á&QÁÝba·Ê-Çšƒ·V‚o0£7ŽìñOÚˍ„aèi¢J)ç\-ˆBAÝiœsc,ޝíÝ^QªN§3 Z­6ñ”RF×66ʲtέ­­ù€ ˆ¼ÑʝsA ”Œ¢x~~¾ÛédY:¿ÿ@¯ß«µw¿ç½§n»=ÍKʘE9«µbŒíß¿!T©ÔŒ2¥Âi–u»ÝííN½Z9yüØ(KÖFçIrãê•Ûî¼ëøÜ|«:Üàp%®­7×7oìŒéðTf¥ÔÑ£GO>:ÕßX_ÿþÓ?Ô2?4à»ï/Šâå—^~핳gµÖZ’žos!„ön5g4Ïrì‚b0<|ààïüöoýÑ¿°²²â­OÕÓ41Z2ŠU)‘ss³ÓŸúÔ'¿ù­o­|㛜2ÊÙh8„(!J*Â(coIÞw–©R ì2ÆjÃ0IµF…B¨RÖ+Õz­:ô‰E•0b±nðçÀÛÖN#v?I‰!|‹ay—»ð­†å¬»kùUèWí^õw«ÁyÕóîÓ4B`LŒ5>ý÷`U¿ß[]]õ†%¥¤„æy¾µ²|ùê•V«577çõŒ1¾Ãè»=WÁ(ÅZ­Ö»Þõ®(àO<ñÄÜÜ\·Û)‹òÑþ̱ã'¥6"K©³ˆ‘’eQÚheÌV§síڕÁö6B&-òúXkÿìÌÆښ4š2á,²a%
+ëͱQoxñÕW;ýa§ßKŠd/ÑÜÉ;•VZaÀZë~¿ßëõH$Æyš¥iÚÛÞÞÜÜôgË\©¥¿ >§”ÚRɲ ŒRY¥§&¦}#د՝%Z–#«£„S
+Ύµš¡~§"Žã¼(œ¶žþV‹RJGÉè™ÿXk=J¯¾åon%Šf¦&9œmkt‘¦€a‚¤6Æ @Ú:Ë ØÜ»¶µWúÝ
+doC‡WŒã
+Î:gQb»ßO’Q«Õäœk­Ò4á<à"Ø©@€µ†bA %kµ³oàYZj‹0ÂþÚ)ÁÎÖÅ ¯]¿vuksSp…õn·såÒåæاÜY7&£A_k7>>GÑܾýëë[/_±Æ`ÂØh0ÜÚܜ™;8¿ŸÖâÅÕegœW+‹ÒiË0µÎi0ŽJ9„¬±ã@pJÈÔd»ÝžÖèÍÍõ²,uÖ:J(cœbR˜YÀË¢¸ôúë/½üÒCïyçâÂÂÕ+W<×HpþÈûßOéOÿtfjúSŸú•‡zèGO?…!Âä[_ý‹Jµúé_ûÌõ…ë_üâ«õ:ç¢tá7 §RJ!¸.KF ‚ `B˜çœÃP–e{[í¤MdÁ·)²˜`†ܬ r»=BB|n׏sÈYoÈZ„‘·0çސHì@Ö"laì,RÖ0
+Pj8‚’”±\J£”*ˆC[ Dð´¿æ IDATÊòâÙó¯J«Ód„•EÞjµ†ƒþË/¿ôŠ³£Œ`Çq„E^üð™g¾ö_¿Fûð£>zä0#$ä\–’p
+GËËˍññ²(ªÕj½ž­­¬:ʵ£´EB@ ­1Îƽá€2vpÿü‘C‡0ÆÏ?ÿü~ô#ßÐ *‘1¦Ÿç€\½Vkc‡[ŒQ«Q
+Y pÛm·—eÙïõg÷Í<x0MSBˆ¢þ¾Ñ°(¥A$ƒ~V”˜RŒU¦Ýž8tàÐx³q¶²p-ív¨3BØ!ì:övÖü„ãͶ…CœÛÁEÁC¨·¤VþÄX‹oæì7wÙc¼£áy2”ÒSJ `R(ä=­”µ~©…ÕªÊò¬(‹‹—//.¯X+…²@Y{jº^kDa ”PB5e,pgiêIϞƒw70îYó^‚„ÜZ»´´øõ¯?Þl<x`ksmey©Ùl>|xeeåƍûöí ÃðƍBˆ±±1_óSJ‘!AÈTW*•™™™åÕÕÁ`Àãŀ777××72g˲lT+e£&8oÔq
+.œµÖš0Š[ãcVsemuqi)͒íAŸ2ÊRmm‡Áh%n6ª!¦&&õºT
+0PJ‹,ç˜Ô+Õ©É)Np½R½ûλöïß¿°¸0?ü¡÷{ÛÿëÿùÎÿõÿò¯çææz.c¬W&Ûmk]œ‹£‡mÍJw3K~ÒX¹"/@$„l´‚7*ՙÉÉöØx™%Vi
+G‰Vöêå+ýno¬Ùrªì®¯… 3Á|*tÓª;ð>l—Íþ˺ùln>ßÕq€œÏè1Dêr;Ÿ¸ rbŒ½XƒÇu¼~Ä “@0ᜋ@XÊnc½»²¼Þï+ÕPÊ´(ˀq‡°”zqi™&”2*D€1„a(„hµÆؽmû{&µ§°p‹aYB€FÑ}÷ݳ´tcyeißôôö֖7¯V«µ¼¼Üjµ~øáƒ×ëõ~¿? ¼|&e!Ä9sªÕêìììòÊÊvš˜Bb‡2 ¼Q¯U«E‘W+xØïk¥¨W—#D+¹º²²¹µÉ¸ˆÃpnv¶Óë'IâKÂ,Ëc„àj7ëuU*«5ˆÂÐÇ)Ӕ:c àPFðÝwÝÙjµœ³ý^ÿëßøÆ¥K—{ì±0‡ª×ë~ Ǐ?öя58ŒÎ¾r&£~ðƒŒóþ7Ó«kKozþ$k!g)BBJiJi¥ZwÎ1ÆCYZfI#Ž9%Èh Ôbì ÀÎÿC?ÉctÓcíþƒv†€ý „áÖ÷x›th—•µ÷%€œïäøîÍÖÖÖææf?+”ÑcL å<Šã 0re¡”2EQ¶Ûc"dZ+„€ ±ov?c¼”
+tªß}ïk_=~2Ÿ­âÒݹs÷;ßùÎÙٙÖÚ:n¬ˆP1€³6iêêZIH7,†§‡'÷>$3
+¬›j=½ü胯e.泺©ƒ"Ë. Ëx~û®µ6ÏC]5•«¼”8îììóíF€ç|?ïé$eF!`nŒYÌ˲ö!H¢³£ã~ž}õìñÿ?ÿ»Öé;wHŠ'ϟMó/_>ü?¾:;:Šâ±!xdøë¿ÿŸ_=}º)«ª*Mcnœßúów“ Û“7 @&R9ëLðˆ˜·Ui½ÓZ“ I¬´ Þ *ä½ú^äé]Ï Îèĉâ
+ÐN±â)‰<ïnéîv»”„BB`Œ«ê¦¬() BLÆ£;wîܽ{7²>Œ1„8î{Öpµ)/^<Ët‘& 2ƒñx49š4Ö1¢gOÎ"K2­Uš&ñ¨íLêÊAgaà™£Ü¼s¡×¾ÿþGWW¶.¿õ­o}ôÑGÃᰭӑŠœsÀÌDÎ9•¦¤ÔÚù‘„ÄŸNŽs7¦‰01³¯6kÅAªd%•I‚EWm«Çϟ?{vñübFÈ£á@'R’ˆÖ{-Ež$"¢€LZ§yVx‚` ÌUÝ̗ËiY{R%³,˲T%j¶˜'B…jg¿|úxºX£aY×eYåyá}+fë/ž¼x~1ŸoÖ%eÖëé,…`ºq¿§¯g…Ƙª©PRäˆn6›~¿ppp0KBޚºÙV ‚øºªÈï»øuºßÄkÀÝסCS»ø,bWËåz:ŸyïIIçBQÿéƒ?ú³o'B1ðê÷ûyži)½Cï0ÍsÇÁ«$aæ^¯‡DuÓÈDÇò‹Ú±¾ªªZ­V/^¼˜L&´”Û7/Ø{I‘ÔÖµnÇžžžþàÿeØËNOO1‹Å"jïØQPkµ.//§ÓËÓ“B
+qrrrzzòðÑ£ˆç!bY–ëõúp4ÖZk„Mc®®®æ‹…±Ülø捳Û7o¨D†à˜G ÄYDyžçY_s|8ëõz:¡„÷aµZ‹üèð Y¾|ñl¾^>}ñbUm
+!„çù»w•À²®Mc„P.0{Ç( ÆìñúüóÏg³«¯øáx0”BJ!-Ñh4ºuûöWÇ¿kvÓ«éÑá$I7u$"‘: Î5Ö¸àن¼HT’$iª“$±¶$Ė=B,†FU°º®“aî¼3ƗˆBÈóósáÙô
+´äT-êreëUµ=>>î
+OON‹¢X­V•õÞÏfÓ(š%¥ŒNa“êTé„=ÇF!j‘«èn£ü3a,TÄ~n­u¯ß¯ëÚ5Gãq–èÒÚÍvë9yÞ+
+‡Ãxu³{ûb㼑‹ j­a·­ãïú(­ÀŒ™H¶Ÿ~ú駟~ºÝn[çŠÛ_ É[…03‚^¯;!„¨ÊjµZ‡ˆ-ÏGI•å¨śí6Š1xgLt$Ñ}î4Ì!úª=Ÿ
+Ƙ¦nØ9 \WՋç/`·nßÎýéjá­»œ^±q>õûu!Ñ ØÆÄÞ|!"/ášË‘eY«DZÇc£"
+µ›ÊlVh+©o‚G)3¾µ,øŠä·g6Й0¶±¥,Gÿ÷#†Ø€È ‘=âr»Ý4.Šív{÷üæûÑ_¾óÎíõjÌi‘%i"¥ŒpÌ%‡“$qÎ``bðƲs©L8ØÁ`PEt3DT7õrµÇñ迸¸ˆ°Et“boœXgî=qÇx~=¨ Ñï½ÏÒ ®®.þ¯?ý_?ûé³gÏÎÏÏÿòÏðõ¯]km=7$Œñ…ðBh”7NϾø⋦i„L¸5õ²ÚžpÀÀèC¯(jc2…ÀÌB$ ÖBpA2£sž¬³ ^%$ Ðyo90¡H”³Œ!8Ó8ÓXd\Ti‡LL«åŠëU¹Ùø²B;JZ•×€b% °õÞY‡ ®1J)ã\míIfÏשÉiš’$ãBòÎYc¥yš’II@*ïØCWï㷁 oý
+¿fU­ îútÚEzÅÒzU?Á£¤( î¼wUuxtôÃÿú_oœyë€9˳xî¼qà‘āØGtcÄÕ+zãñ¸1&B÷SA¤µöÎ/‹“““Åb‘eÙ.öUØÏLcœ´oXÑMî¿øèf¤”UY~ùèу>ýôÓËÏÇÃýÅ?øàƒ<ÏgÓ«²,=‹Ë«i¿ß?>>fĺi<30ƒ^¯·X,â
+–«UUÖ €Ù9ë9x瀄@òƙº­¥ RB 3Æ£3á­õΣ ­µ"º g€YU]͖sË¡4ÍÅŅ'PZåyî¼o¬‰“
+æ‹ùzµ‰Ób¢’s ѺøšÇ’ŠA¢$ĺtι<Ëó<G×HE"P,^ûµÿÈõBŠðÊavñ
+ì…\¯Ì‹9Äié»F€oûÛßýîwÑz½ÖZG èêÄ~7 £õùCà]¯%'JMŽ&Ãáp[–JëD)ǐ$É­[·œ51‘ŽÑn÷ÂZm€ˆ1±êx­]ØN»¦mÞUŸ¼÷=úôÓO˲ì÷ûïÝùÓóӓ££‰RÉz½Ùn·!ø2ê™o·[ï}Y–eYj%´ÖÃÁ`¹\:ïBXÍëå2ë÷”¦i‚ó‰Þ;/ ÄQ¸X* u]3s¿ßÏ"Làƒ±ÞsPDÎXkŒJ’¦ª”R’Te³6xÏ>Ô¾ª›Ú#˜¦nš&ë½¢UûýÚ×U|@€8e-²bá(v^Ä1joV–„ŒÒû „R4MÓÔ5°;ړìĺfUÐÆæ×2ˆýh&.’˜WÒí~øá·¿ýí¨Ôílÿ·âZvC ¼w»û´§Õ`0˜L&Zk"Zë˜H
+©µFàõzñåˆÙ@wv¥;õâçíMcÞ0¬.‡üq\EÈÈÁ9ï#=L43;Ï*ÑP×u üs¦.™9¥ñÎEð¹©êÍj¥´FöA
+‘¤ÚZÛ4•e‰À;cLp-&w29JoÜDĪ®MÝb@pÎXdˆ£b©”@[WÞÚ¦®Áï=
+»Ú5§ÇG¬¼­
+tç·»1ÜËó"%FÄ󸵬6à/w‡‘õ†ÁêTß}÷Öd2
+™y»ÝFì’1Íf½vBÖö.¸¶|O¢^Á®ÀŠˆDM òâk‹&ßQ·6{Ùtƒ ]”-f„,K•RÑÖ)ò
+½·Îzfä}‚P*ÚA8Á^SM–iªjï$
+Àìêª\¯µ \nÖ±;숨Èò4ÕÌ!¾6±'nà ±|×#bîÑJ"èǀǣp6›Eƒˆ‘ß?ˆ»5F$ï_cq”u¯*ŒËå2Þ?®ML"HFDŽ º`}ð!x!´1I´ŠÀ2D6|è¢i$ÑåL1Gf @¥{šÀ†LðÌ!t4'I`gÙ‹Á9R² D€’P’u–˜ƒ ò¾µJX 2®×ÛB$R(‰@€“$8•@lÒ–°'®»¬˜ÚQ‡2Ī0bK!m=0 T‚B $§d"…ÐZÇȺªê.ˆ€.¹efç< Yã¶Û²ª`R2k7ë±?”À³£ã$MƒEQ ‡Ãè"“•vÞ(Æ
+B­UG
+Àˆ´Îº°MvßbDˆ­Ðoœ'í ‚ ÁyD°{ßiµ<1HoÕ}™¼$%APpÖ9v¶aöÁû$IH\«®W%@­©+[¥Jso="N”`ŽŒ<Ž´vcî"Ö·^ûF°;1aKµ ~vö×þWU6Mð`<Ž¥È8ØKA­# q(3"9K!ðfcÊ­sbd[zcúy¶çŒ!yš•äy^–åÓ««ƒñÁÉñI¯×»l6›M§Ó4MgÓ˦i†Ãáx<®ª*΀˜ÍfϞ=»¸¸€ù|þøñãív3ÄXGÚ>ð+•€Îl)†\ØV¯ vþ©#3µŽ‡[NUçð8x@’\)4e£
+î@¿«/ŇûÊ®÷–[v×r(Bà RÆÖ/ã9
+ÌaçÀ
+=°pŽ«ÚéܽÅce遭+ÓÔÆX[7~蚦©·¥NJ‰Ÿ‘Ö+$Þw©8D’Õ[c,"ü¶ê~ÀöŠ<íVŽ(yDz„€ xâ ¥,ªÒ/æeÝ8BªÊ­‘±i›¦ … º2Æúùr¹\oUðP×õfµ°MI2U%«í:-r@2Æ̧³Ç_~y<Y†Ãêً“ÉÄ{ÿþýÓÓÓÉdrqqÙ4õh4Ún·?ÿùÏ£@RQËåòêê*_,B´*Þûñxüãÿøæ͛e¹Yo–Î9æ$IÔ@ìõúÌüøñãétöòåˋ‹ $!`YVŸ ¢¯D§(vS¥”J‚ÒIÑëYï·UÙëõ>þîÇ·o¼³¯Ž ;ZH·Ï»Ø—wÝÀ¯fÏþº/ù`«ª¬ªJ
+sH´žOySVÖº€äB¨ÊU
+ëà}ªÕj¹xçæ-[׶1:ë'Ig¤}Pó IDAT“€à‚{ùò¹ÖÉG}´Ù¬ÏÏÏÇ㑱4™6M3›M#íäìì,V~ò<¿¸¸(Ër2™D^$½üO¿÷'~øÁ|1kLåBE1 tªs³Ù¬èå³Ù|r4Q¿Q›Í˜„1ö€È’ˆU#Ú €1³dLŁ‰Dë$ÕãñøÃ?üÑ_üx0H!iGD¢6nEnÝPÏvϹEÒbô±ïÍ1@X.æ³ù÷{ƒýx£;—cÿLc­‚¤ð¬s Õj½ž?zð¦aiv¡*ÁY+<IÈD2Hó&/¤ÒÌÑ¡°(< ÙC§k°ûè¼{e,]Ê·ËØß&Þ8=¡M0#î¿Z­V‹EªõíwnþèÇßÏ´&âÉáam,Çãù|~yy‰ˆumàñ“'«õÚ±Ÿ¯–OÖª©kL"ziŠÎÖÞÛ€HÈ$ËOoÝ}õàž¤ðâù—ïÜ:…ДÛû¡RˆˆËÕÌ{r:™Ïç—/^ó~«°ÈBè÷ûBc} AeµÚ”ÓÅúEí™ê,Éb$·Ø.Ö/×e¹>½÷èѓwn¿û­¿û«_~öòéó]úF°½uþfw”)¬We<"gÍì¯ÿúï8Óþƒÿ’ë”+ `Ï!ƵƘ®l
+Áê´xï½÷>üê“O~zqq¹Ùl¨…îà•¹ì¼Tlèè(]ÆÀ;ŠlÔS$,<üÕ¯?¾÷ÇßÍó¼óX¿û|öãƒI–æeS7¶&ÈcûÝou~ñ>uSǍ÷šaÍ×KÊU’¥BUUH‚³ !PHB ÀŽƒ‡ø•aÁ®¦œ8Ê«™mT€-Š¸+3Å/wð 2‹hjB4¶Õ¶iª§OŸžŸœ zE¹)+k»6.9\\\Ü¿÷EÝԉ£A¿®¶y’ {=…D€¶m1PιífíœK¤X.æ:QiªY¥„ÀÞo7kï|š¦åfcëj³]Õuµ\®Á;¿^/Ê
+ò¼0¦vÎ:gŒ©×›UU™à="*™L&Ç7Îo‘¤ÕfÕÔÍv½ŽÂ‚Þ‡¢èFýùl©“´©~ùðށ‚ùu–N|2€pxrtttôèáCϞ™Ûj${„BãÁÁØ:3Ÿ-˜¡Z¯ÞûâäÆéÍããmUé,c±Ç=¼n¸WÀU6À¨|Fq“(©—ú`7$€:e¼·Vð¡ns]ƒ´d×ËzR·.x¯3¥E)—Ö;LH @öˆ,(0ÆIô…êD¨×·x2²BB`ÂNõ€ bµ0D,M‡¶M
+øÊUiš\\\<{úlôÁ‡‰H¶uBˆû8deY~ùè¾i¶x¯ ÆE~ûöí›G§
+…ªf€™ÖyžVeÖ4ÍhÐïùp8BɑÈÂj1÷E‘H¡
+¥SÌòžµ1FH,úí¸ò,×E/ôƒa¯¬¶ue@ràAo˜Èl:»¨Í‘”Jtšã¼÷½bH(­sÞ7‰‰àLˆ¥½7V E"oÿÁݓóÓ¯^>í \͖±C>@à¸Þ`üßxWeêù£—Oï=©·U9ŸÚ±&á)‘,fü-ñ´ð4Ân[ŒD HADXH“µMc7B°‹„‘~ø&„ADJJk®Öz½ž®Ç"yïëªÊ… )ŽÀ£6˜ÇáwaÓ[ßÃk à~ºÿOA½­qO2i%Ó4ÑÛíöòêŠ?€¼×ۘŠˆò<oš&Ò>§Óév»å=Núd2ù裏ÎÏÏcÎô´ÖY–Ÿ{ï‡Ãa4Šxpôz=DLÓÔ{oMÙ+úyž÷{cLYUiš@Ó4Ö¸ºn8@“›A¿¶†7›•÷!:§ˆ—E€Rª,-U×µq!XKDÖØBš¦Óæëë˜F£áååe–e“ãÓ¯¬_,¶ž= î÷‹ÁAÿäôèäôd0|íö¿}þÿþßÿ÷þüƍç7âëÌ<í1÷¯_ûQ
+ò ¯uŒDRk¡”ÎÒ|>Ÿs@¥ÒD¥B"E$»ÐG)Õëõ†Ã!
+v¾ººš"R‘÷­µÆØ8d/MõF
+ï}”ò²Ö^W ÞEaŒùÅ/~‘&z4Ý·Vjé­ïõzï}íÝ»ð
+ƒC‹ù|µZE¿¼¸œÏçIQôÅÁѨ7ìÉDnʕ]ÚñxœeéùûgßûÞ÷~}ïӃÃC­“È¡…À]iä-^ñµzõÝëṐq{k­V'mÿ–û˜ª~‹Td¯×WJŔØ{¼g¥”R*ÐǸ»µ—Ý!¸{it½¬ €Ñ?¦8÷±•R&"ˆŒ7)âp$)!2AHJ%ý¼·)·,D@x~ùòèÆéÑpÄ!ÄCg:>þ<„%\ò</Š¢(Š““ØSv4ÆD½
+)b¤i@„¦0v,Å7ÑÍÂB(©Ø9À"¬«˜‘&$¢މÎÚ(ý°X,['I²Z­­1ãC!¤gŠPèŠ0Ïsh“phêë֕fÙz³€?þøþoî]¾¼LS
+ûãþÁÑáp<̊t¶ºš¯æ½¢Ð;<¸}ðWõWßýÓo§µÙl³dˆˆÖ[ ,®‹ÿvÛzk¤Á¦•72Rñ®_2¶&úk¢ ·nݚW«e]‘”R¶TC!„PJ#I!‘‰BkP]Qsÿ£ˆÂÚo¾jÆMÛ©_݁ñˆ‚â(0„(ÅF”ÉÁ6ΪD-×믞<f92{ï///ïÝ»‰.wïÞí&eFºUÜ¢•Êoˆ’Åvœ>ï]ŒCŒ1°C’¼ ¥‚ƒoùBž#Ñ»à£X±$ASzæ][‡ÖZ&¦Ùáá$Ž@W*±>€àÍvñôÙÓ(?,¥Äæ-ëÙ|~|vZUeL{Q`¢“^¿7>ݼ}+ë§óù,QêÞ÷¸äÿü™Ü§÷µÝšoþ‘Šú¹R„#òw:­îöÁØÖÈâKuŽ#o‹‚–B^?´äv»f𠜤ZqÒl›ª±ŠTåüŠ›ƒŒÐ1¡P"5 ¸3Ž}ӊRîÝ{h?!äÀm]ˆARdÌ·Ýp„RäXI¡„ˆ
+“Gb%“^Ú/N‹”ò^‘-gëËÙź\s€zm./ž¾8>ô%¦B(ë\(q¯ÿeßz~¯©Å‘¦J
+†­Q`nšz7ÊÀÇÁ{ 5Ê¢(BqXµ”IUUUՌLJ<¸wïJ¤Î´w¾iç!3…¶Ì±«I€ÎÒÁ¤wûöí[·nŽÇ1Sùèÿðød2ßÿƒ÷¥ÔθAt~vûjquyyqqñìdrB°†~GßYÕïv`Ý{ïãHÇ=<2R0Ó$iú¦aA" Xßx‘$$$cEOŒÆ‡[ç¥RJ
+_Ռ,[¨öõׄ-Ü°³'l͔¨¢ˆØóÚIŒHR Ü±CD"S©¹Ü¬«ífS–B''7o£Qã‹ç//ž?zxx0V«Í`p0•e¼­kCBfE‘å}AÒïÍgYš¦i›H_÷Xaù*þØ{Ö¸«ij­csf¼[ìÒéªéÝåCˆ’Q«Õj<GPJ靑Bõ{ƒ'Ÿþò¿
+҉êÛ7ïTåçOž>šJ•z ‘7~ݤÞøø;Œ¯{Û»i¯L ®ê,Ëß4,ìkJí:¸”R¦jÖëµj¹©h[êB«H¡Œ§~Ô mƒvD±¿í B’‚ÚÚ#±@"D‰ª;‘2!’D((Q¼_¯W³éåf³rÞ{ÂM]Ý¾„Øn—Ãá`8gYV×f¹X#$išIæFÊ$ª´;¼€^1Ùy)×\Œéùu.¶Z-*þdôRñiF傪ª¢æ‡sQ
+@ !цpuuõ³Ÿýìôôô[ßú–”2Ëòí¦ÜnË{÷îÿÃ?üÏ/^23 H‹ìÎѝ¯ôõ<ϧÓé?ÿó?+™–ei¬enõÃÒ4†iš‘R`QJòŽ¥LbåLˆäð`2?šn·Ëårz0:"p oiR~êð÷U¬;Ï´OˁJ €¨ÕóšaQOK¥Biœ³ˆ”§™©Ýf³‘EŸ‘Œk|P
+/j‘'*¯êz]¯,yÔÒÏ Þùz³F¢~Þ;:™¬7U`(Mpf³±Í•Öio8TiF Øc°>˜óòž5uÝ4¤" ±±§ÓVèfÇí?bÂ×ÎÇ´Zg€!8oªj«A‘9… VœÞÿý[·ni­•RÀø䫧ŸþòWóٌ•”Þ{AiðÕã  ¬qôÎÝ;ÿ‡úgŸH©ž<y‚ ]`ë•Lc(ՅçPÕõb±l6u®ò~ÚcÌ%JoÓÃÞ¹ñÅŋT?»yC Ë ]™XûðZµ8¾ÓèÔ»”^2a\úÐÌæ——‰N‡ý‘T*QI¢u¦õÁøàMÒA¤R;Û$L(X»Y®›m•)=й P5v˜¦€€ZäH(L0'ä8ÊKÄÎ!8/””J¢ dïÆZbIJ ÷Ö90ˆèQpž€¶›í—ɼwçÝ?HtV7~[5Ö9$®Mm¬Í§Þ³:Ï{q9›)­µN]Qò‰¢Ô¥@Š¸¿N°nŸ&bt$Þ{ç\´˜<×uõôéÓØTÈišn·ï=ýŠqÁŸÅšRUU¿ùõÿþo¿¸ÿ~ð!øÐ5=gEá|˜Í‡“ãO>ù×Õ¦ú³ï|K'ɳ§OÜ¿Œãñôê*Ü ˆâ½»ï&GI¬„<<œ¨1õò{ïv…W™¢€DWýíl:-ËMU¯SÝG”bŽûÄ ùGyrû.ª{,¼w•åöùó§/_¾œLŽ&GyÞC¤PÇF£× k»XJš1T•0žkÛ`\½®2LPˆùv=,T&%¡#Dì‰bO"´ìŒ$ˆ‘&€’ŠIyð!
+­}GõÆÓ´Ö$Jᮼ^Z¿sîôôt:>~üD‰ý±ä‹¢ðRê4]­VDâêòêŸþéŸþíçÿ^×u—9J)µVU¹Mól¹œo7«“³Ó_üÛ¿¦àß}÷7/^¾¬·år¹,úE"51ŽRÎ§ó£Éñ³óLêN6"bÞ"IDy^L&“ÆTe¹•"ˆ9@
+ì "Q
+q6½œM§EÖÓy1‚ÇmYrÞ«Ëf1Ÿ%JND’DÜ¥¬ªõf¶-ËñÁ±í¶ëR›.UÞߎñiò[$kCÔ
+ã@÷”Ä·„óû}AûdA¶/;Ï{‰¾ ŒZ§DÂ;&"oÑâéW%{ï°+›8MS¥´i¬³~|p°ñMÍ!´l$µ*!’Qpû9
+@ë€ ì¬dD‰
+MÝo[¸¿GL!º–Xp”RÎÓº®G£ÑÁÁÁÓ§O«ª:<œlVkˆ‚q˜êÕÕL%iUU10 Ÿ~úë«Ë+nÇеJeÞûÈ騷›þh$õà‹{ï½ûîÇßýî¯~õ«?þøßøÆÃ{÷‹EU–?ýÉOïÞz÷ý»ïY¯ÈŠD&̾kƒæœ‹ˆÎyD,ò<I’Ùìªß_y!郏ñ%FHýÚQعÞÎ1óŽMÙ9ï]ÆÎyk}ðQ!†Bpo)!ý¶VRJï½ڑ7. õI'é[·–¹¤r…$‰‚§8Í«=
+®c »ó´=^÷žÆ«~*@%"6uÎ+%cYNì†k¼fX©”€¤uºÙn„R!PU•¨UO¥y–ŸÝ¸Ùï%³¯²ŽbÕÆX»ÞÕØÝùð„€*IP R¬& ¥U ùFæ
+… 'Ož|ýë_ÿå/¹^­ÿøÛ¼Ýnÿæoÿ&fÖØÕb¹]—ä… ‘´§V¾&¢Ì(¥’RXç‚E‘F£¯¾z,„èõ
+Â(¬J°#‚¾qÅ2”ߍPÐZÓN¡dC†àE¼ÏN—Ú‘hG½i¬ÅÁ¡Ê8kÝÿÏ؛5Iš×bîáñ­¹UUVU¯Óݳ÷`°ò‚Øš—0#ïå¥ìJfzÓ/қL¿B÷‰&M&Ҍ¤¡ b#H3ƒž­÷Ú+³rÏo‹Åõ™ÙÕË@ȗήÊÊíóˆp?~üÓ4µ"²e™& 8¨J3›MSMGê\Äi’K']¡$j”Âc$c…Jy¯5€BÐÀš½VÌYƒ7]©$‰)
+$jҊ”bÔ¨b]4ÕÅdì<
+'±$µ·»ÛÎÚy’½qýÆN?kw⬤ 4>蘡Œ´Ž’4k·;;Y¾•·{i֊ãT)-•"ÁŒì7üBÀ!è)8O²'DdOBcÚ¾\.<x°³³³e/˲€/´Z­ÙlÆ̳éÜZc­Cä÷ßïììl4i¥˜]]•$€m¼óBÈu]°Ò{"ŠStÆ ¦Ùdæcyûí7¯ß¸>™NËÅroïãßüV(©çcw¯[ˆBgZ
+AMQ(ÁˆEY•e§iÞjÅY§±’Qdy¾³ÓßÙÞÉ;E€Ä ˆ(µŽâ˜??ÀĊ|h¨b—¾x ×¢.›Q>^³þ™™Ë² bÝççg'''­V+ f-—ËÉx2 š¦F„$ïÝûQžç?AŠË«ì'@äx)©y^s­ûE¡ê†y½¼qýúµ+ךªœŸ{猵Ãá nš­í­k7®9v,ØÔ&¢8Š"‚mˆ—áù7<OD,ÊéááµÛ=)u0Ñ "€qÞpâ‡äD¬§6©ÛK›Ðº¬yᇈâÑÓ§ÃWKj­ó¼–ŒÖZoooK)›Ê„‹b<çY^–Å¢6uª„"Lk1úœ@*°@D‚Ù*%„@Ff`@Rº1 9ύ© kçY«éx¼œ5¶‰’„ˆúý}%µÒ:Šc’RhM¤™Ù1[kéE{ßðïånæ*©ZC/Ÿa`ß³qÛ"†Áù(Šž<yÂ0‚¨,Ë@auÞi­›¦fï}Y–×®]ë÷ûG‡'!ßßÀô—£êrx…Ã1ԛj.¾ü싷oÝyëÍ7›²Z.—ùWÿy¶œœž\¿vm1Ÿÿýßÿnݹùf÷k½V«.õªõôâ¼rˆ’+û×>½ÿðàøêþqÔò`šº(Ë*|Ò\©ðn/§›—Ãèµož_°Aç<¿Bˆ•Zë¦1eU„¿ét:wïލ¢¨XÌа/' uÔꖍ]«cM€Â³ ðƒÁ !œ2¡ÃC„ž¤´:‚W<eF®MÝX' J±,KcŠã¸•ÇIJR5‹¦öžÓ4ËÚ­ÁùHî'üÛ;„ðõÁ iøúÎó¥v\ØÄSøÕ%acŽ¢È{? æóy¿ß9ݸq£Óé4¦
+’ -Œ3eUFIšµZ(PH%µÞÉúµm¦Ó¹Ž"kmY•qœÌfÓ,oÅR!" B©ü+ÌÕW>üóóoÇðZC¬ØC¶1 6³Ú!òâ8€ù‚˲ â“ÉäììŒH²ó¡Ü‹¢¨ªêápøλïüö·=~ü8ÔVAQü’©Åk¢Ê¯E¿š¦Q€çǧ?ùçŸt{½üð‡ó²˜/—Wö÷Ó4œΆç{»»»»»ôŒ+¬‚íà«×Hè[·Þi·ZA~â8Ö*‚6Õæ¯6ߛxΈ|
+Ò¥Gnv,¿úz9°Â²ËÑÑh­Ó8®›
+#5˜Œ"¥¯î좊/“^¤z ‡„Ö;„•@àCT NtLöd Œdh¼w!ª’<„¢,1É2éÆZ©¤T
+M$0’’V‡ @I¤”")IøðfIRI2c÷>ÒQœ&Ö¹ù|Á€­N‡¤ÒQ§)
+¡”TJi-·[!ÈZ×ÞÚ)ª&J’«W¯7Æ5uëtx~ñåƒÛÛ;KÓévË¢
+„ûÒ#¥ ¾FÔQá݈°+rÇíVËTMSUeYnïïöw:fx|aÝV»M€‰ç…gƍA¬TˆÅjv"0ä=" ¥¤RÖ»Ê4Rë4ː(H
+Hdœ›Lfq’Ø¢˜†ú+Š" êt:Q ”qœÑ|¶Ÿõ¶['§Ï–‹Åo¼q>8MΈèË/ëÉdzûÎíùÜ<<9å¼ÕuÖÞýà.IŽbr\×M´µÝï÷§ÎƒÒqšµ¤Òa º,ËóósfnµZMÓ”›
+.\ŒÍze檪ÏNÏî~p÷÷ŸÜuÒjµF£QÇA¿$8¾„­…Ú6eA¸NA†yooo2N¦ShšæÙ³g¿úÕ¯®\ݾ~ý&3?xðeY.Ð+ԆU±2žxM'ƒœÉK¨Ç+IÒ^›8B„RFk-„r΅N× %IJ’yžWM-˜„$@l¬)‹"Š’kW¯îïí!Ãxx1ê²Üí_Wó£áY73I¤5{bdÈ^¬b ‰ƒw¢`(ˆ¤TŠêÆxæ(Ž¤RÆ;DÁ€JÅÖ»‹Ñ°¬ë7ºÝÁàâìtÐëmµZí^o ‘”R’¤÷ µ"’]½ºEÑx<ÎóÔØæ“O>RJcŸ<%"fÇì:Ý6
+žyùöÚÀzé”|)È.׆dlø4­ˆ˜¦óÙüåÀJ³”Áz˜Í2ªª’$‹ãX)©¢(ªëÚŸ&(8‰Æ^<Û»Ûä­˜mp‡†ÕF!ž‚éÊ
+¢ˆ³IXö(€ÆƘñlÊq’Eqõêõ³ÓsDlšˆ•ÒeY,E’äR*I:ɶà ,ø*Ún'×k­Vª1Ƴ,
+ÀXÓÔUc ‘dö‚ˆ=›¦fï€^– ‘YžÂ XÍç¡öÖ)A$u{«MDóù¼µ·7™L–Å’ÑÖÃó¬Ìúýþ¬¿›àUÍ{1ÄX_“O¬W£XJ@d!; (4€%•T
+χO>iå©^Á ¾ª*ôk3öð¡ÄZþ«ÚÌ/=k 6SUËÆTZÇY¡`çŒ@’l ˜W÷VžIÏhš†½WR¦IR23Ãv¿ÿÞ{ï%IR–%"~öÙg?ªª*Š¢ù|6ÃÅbñû£©¸±ÝdìDô¾ŽbM©†Ð‘`$A(X IH„bÕáwkòÉdz¢gƒQ¿ßÏóüÁ—‚Ÿ@˜33ÆÌçsiçÜh4*Šei›ºÉ³ö•+W­ud­ýÕ/1L¬µíNg±X|ï{ßët»Œ&H`8~òÉ'[öÅÅðg?û—ÿú_·³¬}y móÕommÝ»wo:~üÑGÃÁè­·ÞLÇãÉ
+EŒãxgg§×ëåyž¦ét:ýéOúçþçwîÜyðàz/¥tÞj­ú»;çççh!L;^.þy=P~¸IÌ«eQGÑñёwV*ñáw;½®Dyy»úª]góۗp9¿*(/…,„ão>ŸWUE:Žb)•sA”$„óž_•leYš$iKP‘Œu”D±>jÐU_K¬4þ˲‡Î¹V«õtQ|z>^p$TŒˆ,$Æ
+D2ôº®“$¹wïޕ+Wž={öÑG-—…”j±\ºµ_WÈG‰¥”³Ùììììììloo/p†Ó4vÎJ)nÝz£ßßöޅÑÊË\Íp1xöB-i]µ,烣££g‡Ór¡’À%üJùڗëuÈü xí“lž<‹EQÎ{)•R{®dÂå¥?I]b¥I¦Q\é̔¤ZÚé|þ›ßü&„W8¤T¼aºRvóöÁà4.£ýíLÑԊ½—N‰” aA0
+B°1¤P²1søì÷þìÏþõWÿöÙgŸ[ë"Òº“}¢Üßßû«¿ú«,Ë>ûì³û÷ïÿèG?zÿý÷ÏÎO÷¯ì;g¼÷7n\cupð”P¬‡2üæBPû…¨&@SÖK1·Ö4®Ù¹ÒßÞÚMQÁ¥ó—uFüå`
+·?œfʨs«F{{£(bFc]h©xÌV)ùªvƒH’$Ž¢8Žó,Ëó<I’HG±Öq‡­bCÙafæ xÊDΣñx,³í…Ì~{<üh8žÕ…fhJ_-]]²³ À‚#2 DÁÅt“$I²µµ<m•ÒívK)ÅuUœœx者 Ëz_IBŠP(©´ÔR{'عD«÷Þ~{:{k‘9]·Ý¹uóùlº·×ÿñÿãÑñáÇd­‘’<¯Ì™$ŒÖuÝjµÞÿý÷Þ{¯Óé ¢Rz³g„¯(Š¢n·{íÚµo~ó›wîÜ©ªj0|ÿûßëí·²<MÒ¸(—$Å·¿ó­7¯Gq¤µÞWx=‘¶A%V¨&ËÞ;kåòøôä|<b~úká«Ë»Î姅y›=éeX3a¤¬ßïommEQ̘‘HPXø:-]‘¥i;oµò<MÓ,M[yž& 9g‰(MÓ@ª Š±º
+ïÀ,—˃ãsˆ[&ï~1š|1V
+,yôÆ5U]MS¯òD!<{&2ˆ‚-­lÐ]·ÛmµZyž÷ûý4M˲ªëºÓi‡þ4Í‹óóó8NP`pÜßß÷k ¼sÁ«]
+¡ˆœ1ðî;ïÔeÉÞ# ”Ò+‰Ò$¹}ë¶Öúððàk_û`k«û/?ûé“'‚ÚEþ¼zJÓt¹\âÊA(%é¾Pç\UUÌ<™Lþîïþîÿñ1J©?þøË/¿¼zõê›o¾ùÖ[o„}ÿúõëaѾX/]éÖR[W%0’ãñøôüÜ]¢©ü3ñrw9€þp!ì¦B¥$‘§–µ.D•Ö‘Ò;BH©Øó«žÐ¢•¦Vžgi’D­VîıneٕþîÖVk«¿½Ýëv»ÝÎN¿ßív%
+°N I…©§ƒ¡³.ï÷Ë(ùôdüð¼Z¸¶@pԔ¢œaS2³ô¸ž†&Q”b¤€¬wŽ™”²tœf­¢œL¦UÕt:="å¬GÀù|TV³4ÕsÞÞÞi·ºÎ9ï€'Bï÷Öy[›ÊxcÙÔ¦Ú»²»,‹bnlÝ4ucë€ØÞéçyûÑÃǒÔûïÝ=;=ýò‹/¼3›ä=4ÚVô@ˆÂ{^.—Ãá`±˜Ï“ÆԌ’G½˜}ôÉ£GŽg³Ùb±øå/ùåœåïï‡ßþ֟(ŠØ¡ºÝîQžçᐢµóå&6[‘
+i¨©d˜&ƒ“Së,‡ØwÁÖõ«iBð"ñ^F]ß,sx$8ç½wD’H[ƒ¦¡ºÄÉxY×Á³¼7ˆ^FBTôª+¸Ì¢ˆ+ë:KöÎ:g”$o½·\T•SÒZëØk­{!„bäÆxÀª®¡®«ùd,VIV4öÑÈ To_Rp 8aJ»œ9R”¤‚Ø pÞyd¯™H €(Œsž!ŽR¥!¤Vº×íµZm!p2æ­HiEºªªÝþž÷`$P98À$ %‘$!¥q6måãéäéÁ³v·ç¼W*vì­ç¼ÕÙÛ½òøñ—'ǧÜýàÑÃGŸ}öé»ï¾sûöÛ¼¶ˆ6Æ\\\‘Jâ̵øæ͛ˆ8›Í˜½RÒû•oă¿øüÁÿûßÿy4…>®I)ŸÞÿìèðäÞ½{oܸýÎÛï¥IΊ4M«ªJ’$l?â/8f¶Îo­wZkg,“$FëœTj%/ÐlzÎYØs—됿šõ‡‡‘D"Á±Î…Q,X¹˜0(©e±¬ƒažÇûû¢`vHèÙ[×"i/V–9æ$€¢k§ç\UÖuÕX`>Ì# [U¦©3vYW¦ª”5†Ër8´­N¶½Õ]Õ¯ž@Ò{c»+¤©¨.¢97…yS¢lã¼%Y"RXUyž+µ<jµZÌahØ)%«ª:99‹£´,«(Ò¦qÝnÏÛ4͆_+Ċ«ÈžPI€ì¹ªêÃÃÃ?üFȗÂkµZï½÷Þ§Ÿ~|ppðýïÿÏþìÏþæoþæç?ÿùNÿ
+¼þêÅ~ýO˜›¦év{i3{"
+žiw»4͊etýZÚjušÚ#BHݚƒˆ¦iì«ì%¥÷>‘£¨AÄv[, f_šZ”¤‘ã”4Íçށµà.ŠÉ¢X
+ãg‰‚•’¬k’4ÎsM`PãV¯§¢þà´þݳ¦b÷A©Š¬kj¬&p65ót¯Fíd¹G žµX±SÐ9Ȉž™{[[Bc¬s†£ñd:Û»òV§»]WµTêøøäþýûúÝ?ýðÃCîrpppÿþýo}ë[W®\D<|òäé½{÷Ò$6¦Ñ$÷vv­µÎº$I˜YéhÿJ ‘
+D"%%×U(„ŠtÖÊÓ<GãÉx:#²g„Ûo½wý·vQÌ˲`öe5“´:i2ŠÊj!8ãWƒëº~øða°ä¬ªj#”â8ÀiÎ9&,êJÆ*înõ®Ý¼$9k­@Ð2*KÛ4ŽµQZíV»i¬$éü>xŽ£nK: î|p®‚Þ)f?™ŒóE'y«+I6Æ9ïÉpX‡ìƒì»@ÏÞ5 ¤æúj²$É
+Ò8êVÈ ÎykBfMQ,­3 PÖÒ9S¥"RIã­sN¡dYJc­|˜HÂjÆŠºð#×Î[ý«7ËÅò‹'ÃJ-o߸²ÓÉ0× i7ܔ†ŠN´»—uw ”¯-£RJ%Á{¶×¶š/A!Hk(Þ~û$I¬õ‚¤”*I’,Ëx±XÄq콪“ɤÛí¥*ÚêmUei­”D„Všóëß0Æ䝶6ֆ)¥4Óc%ÉV«ôæ‹ùl6;???=;›Œ'ì\½t¬Þ}ÿîöÎ~]Þ6Ëb9NÙ±Sš½óÆy'XXð€ P`S7ƒÁ `ÂËuç1D@ØÂ6™D±Ž5 Dqűuîðè¨Ì;ý~_JÕË ÖzÖ¸j±(’4õÞecç™ùá«`f#„0MžÝxrqzz²ÕÛ1n6›9k[íN’¤UÕ9ĕÁCPf!„ó.”VZkg¹,ªW›Ð+ùT†$¤`´¶¡:²¦1‚H’,”òαçM­€‰8ŽGËÂXk­ÓR.,T¦Iâx¾XÌg³þN?Ï҅m¾Çίo·nö;½¸ã\%L%še±<ŽâN¿ÓÛïtv(îºÕð…"R¡Ani‘dd{{[ª>ÂÌý~?xÇÛ&´â«N§sïÞ=(˂Hîïïïîînr¸¢(¥Rq–:`c¬Ä´–5 ݅F„цû÷ïþùçÇÇÇË刈„<o½ûNç¬*=‚qn¾\VuI˦®MíH‘·>8œ
+±WËb9¼8žNg{{WHHcÄÕ Xy̬X_ˆÇQ¨“f³ùd<îtÚ»»»‚èâ⢮ë~¿Ÿ$IÓØÍÐDx3aç z»P–eQ̼˜“éäU„V*¥P¬Ô¸ÃŠ ORVÖ6u½Þ<)”!:Šqó½7MÇ1˜¦ qŠ!=òÂ8W™º\ιý½ý¤Ó£´3¾,.–ÅÕN²·•o©HÕUäëeuîÌl±ÈIw?Ê»qšGi†$õ>V¤@1³$HA¬6d­u»ÝŽãèh8F½^/À•»»»D²,Ë8ŽÃ’X©ŸjY諸öÀ$€„aô>à ƒÁàäää÷÷?~öìÙÁÁÁl6 lOӘG˜C†D$¼CfDË岪 çŒ Ñêæžíb²`tŽQ€°µ‰âx±XœœœÜ¸qãêÕ«aß
+&.¥dDç\’%ýÝ~p–ÜÝÛS¬«¦Ñ*ÎÛ=f6Ɲýþ÷¿wŽ¿ño§IìÍÄڒfÓ¡
+ÒWÞùƚf¹lêZJR.Ë¢¶NeVϕÉÑàøxxqcÙ³Ÿí¨˜˜ yh–óårîƒ(iõvö:;ûI«‡*AM픒a»
+‡Ã^o+ÀE¼žÁ""@€‚= Œ’¸¬ëÅb1¿/F'''ÇÇÇGGGMÓX·ò ì4ˆtdØxvž½µn4yï‰Ú4EYÖuˆÎûªq΁ŠTœF2’Ö:Î[šaq£Ã`7 ¡­¤"É5‡…°aŒ.†¦®´Žœõvw{»åÊÕN+ïv»ÏžZkIX\É¢ãŽßœEEQ´Ú­ÙlòÑGýâ?^œ3sÒÞyóÎ’r6Î‹ñhT•¥­Íx<¾¸¸˜N§
+8¶¥ð ›mO¬guVÇ«wDôO蕆©µ~í„J(¬s(ê,K=
+R¨BӜp °qÉXƒÚK%Ó<3Aˆh¨ê’P`–„ˆ¥r ‚k°ìàb4@Iy»‰H¶ZE]|r1?m\¿×jçI u¤<HƪĦ¶°Ö\ N&O¿x’¤QÚj÷ú[;»y»w¶‰„RZk¥µV(¼qZë›7o6Móµ¯}íʕ+{{{iž¦ŽŒ1MSc˪,Šr¹,çƒÃ£Ã³³³‹‹‹ÅrIì|¨pQŽ›Ö‘ -]í4É$Ž­1uݔeÈ)É;_•UY–­V¯cL§ê4aÁŽXÅ©ŠbŠ£vUÔÃӉášY"¬.Ø|ºÌòƒµ› 5npv‘¥™±æŸþï~üæ³o~û[·nÝi·ÛíNg<>yz’µ{Ýíñ|抲h·Ú¥W¾âHGyž¼¨§¦ôsøÙÏ~ñӟþôÑ£g¡y`Œg(?ûøþMA=†ˆÂx;3³c€k®£¤Ê4¯:Ø=7s „$
+¥£V*Ž"ï= ‰Š cm]×À¬¥,ËR
+KŠ¼÷l½"åÁ¯mŸâ/¡—›t¬±UUyïëªþÝï>ú×û÷^¯wãƍþð‡{{{eYi-«ºžÍç_~ùežçƒÁ`±X GD±³³³½½MDEQEñùïF#cÌz—ι•A†/n¢ֈ¾¼¶§|ñÆpÖ~XáŸçGææ¿W/%VT]Bi]Uu¥t¤õBiÂh½Ílk£V2Î
+I)bàsRÇRp¾1&°äŒ1X×ÞÕ¶¶I¬w{´Õ2ŠØÙژ²¶¾¬ª8ÒJx#00dô–gŒ¢ªÝræΟwк•Ÿ{Àˆ›¦qìA®L÷6Œ^ç6*°&”öÞ3
+ˆ¤’(QRfÝ.!5u-Ù²oŒu«$Á#¢iÌx<N’”¹1ƚš‡çãó³Ñx4õ$©•wˆeÅÕ¢6MõU6¸¯\29®÷¾®ëUœ$ççÃáùÙYw7˲½ÝÅröìÙ³‹áŸž]\\xÀ$Iƒh÷~¹\4Mcµiš@ÖÝäõ_Ù¼&¾Ú,ºü0±RÎ}%°6ºÙœŸÇì%,DiT*AVGœ7²)=7í: óe)%¶³|UÚHł²4Ýîvcóóù<”Wá=I)ÙÛÉdIàÓ$Q:ӊ< u¼\ÎG£ ·\(IÈ~+d'eðŒ‡(ÐðŽïE8þ1ø›·Ö+;­_K„v)â†ô›8(3si")¥l·[JiÅeQ,–E]TÀZ&© ®ÃözˆÖZ%ÅéÉÁ¯ýë³Ó³ápXVe]׎Pô:ÍÞÎ^+ÍMe—~a_±æþªÐ
+hnY–•ßñÞ¹))°Þy/Zí²©‘YÄ12ÄJ! w^K ˆ>h;)E‘`´uÍΕU½¨ê8ŽRE2BŠ­¯ÊÂyç­.w6֘¥
+™¼ó$H±Þyr.°a‡RÈx0èM*ã½Çà‡à}€å²,#¢$˴֝N7äÎDTUÕp8*Šbx1vÆ&Q$¤Š$•B@.Šb413€_œ>yøèìtä,£`$5֍‡Wy­µ©jo›K)ʺ…~ó梀”IÓ4¦nÒ4a†¦¬lӏï<H!…1f>›Ycˆ(Œ7·ãuCúÛ7a´ †Ë—´Þ¤@×ø×ô
+Ba­‘(„óUUY¥Qpž‘Â$mU c#­Ë¢ðÞGq$¼ÔQ„γ1iI¥¢$Ëò–u—EY–K¤ 0KŽeYT}M䛪©kBôÖxc™YH)‰4¡7›EÒ,ã,H
+xúÇ
+*#!þÚíööövEY«€RªÉtrqq¾X.†ƒÁ¢® išXGQ;ç¼µ:Š–å2´"ö÷÷÷ööêjî\mšÒ$-˅÷ŽHˆ¬oóe¬8ÿh—MŸ`s*%I|óÆͪªŽÃ" ‡¸¶Æ€–S”õ`±Ö;G(@€àÕ!΢_Þ¢^>µ^Ô[{9°.EÞWÖåØ
+#äÂ{@ç°t$@h©5ɊÊH*%=ÆP9#"³ŸÏæƚ¤MF“¦iØ9‰B VP1sÀúk|Uc")“$öž¥RÛÛÛW®]wÞ[S?yúøøpà­SRDŠZ­¨LfQ–DÝ<×ÔÅØ/–‹Æ®*g-1I Š"ˆÆÏ,µ@É%Q’¤Q¤QI¥£HG10kò,ït;RÊÆòl>/Šâôôô|0@€ÅbR
+
+²m¬•R–uåVUå›)-•j·ÚQ¤…”äIÖ͝ÍæÅÂøᢐRÚ:ð^œcX֕Š"™gf¾D’H*¦m“8BoíhÄ—Óòû_ÿ÷ÿóöÿÕnåÓñÅáё5FªQèq¡Ò–R%‰@ PJ
+ĺnš¦A„«³{uˆ3WÍjxy}’0OÆ#@Ɓ¸¢0{ör8灐”fk]@øœ³èXJU75H¥B)¬©PÂ?—@F
+QUÕIš\½vSFéùÅÐcœ%%‘Hz¶ŽµzÕú«o4Œ×sþzmmÐá0OY’åyU׍1Y™fij¬5Î6MSEUU€˜Ä±âyí¢4qö‚A‰bi4M3™LœsuUm:Ù~m=åœ 
+y–ˆH!Ô]»¼¾ÚívÆØ¡?pa´šµò¨P$ƒrNµ«Úº‘Œgyy9ŸÍbŠ÷«»»»»qô ýg­¹¾º–“ìg‰Ê~¿ËP´ÒTˆ 7M³¼\6uS2ňÊz½îûƒTõg³®ëf2‡ˆ1¦ín›(mX`ûWWWõ Ã0®×ë£uN8Ê{úróùüâ₨h­›®#€D9 ÃJ&Òå ù ÞÅPqž\ðĔ"Ÿ];ídЌƒÒ@%¥„ÄÊ13C¦TQI9£RUUÍf3—+΄Ä\
+2+PxÊ%ōªª$‰ Á¸
+(Oê:ÌÜ÷½t-÷û}]×uUMÃX55 R¦c{ ‘ªªŠ9'"böÞOý4 ƒÌ#œ܄pr,W×ͦXŠ3FI›åxÑK©g]f”•RŽ éÊ# ²ÆkÎë梛IÂþôéÓår9cÊe?ŽÈHäàb­»¼z
+BJÆû0R¦ ¼¯›¦3ÆDeÏ… +]sá\˜Q+¥
+£.…–Ý•Úl6©PŠ¡h½ÐîŸ綇ýÝúÁ¶­­ªfÞÝÜ|”BØn·Ò¡»¾X.‹£Ü?fnÛVŸ‡¾'FTà*ÿ鳏=èïøa7¨•º¹~2kÛû»7Ê(ëk¥Ô‹§c¶Ûía˜èáAkýüù󋋋iš¾ýöÛRÊ.MŨ/^è¯n_M%çR../¿øòK­µ sêº*‰ÆðüÙ³ùâŸV«×www~õ6êÉÅå—Ï?Ý.®¶¿Y¯rÿõ‹/ç‹Åý›{Q:ô‡Ënþù?~q?«›®mÿûOB­r)‚€ª®û¾1
+ÜÃðõW_SÌF)kl.™™ʲÝneúcš¦ï¾û.¥ôìÙ³ív»Z­J)¯^½úÃþð鳏}割ô¤^¿~-Û^¥Tß÷›í«×·ýÐÿp·z¹º­«úööUÈIkóÇ?þñõ7ñuÕ\]´WKx½Zݾ¾˜aŒQiý§?ÿy½Ýl¶iÈ‘V:Œ“RX
+·^Ì}ÝXoí./ÚùL
+rU¼ê͛7Ûýî0MÓÈb]×1FÑѵ ¬R™¨j››ŸÀ¶n¬µ’•Ê…ýËW_'§CPÖk•V›ûuå=†º®C¨5)@€«åòæê ­aß÷«Õj°ÖŽãH)×]»¸Z~ûÿù¶{üâ¥ðG—<wàXG=ï•RF*C†Žƒ1¥CDÎ眫|•)g¢”SŠ)ÆS$¢B4¥OØꔒ€ÁÀLnR¡ifF›aШ(§’õN…ˆ™Â0…çÕjµÛí8¦œó8M„l¬ÅRåÝ.hÀÊúeݶ—M¿?l»Ýn7M“¨âh­×»í0 ÖZ`î‡A)å¬UZPÚZÅÇ2Û4G²Ö’€yÖ´Z©õ›ûa”VZë3Û¢TAe{;HKÞûv6‹Z&ºó>D"z8쪶É!úª’N³÷>çlµ¹š/q"NTòr `”Fk•5…Ëv»Ýí÷gš‚3P½”R×ÍÜ»ãaè§CŒuÛ8k«ª’8}\ˆ
+å°~X§)¤˜€9B­ëº¾¾¾†ÓÜpèA¸I~½c£ÔÛk¢B<÷**BRJ1þƌÖY"2†‰È[9],¥HWV¨išäd.S ò»Ä0D¬]<”ù÷âQ+]{g¤õA…]H˜©Ô±mZ]²1všÂhFç}Û¶¬° „‘²[R6…=êÖxßÀö°2µ˜ó8 *•âÍ1„ååeݶZ©Z[Ò¸î÷! Š™¤! âŒ‘^…¸Žd$²#M‡s Aî(ÔVDVY˜¦)ä”Æi¶XH K:V,%§}œÆép8(4Úsˆ¡EÊpÿð •jÚÆûª®«®ëè0çbJó‹Å~ÞÜ¿¡L
+‘Ë‘–)Řb4Î)£´R…Š¬0ÀÌuÛ
+94žFjS‘Hh›~½c+üæëˆå@ÐJ1¢bf.(<M¥¨B\ ‘¡BÎY*”sN9KF坕ðNÀ>º˜"paÁ—‚½Råe¡L¹NH…Èji PI)7uÙƒÖz®pÑ4C×µm{œ©¢Ni§´Rj*ã°?|óÕב g£
+S!N¢a]röÆ**Üøª2 …)E&1C"ßTÄSÌ\œsZÙB¡l¼uóNJe璲TéÚ¶µÖî÷{YY8$Ð &*!gm5tÝl¹XXk°PÑFk……¡nëë©öŒz¦Â¬0§$i“ÕÚûŠ*ïçó¹HH ¢F…ÐJ)µ¼X pLéaQÄZ °2† ‘$¢ ±
+\«RÊéŠrÎ1ÊßJEÞra§ôl6«}Å̍¯¦iJ1©\lAgÌ0M l”BYF
+¾´Þåß6M³X,d+pÞT‰KåœÊ{[À_¿+üö“ŸõWoòQððôãÇßO«í{/ßyó=Ǒr†SŸà§¿¯èŶó„F:?#ü6¨ò<©‚ïLœ‘DAðxBP1%«Þ~‰ˆò›<RçKq<IÄ÷iòÎ-ç|úD\|.¾G‹…€|¢P8^)|粋Àýû__Îô!~‹s›OW p91L^-—ïœãÿ¥c=ÚÿûÛ2=öh¿ÒëÑ>ˆ=:Ö£}{t¬Gû öèXöAìѱíƒØ£c=Ú±GÇz´bŽõhÄëÑ>ˆý/”Au•ËF¶•IEND®B`‚
\ No newline at end of file
/advdemos/branches/advdemos/mesaref/mesaref.c
0,0 → 1,516
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Giacomo Guidi <giacomo@gandalf.sssup.it>
*
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
#include <drivers/glib.h>
#include <drivers/keyb.h>
 
#include <GL/osmesa.h>
#include <GL/glut.h>
#include <png.h>
 
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <kernel/log.h>
#include <kernel/kern.h>
 
#include <stdio.h>
 
#ifndef M_PI
#define M_PI 3.14159265
#endif
 
#define WIDTH 640
#define HEIGHT 480
#define BYTES_PP 2 //BytesPerPixel
 
#define DEG2RAD (3.14159/180.0)
 
static GLint ImgWidth = 0, ImgHeight = 0;
static GLenum ImgFormat = 0;
static GLubyte *Image = NULL;
 
#define MAX_OBJECTS 2
static GLint table_list;
static GLint objects_list[MAX_OBJECTS];
 
static GLfloat xrot, yrot;
static GLfloat spin;
 
OSMesaContext ctx;
 
unsigned char *rgb_565_buf = NULL; //RGB 16 bpp Buffer
unsigned char *video_buf = NULL; //Video Buffer
 
unsigned long int VMEMLONG = WIDTH * HEIGHT * BYTES_PP / 4; // Used by copy_videomem_16to16
unsigned long int RGB565MEM = WIDTH * HEIGHT * BYTES_PP; // Total video mem
 
unsigned long int PERIOD_REFRESH = 150000;
unsigned long int PERIOD_DISEGNA = 150000;
 
unsigned long int WCET_REFRESH, WCET_DISEGNA;
 
TASK refesh(void);
TASK disegna(void);
 
PID refresh_PID, disegna_PID;
 
void read_png_file(char *file_name, GLubyte **buffer, GLint *width, GLint *height, png_byte *color_type)
{
 
int y;
png_byte bit_depth;
 
png_structp png_ptr;
png_infop info_ptr;
int number_of_passes;
png_bytep * row_pointers;
 
char header[8]; // 8 is the maximum size that can be checked
 
/* open file and test for it being a png */
FILE *fp = fopen(file_name, "rb");
if (!fp) {
cprintf("[read_png_file] File %s could not be opened for reading\n", file_name);
sys_end();
}
fread(header, 1, 8, fp);
if (png_sig_cmp(header, 0, 8))
cprintf("[read_png_file] File %s is not recognized as a PNG file\n", file_name);
/* initialize stuff */
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
cprintf("[read_png_file] png_create_read_struct failed\n");
 
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
cprintf("[read_png_file] png_create_info_struct failed\n");
 
png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, 8);
 
png_read_info(png_ptr, info_ptr);
 
*width = info_ptr->width;
*height = info_ptr->height;
*color_type = info_ptr->color_type;
bit_depth = info_ptr->bit_depth;
 
number_of_passes = png_set_interlace_handling(png_ptr);
cprintf("Open PNG W: %d H: %d CT: %d BD: %d\n",*width,*height,*color_type,bit_depth);
png_read_update_info(png_ptr, info_ptr);
 
row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * info_ptr->height);
for (y=0; y<info_ptr->height; y++)
row_pointers[y] = (png_byte*) malloc(info_ptr->rowbytes);
 
png_read_image(png_ptr, row_pointers);
 
if(info_ptr->color_type == PNG_COLOR_TYPE_RGB) {
*buffer = malloc(info_ptr->height * info_ptr->rowbytes);
for(y=0; y<info_ptr->height; y++)
memcpy(*buffer+y*info_ptr->rowbytes,row_pointers[y],info_ptr->rowbytes);
}
 
fclose(fp);
}
 
static void make_table( void )
{
static GLfloat table_mat[] = { 1.0, 1.0, 1.0, 0.6 };
static GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 };
 
table_list = glGenLists(1);
glNewList( table_list, GL_COMPILE );
 
/* load table's texture */
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat );
/* glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/
glMaterialfv( GL_FRONT, GL_DIFFUSE, table_mat );
glMaterialfv( GL_FRONT, GL_AMBIENT, gray );
/* draw textured square for the table */
glPushMatrix();
glScalef( 4.0, 4.0, 4.0 );
glBegin( GL_POLYGON );
glNormal3f( 0.0, 1.0, 0.0 );
glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, 0.0, -1.0 );
glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, 0.0, 1.0 );
glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 0.0, -1.0 );
glEnd();
glPopMatrix();
 
glDisable( GL_TEXTURE_2D );
 
glEndList();
}
 
 
static void make_objects( void )
{
GLUquadricObj *q;
 
static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
static GLfloat green[] = { 0.2, 1.0, 0.2, 1.0 };
static GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 };
 
q = gluNewQuadric();
gluQuadricDrawStyle( q, GLU_FILL );
gluQuadricNormals( q, GLU_SMOOTH );
 
objects_list[0] = glGenLists(1);
glNewList( objects_list[0], GL_COMPILE );
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan );
glMaterialfv( GL_FRONT, GL_EMISSION, black );
gluCylinder( q, 0.5, 0.5, 1.0, 15, 1 );
glEndList();
 
objects_list[1] = glGenLists(1);
glNewList( objects_list[1], GL_COMPILE );
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green );
glMaterialfv( GL_FRONT, GL_EMISSION, black );
gluCylinder( q, 1.5, 0.0, 2.5, 15, 1 );
glEndList();
}
 
static void gl_init( void )
{
png_byte img_color;
 
GLfloat yAspect = 2.5;
GLfloat xAspect = yAspect * (float) WIDTH / (float) HEIGHT;
 
//Create the OSMesa Context
ctx = OSMesaCreateContext(OSMESA_RGB_565, NULL);
 
//Make Current Context
OSMesaMakeCurrent(ctx, rgb_565_buf, GL_UNSIGNED_SHORT_5_6_5, WIDTH, HEIGHT);
 
read_png_file("test.png",&Image,&ImgWidth,&ImgHeight,&img_color);
if (img_color == PNG_COLOR_TYPE_RGB && Image != NULL)
ImgFormat = GL_RGB;
else {
cprintf("Texture Load Falied !!\n");
sys_end();
}
make_table();
make_objects();
 
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ImgWidth, ImgHeight,
ImgFormat, GL_UNSIGNED_BYTE, Image);
 
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
 
xrot = 30.0;
yrot = 50.0;
spin = 0.0;
 
glShadeModel( GL_FLAT );
glEnable( GL_LIGHT0 );
glEnable( GL_LIGHTING );
 
glClearColor( 0.5, 0.5, 0.9, 0.0 );
 
glEnable( GL_NORMALIZE );
 
glViewport(0, 0, WIDTH, HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum( -xAspect, xAspect, yAspect, -yAspect, 10.0, 30.0 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
 
}
 
static void draw_objects( GLfloat eyex, GLfloat eyey, GLfloat eyez )
{
(void) eyex;
(void) eyey;
(void) eyez;
#ifndef USE_ZBUFFER
if (eyex<0.5) {
#endif
glPushMatrix();
glTranslatef( 1.0, 1.5, 0.0 );
glRotatef( spin, 1.0, 0.5, 0.0 );
glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
glCallList( objects_list[0] );
glPopMatrix();
glPushMatrix();
glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
glRotatef( spin, 1.0, 0.5, 0.0 );
glScalef( 0.5, 0.5, 0.5 );
glCallList( objects_list[1] );
glPopMatrix();
#ifndef USE_ZBUFFER
}
else {
glPushMatrix();
glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
glRotatef( spin, 1.0, 0.5, 0.0 );
glScalef( 0.5, 0.5, 0.5 );
glCallList( objects_list[1] );
glPopMatrix();
 
glPushMatrix();
glTranslatef( 1.0, 1.5, 0.0 );
glRotatef( spin, 1.0, 0.5, 0.0 );
glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
glCallList( objects_list[0] );
glPopMatrix();
}
#endif
 
}
 
static void draw_table( void )
{
glCallList( table_list );
}
 
static void draw( void )
{
static GLfloat light_pos[] = { 0.0, 20.0, 0.0, 1.0 };
GLfloat dist = 20.0;
GLfloat eyex, eyey, eyez;
 
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
 
eyex = dist * cos(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
eyez = dist * sin(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
eyey = dist * sin(xrot*DEG2RAD);
 
/* view from top */
glPushMatrix();
gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
 
glLightfv( GL_LIGHT0, GL_POSITION, light_pos );
/* draw table into stencil planes */
glDisable( GL_DEPTH_TEST );
glEnable( GL_STENCIL_TEST );
glStencilFunc( GL_ALWAYS, 1, 0xffffffff );
glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
draw_table();
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
 
glEnable( GL_DEPTH_TEST );
 
/* render view from below (reflected viewport) */
/* only draw where stencil==1 */
if (eyey>0.0) {
glPushMatrix();
glStencilFunc( GL_EQUAL, 1, 0xffffffff ); /* draw if ==1 */
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
glScalef( 1.0, -1.0, 1.0 );
 
/* Reposition light in reflected space. */
glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
 
draw_objects(eyex, eyey, eyez);
glPopMatrix();
 
/* Restore light's original unreflected position. */
glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
}
 
glDisable( GL_STENCIL_TEST );
 
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
 
glEnable( GL_TEXTURE_2D );
draw_table();
glDisable( GL_TEXTURE_2D );
glDisable( GL_BLEND );
 
/* view from top */
glPushMatrix();
 
draw_objects(eyex, eyey, eyez);
 
glPopMatrix();
 
glPopMatrix();
 
glFinish();
 
}
 
static int screen()
{
 
extern DWORD flbaddr;
/* graphic card Initialization */
if (grx_init() < 1) {
sys_abort(1);
}
if (grx_open(640, 480, 16) < 0) {
cprintf("GRX Err\n");
sys_abort(1);
}
video_buf = (unsigned char *)flbaddr;
 
return 0;
}
 
void program_end(void *arg)
{
OSMesaDestroyContext(ctx);
free(rgb_565_buf);
 
grx_close();
 
sys_end();
 
}
 
void program_key_end(KEY_EVT *k)
{
 
sys_end();
 
}
 
TASK refresh(void)
{
 
while(1) {
 
memcpy(rgb_565_buf, video_buf, RGB565MEM);
task_endcycle();
 
}
 
sys_end();
 
}
 
 
TASK disegna(void)
{
 
char text[100];
TIME disegna_TIME, refresh_TIME;
while(1) {
jet_gettable(refresh_PID, &refresh_TIME, 1);
jet_gettable(disegna_PID, &disegna_TIME, 1);
 
spin += 2.0;
yrot += 3.0;
 
draw();
sprintf(text,"Hard Task Refresh PER:%6d us EX:%6d us",(int)PERIOD_REFRESH,(int)refresh_TIME);
grx_text(text,10,5,rgb16(0,0,255),0);
sprintf(text,"Hard Task Draw PER:%6d us EX:%6d us",(int)PERIOD_DISEGNA,(int)disegna_TIME);
grx_text(text,10,15,rgb16(0,0,255),0);
 
task_endcycle();
 
}
 
sys_end();
 
}
 
int main (int argc, char *argv[])
{
HARD_TASK_MODEL ht_refresh, ht_disegna;
 
sys_atrunlevel(program_end,NULL, RUNLEVEL_BEFORE_EXIT);
WCET_REFRESH =((long int) PERIOD_REFRESH * (0.2));
WCET_DISEGNA =((long int) PERIOD_DISEGNA * (0.7));
 
hard_task_default_model(ht_refresh);
hard_task_def_wcet(ht_refresh,WCET_REFRESH);
hard_task_def_mit(ht_refresh,PERIOD_REFRESH);
hard_task_def_usemath(ht_refresh);
hard_task_def_group(ht_refresh,1);
hard_task_def_ctrl_jet(ht_refresh);
 
refresh_PID = task_create("refresh", refresh, &ht_refresh, NULL);
if (refresh_PID == -1) {
sys_end();
exit(4);
}
 
hard_task_default_model(ht_disegna);
hard_task_def_mit(ht_disegna,PERIOD_DISEGNA);
hard_task_def_wcet(ht_disegna,WCET_DISEGNA);
hard_task_def_group(ht_disegna,1);
hard_task_def_ctrl_jet(ht_disegna);
hard_task_def_usemath(ht_disegna);
hard_task_def_stack(ht_disegna, 30000);
disegna_PID = task_create("disegna", disegna, &ht_disegna, NULL);
if (disegna_PID == -1) {
sys_end();
exit(4);
}
 
{
KEY_EVT k;
k.flag = ALTL_BIT;
k.scan = KEY_C;
k.ascii = 'c';
keyb_hook(k,program_key_end);
}
rgb_565_buf = malloc(RGB565MEM);
gl_init();
if (screen()) {
printk(KERN_INFO "Graphical initialization failed !!\n");
sys_end();
}
 
group_activate(1);
 
return 0;
}
/advdemos/branches/advdemos/mesaref/initfile.c
0,0 → 1,182
/*
* 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
*/
 
/*
* 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
*
*/
 
/*
* CVS : $Id: initfile.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 $
*/
 
#include "kernel/kern.h"
#include "modules/edf.h"
#include "modules/rr.h"
#include "modules/cbs.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
#include "modules/pi.h"
#include "modules/pc.h"
#include "modules/srp.h"
#include "modules/npp.h"
#include "modules/nop.h"
#include "modules/nopm.h"
 
#include "fs/bdevinit.h"
#include "fs/fsinit.h"
#include "fs/bdev.h"
 
#include "drivers/keyb.h"
 
/*+ sysyem tick in us +*/
#define TICK 1000
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
dev_t root_device=-1;
dev_t temp_device=-1;
 
int __register_sub_init(void)
{
#if defined(EDFSCHED)
extern void BD_EDF_register_module(void);
BD_EDF_register_module();
#elif defined(PSCANSCHED)
extern void BD_PSCAN_register_module(void);
BD_PSCAN_register_module();
#endif
return 0;
}
 
int choose_root_callback(dev_t dev,u_int8_t fs)
{
if (fs==FS_MSDOS) return dev;
return -1;
}
 
int choose_temp_callback(__dev_t dev,__uint8_t fs)
{
static int flag=0;
if (fs==FS_MSDOS) {
if (flag) return dev;
flag=1;
}
return -1;
}
 
int __bdev_sub_init(void)
{
BDEV_PARMS bdev=BASE_BDEV;
bdev_def_showinfo(bdev,FALSE);
bdev_init(&bdev);
 
root_device=bdev_scan_devices(choose_root_callback);
if (root_device<0) {
cprintf("can't find root device to mount on /!!!\n");
sys_end();
return -1;
}
 
return 0;
 
}
 
int __fs_sub_init(void)
{
extern int libc_initialize(void);
FILESYSTEM_PARMS fs=BASE_FILESYSTEM;
filesystem_def_rootdevice(fs,root_device);
filesystem_def_fs(fs,FS_MSDOS);
filesystem_def_showinfo(fs,FALSE);
filesystem_init(&fs);
 
libc_initialize();
 
return 0;
}
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
extern int __register_sub_init(void);
 
EDF_register_level(EDF_ENABLE_ALL);
RR_register_level(RRTICK, RR_MAIN_YES, mb);
CBS_register_level(CBS_ENABLE_ALL, 0);
dummy_register_level();
 
SEM_register_module();
 
CABS_register_module();
 
PI_register_module();
PC_register_module();
NPP_register_module();
SRP_register_module();
NOP_register_module();
NOPM_register_module();
 
__register_sub_init();
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
KEYB_PARMS keyb = BASE_KEYB;
extern int __bdev_sub_init(void);
extern int __fs_sub_init(void);
HARTPORT_init();
KEYB_init(&keyb);
 
__bdev_sub_init();
__fs_sub_init();
__call_main__(mb);
 
return (void *)0;
}
 
/advdemos/branches/advdemos/mesaref/readme.txt
0,0 → 1,52
--------------------------------------
MESA Demo (reflect)
 
by
 
Giacomo Guidi <giacomo@gandalf.sssup.it>
 
Last update 20/03/2003
--------------------------------------
 
This is a simple test demo for the MESA (5.0)
libraries, the low level graphic drivers is
the SVGA (from the SVGAlib)
 
See drivers/svga/readme for supported cards
 
You need a test.png file present in the
same directory of the demo. Remember that
the file system support only a DOS FAT16 fs.
 
The PNGlib will load this file and it
will be used as a texture.
 
--------------------------------------
 
The demo is composed by:
 
MAKEFILE The makefile used to compile the application
README.TXT This file
INITFILE.C The init file (with fs initialization)
MESAREF.C The MESA Demo
TEST.PNG The PNG texture image
 
--------------------------------------
 
- To specify your card change the line
 
#define CARD <driver name>
 
- The demo calls the grx and off-screen Mesa functions.
The resolution must be 16 bitsperpixel (64K colors) and
the graphic access mode must be linear.
 
- There are two buffers
 
The video buffer (video_buf)
The virtual buffer (rgb_565_buf)
 
copy_videomem_16to16 links these buffers
 
- If the texture load fails, sys_end() is called
 
/advdemos/branches/advdemos/mesaref/makefile
0,0 → 1,16
#
#
#
 
ifndef BASE
BASE=../..
endif
include $(BASE)/config/config.mk
 
PROGS = mesaref
 
include $(BASE)/config/example.mk
 
mesaref:
make -f $(SUBMAKE) APP=mesaref INIT= OTHEROBJS="initfile.o" SHARKOPT="__OSMESA__ __PNG__ __OLDCHAR__ __GRX__"
 
/advdemos/branches/advdemos/edfact/initfile.c
0,0 → 1,99
/*
* 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: initfile.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
*/
 
/*
* 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 "edfact.h"
#include "modules/cbs.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
EDFACT_register_level(EDFACT_ENABLE_ALL);
CBS_register_level(CBS_ENABLE_ALL, 0);
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
//keyb_def_ctrlC(kparms, NULL);
keyb_def_map(kparms,itaMap);
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
/advdemos/branches/advdemos/edfact/edfact.c
0,0 → 1,565
/*
* 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: edfact.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
**/
 
/*
* Copyright (C) 2001 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 "edfact.h"
#include <ll/stdio.h>
#include <ll/string.h>
#include <kernel/model.h>
#include <kernel/descr.h>
#include <kernel/var.h>
#include <kernel/func.h>
 
//#define edfact_printf kern_printf
#define edfact_printf printk
 
/*+ Status used in the level +*/
#define EDFACT_READY MODULE_STATUS_BASE /*+ - Ready status +*/
#define EDFACT_IDLE MODULE_STATUS_BASE+4 /*+ to wait the deadline +*/
 
/*+ flags +*/
#define EDFACT_FLAG_NORAISEEXC 2
 
/*+ the level redefinition for the Earliest Deadline First level +*/
typedef struct {
level_des l; /*+ the standard level descriptor +*/
 
TIME period[MAX_PROC]; /*+ The task periods; the deadlines are
stored in the priority field +*/
int deadline_timer[MAX_PROC];
/*+ The task deadline timers +*/
 
struct timespec deadline_timespec[MAX_PROC];
 
int dline_miss[MAX_PROC]; /*+ Deadline miss counter +*/
int wcet_miss[MAX_PROC]; /*+ Wcet miss counter +*/
 
int nact[MAX_PROC]; /*+ Wcet miss counter +*/
 
int flag[MAX_PROC];
/*+ used to manage the JOB_TASK_MODEL and the
periodicity +*/
 
IQUEUE ready; /*+ the ready queue +*/
 
int flags; /*+ the init flags... +*/
 
bandwidth_t U; /*+ the used bandwidth +*/
 
} EDFACT_level_des;
 
 
static void EDFACT_timer_deadline(void *par);
 
static void EDFACT_internal_activate(EDFACT_level_des *lev, PID p,
struct timespec *t)
{
struct timespec *temp;
 
temp = iq_query_timespec(p, &lev->ready);
 
TIMESPEC_ASSIGN(temp,t);
ADDUSEC2TIMESPEC(lev->period[p], temp);
 
TIMESPEC_ASSIGN(&lev->deadline_timespec[p],
temp);
 
/* Insert task in the correct position */
proc_table[p].status = EDFACT_READY;
iq_timespec_insert(p,&lev->ready);
 
/* needed because when there is a wcet miss I disable CONTROL_CAP */
proc_table[p].control |= CONTROL_CAP;
}
 
static void EDFACT_timer_deadline(void *par)
{
PID p = (PID) par;
EDFACT_level_des *lev;
 
lev = (EDFACT_level_des *)level_table[proc_table[p].task_level];
 
switch (proc_table[p].status) {
case EDFACT_IDLE:
edfact_printf("I%d",p);
 
EDFACT_internal_activate(lev,p, &lev->deadline_timespec[p]);
 
event_need_reschedule();
break;
 
default:
edfact_printf("D%d",p);
/* else, a deadline miss occurred!!! */
lev->dline_miss[p]++;
 
/* the task is into another state */
lev->nact[p]++;
 
/* Set the deadline timer */
ADDUSEC2TIMESPEC(lev->period[p], &lev->deadline_timespec[p]);
}
 
/* Set the deadline timer */
lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
EDFACT_timer_deadline,
(void *)p);
 
}
 
static void EDFACT_timer_guest_deadline(void *par)
{
PID p = (PID) par;
 
edfact_printf("AAARRRGGGHHH!!!");
kern_raise(XDEADLINE_MISS,p);
}
 
 
/* The scheduler only gets the first task in the queue */
static PID EDFACT_public_scheduler(LEVEL l)
{
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
return iq_query_first(&lev->ready);
}
 
/* The on-line guarantee is enabled only if the appropriate flag is set... */
static int EDFACT_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
{
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
if (lev->flags & EDFACT_FAILED_GUARANTEE) {
*freebandwidth = 0;
return 0;
}
else
if (*freebandwidth >= lev->U) {
*freebandwidth -= lev->U;
return 1;
}
else
return 0;
 
}
 
static int EDFACT_public_create(LEVEL l, PID p, TASK_MODEL *m)
{
EDFACT_level_des *lev = (EDFACT_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 || h->periodicity != PERIODIC) return -1;
/* now we know that m is a valid model */
 
lev->period[p] = h->mit;
 
lev->flag[p] = 0;
lev->deadline_timer[p] = -1;
lev->dline_miss[p] = 0;
lev->wcet_miss[p] = 0;
lev->nact[p] = 0;
 
/* Enable wcet check */
proc_table[p].avail_time = h->wcet;
proc_table[p].wcet = h->wcet;
proc_table[p].control |= CONTROL_CAP;
 
/* update the bandwidth... */
if (lev->flags & EDFACT_ENABLE_GUARANTEE) {
bandwidth_t b;
b = (MAX_BANDWIDTH / h->mit) * h->wcet;
 
/* really update lev->U, checking an overflow... */
if (MAX_BANDWIDTH - lev->U > b)
lev->U += b;
else
/* The task can NOT be guaranteed (U>MAX_BANDWIDTH)...
in this case, we don't raise an exception... in fact, after the
EDFACT_task_create the task_create will call level_guarantee that return
-1... return -1 in EDFACT_task_create isn't correct, because:
. generally, the guarantee must be done when also the resources
are registered
. returning -1 will cause the task_create to return with an errno
ETASK_CREATE instead of ENO_GUARANTEE!!!
 
Why I use the flag??? because if the lev->U overflows, if i.e. I set
it to MAX_BANDWIDTH, I lose the correct allocated bandwidth...
*/
lev->flags |= EDFACT_FAILED_GUARANTEE;
}
 
return 0; /* OK, also if the task cannot be guaranteed... */
}
 
static void EDFACT_public_detach(LEVEL l, PID p)
{
/* the EDFACT level doesn't introduce any dinamic allocated new field.
we have only to reset the NO_GUARANTEE FIELD and decrement the allocated
bandwidth */
 
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
if (lev->flags & EDFACT_FAILED_GUARANTEE)
lev->flags &= ~EDFACT_FAILED_GUARANTEE;
else
lev->U -= (MAX_BANDWIDTH / lev->period[p]) * proc_table[p].wcet;
}
 
static void EDFACT_public_dispatch(LEVEL l, PID p, int nostop)
{
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
/* the task state is set EXE by the scheduler()
we extract the task from the ready queue
NB: we can't assume that p is the first task in the queue!!! */
iq_extract(p, &lev->ready);
}
 
static void EDFACT_public_epilogue(LEVEL l, PID p)
{
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
/* check if the wcet is finished... */
if (proc_table[p].avail_time <= 0 && proc_table[p].control&CONTROL_CAP) {
/* wcet finished: disable wcet event and count wcet miss */
edfact_printf("W%d",p);
proc_table[p].control &= ~CONTROL_CAP;
lev->wcet_miss[p]++;
}
 
/* the task it returns into the ready queue... */
iq_timespec_insert(p,&lev->ready);
proc_table[p].status = EDFACT_READY;
}
 
static void EDFACT_public_activate(LEVEL l, PID p)
{
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
struct timespec t;
 
/* Test if we are trying to activate a non sleeping task */
/* save activation (only if needed... */
if (proc_table[p].status != SLEEP) {
/* a periodic task cannot be activated when it is already active */
kern_raise(XACTIVATION,p);
return;
}
 
kern_gettime(&t);
EDFACT_internal_activate(lev,p, &t);
 
/* Set the deadline timer */
lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
EDFACT_timer_deadline,
(void *)p);
 
}
 
static void EDFACT_public_unblock(LEVEL l, PID p)
{
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
/* Insert task in the coEDFect position */
proc_table[p].status = EDFACT_READY;
iq_timespec_insert(p,&lev->ready);
}
 
static void EDFACT_public_block(LEVEL l, PID p)
{
}
 
static int EDFACT_public_message(LEVEL l, PID p, void *m)
{
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
struct timespec t;
 
/* we reset the capacity counters... */
proc_table[p].avail_time = proc_table[p].wcet;
 
if (lev->nact[p] > 0) {
edfact_printf("E%d",p);
 
/* Pending activation: reactivate the thread!!! */
lev->nact[p]--;
 
/* see also EDFACT_timer_deadline */
kern_gettime(&t);
EDFACT_internal_activate(lev,p, &t);
 
/* check if the deadline has already expired */
if (TIMESPEC_A_LT_B(iq_query_timespec(p, &lev->ready), &schedule_time)) {
/* count the deadline miss */
lev->dline_miss[p]++;
kern_event_delete(lev->deadline_timer[p]);
}
 
}
else {
edfact_printf("e%d",p);
 
/* the task has terminated his job before it consume the wcet. All OK! */
proc_table[p].status = EDFACT_IDLE;
 
/* when the deadline timer fire, it recognize the situation and set
correctly all the stuffs (like reactivation, etc... ) */
}
 
jet_update_endcycle(); /* Update the Jet data... */
 
return 0;
}
 
static void EDFACT_public_end(LEVEL l, PID p)
{
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
edfact_printf("Û%d",p);
 
/* we finally put the task in the ready queue */
proc_table[p].status = FREE;
iq_insertfirst(p,&freedesc);
/* and free the allocated bandwidth */
lev->U -= (MAX_BANDWIDTH/lev->period[p]) * proc_table[p].wcet;
 
if (lev->deadline_timer[p] != -1) {
edfact_printf("²%d",p);
kern_event_delete(lev->deadline_timer[p]);
}
}
 
 
/* Guest Functions
These functions manages a JOB_TASK_MODEL, that is used to put
a guest task in the EDFACT ready queue. */
 
static void EDFACT_private_insert(LEVEL l, PID p, TASK_MODEL *m)
{
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
JOB_TASK_MODEL *job;
 
if (m->pclass != JOB_PCLASS || (m->level != 0 && m->level != l) ) {
kern_raise(XINVALID_TASK, p);
return;
}
 
job = (JOB_TASK_MODEL *)m;
 
TIMESPEC_ASSIGN(iq_query_timespec(p, &lev->ready), &job->deadline);
lev->deadline_timer[p] = -1;
lev->dline_miss[p] = 0;
lev->wcet_miss[p] = 0;
lev->nact[p] = 0;
 
if (job->noraiseexc)
lev->flag[p] = EDFACT_FLAG_NORAISEEXC;
else {
lev->flag[p] = 0;
lev->deadline_timer[p] = kern_event_post(iq_query_timespec(p, &lev->ready),
EDFACT_timer_guest_deadline,
(void *)p);
}
 
lev->period[p] = job->period;
 
/* Insert task in the correct position */
iq_timespec_insert(p,&lev->ready);
proc_table[p].status = EDFACT_READY;
 
/* there is no bandwidth guarantee at this level, it is performed
by the level that inserts guest tasks... */
}
 
static void EDFACT_private_dispatch(LEVEL l, PID p, int nostop)
{
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
/* the task state is set to EXE by the scheduler()
we extract the task from the ready queue
NB: we can't assume that p is the first task in the queue!!! */
iq_extract(p, &lev->ready);
}
 
static void EDFACT_private_epilogue(LEVEL l, PID p)
{
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
/* the task has been preempted. it returns into the ready queue... */
iq_timespec_insert(p,&lev->ready);
proc_table[p].status = EDFACT_READY;
}
 
static void EDFACT_private_extract(LEVEL l, PID p)
{
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
//kern_printf("EDFACT_guest_end: dline timer %d\n",lev->deadline_timer[p]);
if (proc_table[p].status == EDFACT_READY)
{
iq_extract(p, &lev->ready);
//kern_printf("(g_end rdy extr)");
}
 
/* we remove the deadline timer, because the slice is finished */
if (lev->deadline_timer[p] != NIL) {
// kern_printf("EDFACT_guest_end: dline timer %d\n",lev->deadline_timer[p]);
kern_event_delete(lev->deadline_timer[p]);
lev->deadline_timer[p] = NIL;
}
 
}
 
/* Registration functions */
 
/*+ Registration function:
int flags the init flags ... see EDFACT.h +*/
LEVEL EDFACT_register_level(int flags)
{
LEVEL l; /* the level that we register */
EDFACT_level_des *lev; /* for readableness only */
PID i; /* a counter */
 
printk("EDFACT_register_level\n");
 
/* request an entry in the level_table */
l = level_alloc_descriptor(sizeof(EDFACT_level_des));
 
lev = (EDFACT_level_des *)level_table[l];
 
printk(" lev=%d\n",(int)lev);
 
/* fill the standard descriptor */
lev->l.private_insert = EDFACT_private_insert;
lev->l.private_extract = EDFACT_private_extract;
lev->l.private_dispatch = EDFACT_private_dispatch;
lev->l.private_epilogue = EDFACT_private_epilogue;
 
lev->l.public_scheduler = EDFACT_public_scheduler;
if (flags & EDFACT_ENABLE_GUARANTEE)
lev->l.public_guarantee = EDFACT_public_guarantee;
else
lev->l.public_guarantee = NULL;
lev->l.public_create = EDFACT_public_create;
lev->l.public_detach = EDFACT_public_detach;
lev->l.public_end = EDFACT_public_end;
lev->l.public_dispatch = EDFACT_public_dispatch;
lev->l.public_epilogue = EDFACT_public_epilogue;
lev->l.public_activate = EDFACT_public_activate;
lev->l.public_unblock = EDFACT_public_unblock;
lev->l.public_block = EDFACT_public_block;
lev->l.public_message = EDFACT_public_message;
 
/* fill the EDFACT descriptor part */
for(i=0; i<MAX_PROC; i++) {
lev->period[i] = 0;
lev->deadline_timer[i] = -1;
lev->flag[i] = 0;
lev->dline_miss[i] = 0;
lev->wcet_miss[i] = 0;
lev->nact[i] = 0;
}
 
iq_init(&lev->ready,&freedesc, 0);
lev->flags = flags & 0x07;
lev->U = 0;
 
return l;
}
 
bandwidth_t EDFACT_usedbandwidth(LEVEL l)
{
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
return lev->U;
}
 
int EDFACT_get_dline_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
return lev->dline_miss[p];
}
 
int EDFACT_get_wcet_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
return lev->wcet_miss[p];
}
 
int EDFACT_get_nact(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
return lev->nact[p];
}
 
int EDFACT_reset_dline_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
lev->dline_miss[p] = 0;
return 0;
}
 
int EDFACT_reset_wcet_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFACT_level_des *lev = (EDFACT_level_des *)(level_table[l]);
 
lev->wcet_miss[p] = 0;
return 0;
}
 
/advdemos/branches/advdemos/edfact/testact.c
0,0 → 1,245
/*
* 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: testact.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
**/
 
/*
* Copyright (C) 2001 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
*
*/
 
/* the demo tests EDFACT with my Celeron 366 Mhz.
Aster1 meet all wcets and all deadlines
Aster2 miss all wcets but hits all the deadlines
Aster3 blocks on a semaphore so it miss all the deadlines and it accumulates
pending activations
Aster4 does 5 states:
1: is a cycle, long enough to cope a little more than 2 periods
2-5: like aster1, they meets all the wcet and deadlines
the debug pattern is something like
WDDEEeIeIeI
W wcet violated
D deadline miss event
E endcycle with automatic reactivation due to pending activations
e normal endcycle
I normal reactivation event
 
 
*/
 
 
#include <kernel/kern.h>
#include <semaphore.h>
#include "edfact.h"
 
PID p1,p2,p3,p4;
 
sem_t sem;
 
#define ASTER_LIM 77
 
TASK aster1(void *arg)
{
int i = 10;
int y = 10+exec_shadow;
 
printf_xy(1,y,WHITE,"%d", exec_shadow);
while (i < ASTER_LIM) {
puts_xy(i,y,WHITE,"*");
task_endcycle();
 
puts_xy(i,y,WHITE," ");
i++;
}
 
return 0;
}
 
TASK aster2(void *arg)
{
int i = 10;
int y = 10+exec_shadow;
int x;
 
printf_xy(1,y,WHITE,"%d", exec_shadow);
while (i < ASTER_LIM) {
puts_xy(i,y,WHITE,"*");
for(x=0; x<1000000; x++);
task_endcycle();
 
puts_xy(i,y,WHITE," ");
i++;
}
 
return 0;
}
 
TASK aster3(void *arg)
{
int i = 10;
int y = 10+exec_shadow;
 
printf_xy(1,y,WHITE,"%d", exec_shadow);
while (i < ASTER_LIM) {
puts_xy(i,y,WHITE,"*");
sem_wait(&sem);
task_endcycle();
 
puts_xy(i,y,WHITE," ");
i++;
}
 
return 0;
}
 
TASK aster4(void *arg)
{
int i = 10;
int y = 10+exec_shadow;
int x;
int flag = 0;
 
printf_xy(1,y,WHITE,"%d", exec_shadow);
while (i < ASTER_LIM) {
puts_xy(i,y,WHITE,"*");
 
switch (flag) {
case 0:
kern_printf("!");
for(x=0; x<5000000; x++) flag=1;
break;
case 1:
flag = 2;
break;
case 2:
flag = 3;
break;
case 3:
flag = 4;
break;
case 4:
flag = 0;
break;
}
 
task_endcycle();
 
puts_xy(i,y,WHITE," ");
i++;
}
 
return 0;
}
 
 
 
TASK clock()
{
printf_xy(50,19,WHITE,"PID miss wcet nact");
while(1) {
printf_xy(50,20,WHITE,"%3d %4d %4d %4d",
p1, EDFACT_get_dline_miss(p1),
EDFACT_get_wcet_miss(p1),
EDFACT_get_nact(p1));
printf_xy(50,21,WHITE,"%3d %4d %4d %4d",
p2, EDFACT_get_dline_miss(p2),
EDFACT_get_wcet_miss(p2),
EDFACT_get_nact(p2));
printf_xy(50,22,WHITE,"%3d %4d %4d %4d",
p3, EDFACT_get_dline_miss(p3),
EDFACT_get_wcet_miss(p3),
EDFACT_get_nact(p3));
printf_xy(50,23,WHITE,"%3d %4d %4d %4d",
p4, EDFACT_get_dline_miss(p4),
EDFACT_get_wcet_miss(p4),
EDFACT_get_nact(p4));
}
}
 
int main(int argc, char **argv)
{
NRT_TASK_MODEL n;
 
HARD_TASK_MODEL m;
 
kern_printf("\nCtrl-C = end demo\n");
 
hard_task_default_model(m);
hard_task_def_mit(m,200000);
hard_task_def_group(m,1);
 
sem_init(&sem,0,0);
 
hard_task_def_wcet(m,2000);
p1 = task_create("1",aster1,&m,NULL);
if (p1 == -1) {
perror("Aster.C(main): Could not create task <aster> ...");
sys_end();
}
 
hard_task_def_wcet(m,2000);
p2 = task_create("1",aster2,&m,NULL);
if (p2 == -1) {
perror("Aster.C(main): Could not create task <aster> ...");
sys_end();
}
 
hard_task_def_wcet(m,2000);
p3 = task_create("1",aster3,&m,NULL);
if (p3 == -1) {
perror("Aster.C(main): Could not create task <aster> ...");
sys_end();
}
 
hard_task_def_mit(m,20000);
hard_task_def_wcet(m,500);
p4 = task_create("1",aster4,&m,NULL);
if (p4 == -1) {
perror("Aster.C(main): Could not create task <aster> ...");
sys_end();
}
 
group_activate(1);
 
nrt_task_default_model(n);
task_activate(task_create("Clock",clock,&n,NULL));
return 0;
}
 
/advdemos/branches/advdemos/edfact/edfact.h
0,0 → 1,152
/*
* 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: edfact.h,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
This file contains the server EDFACT (EDF with pending activations)
 
Title:
EDFACT
 
Task Models Accepted:
HARD_TASK_MODEL - Hard Tasks (only Periodic)
wcet field and mit field must be != 0. They are used to set the wcet
and period of the tasks.
periodicity field can be only PERIODIC
drel field is ignored
Guest Models Accepted:
JOB_TASK_MODEL - a single guest task activation
Identified by an absolute deadline and a period.
period field is ignored
 
Description:
This module schedule his tasks following the classic EDF scheme.
The task guarantee is based on the factor utilization approach.
The tasks scheduled are only periodic.
All the task are put in a queue and the scheduling is based on the
deadline value.
NO GUARANTEE is performed on guest tasks. The guarantee must be performed
by the level that inserts guest tasks in the EDF level.
If a task miss a deadline a counter is incremented.
If a task exausts the wcet a counter is incremented
No ZOMBIE support!!!!!!
 
Exceptions raised:
XUNVALID_GUEST XUNVALID_TASK
some primitives are not implemented:
task_sleep, task_delay, guest_endcycle, guest_sleep, guest_delay
 
XACTIVATION
If a task is actiated through task_activate or guest_activate more than
one time
Restrictions & special features:
- This level doesn't manage the main task.
- At init time we have to specify:
. guarantee check
(when all task are created the system will check that the task_set
will not use more than the available bandwidth)
- A function to return the used bandwidth of the level is provided.
- Functions to return and reset the nact, wcet and dline miss counters
 
**/
 
/*
* Copyright (C) 2001 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 __EDFACT_H__
#define __EDFACT_H__
 
#include <ll/ll.h>
#include <kernel/config.h>
#include <sys/types.h>
#include <kernel/types.h>
 
 
 
 
 
 
 
 
/*+ flags... +*/
#define EDFACT_ENABLE_GUARANTEE 1 /*+ Task Guarantee enabled +*/
#define EDFACT_ENABLE_ALL 1
 
#define EDFACT_FAILED_GUARANTEE 8 /*+ used in the module, unsettabl
in EDF_register_level... +*/
 
 
 
 
 
#define ELASTIC_HARD_PCLASS 0x0600
 
#define EDFACT_LEVELNAME "EDFACT base"
#define EDFACT_LEVEL_CODE 166
#define EDFACT_LEVEL_VERSION 1
 
 
/*+ Registration function:
int flags Options to be used in this level instance...
 
returns the level number at which the module has been registered.
+*/
LEVEL EDFACT_register_level(int flags);
 
/*+ Returns the used bandwidth of a level +*/
bandwidth_t EDFACT_usedbandwidth(LEVEL l);
 
/*+ returns respectively the number of dline, wcet or nact; -1 if error +*/
int EDFACT_get_dline_miss(PID p);
int EDFACT_get_wcet_miss(PID p);
int EDFACT_get_nact(PID p);
 
/*+ resets respectively the number of dline, wcet miss; -1 if error +*/
int EDFACT_reset_dline_miss(PID p);
int EDFACT_reset_wcet_miss(PID p);
 
#endif
 
/advdemos/branches/advdemos/edfact/makefile
0,0 → 1,16
#
#
#
 
ifndef BASE
BASE=../..
endif
include $(BASE)/config/config.mk
 
PROGS= testact
 
include $(BASE)/config/example.mk
 
testact:
make -f $(SUBMAKE) APP=testact INIT= OTHEROBJS="initfile.o edfact.o" OTHERINCL= SHARKOPT=__OLDCHAR__
 
/advdemos/branches/advdemos/edfact/readme
0,0 → 1,31
EDFACT Scheduling Module
------------------------
by Paolo Gai 2001
 
 
Pisa, 6, Jun 2001
 
This Module implements a EDF scheduler.
 
It is very similar to the EDF Module distributed with the kernel sources,
except that:
- It does not support hard sporadic tasks
- It does not raise a deadline exception
- It does not raise a wcet violation exception
- Instead of raising an exception, the module simply COUNTS deadline misses
and wcet exaustions..
 
Since a large part of the applications use only periodic tasks, this Module
can be a great improvement because the application will not hang up at
the first exception!!! (and this happens frequently when switching to a
slower PC :-( )
 
I also wrote a simple test to show how the module works...
 
To use the Module in your applications, simply copy the edfact.c and edfact.h
into your application directory, and register edfact instead of the
tradictional edf...
 
For bugs, questions and comments please write to pj@sssup.it
 
Paolo
/advdemos/branches/advdemos/first/test1.c
0,0 → 1,247
/*
* 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: test1.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
this test shows a set of 5 tasks (+main+dummy+keyboard driver).
The first 4 tasks are scheduled by a EDFSTAR Module, whereas the
fifth one is a standard traditional EDF task. The 4 tasks uses a
budget of 10000/100000.
if edfstar.c is compiled with edfstar_printf3 active, a couple
(dline, curtime) is showed (in ms).
if cbsstar.c is compiled with cbsstar_printf3 active, the budget
replenishments are showed.
*/
 
/*
* Copyright (C) 2002 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 "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "edfstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
int cbsstar_level, edfstar_level, mybudget;
 
EDF_register_level(EDF_ENABLE_ALL);
 
cbsstar_level = CBSSTAR_register_level(3, 0);
mybudget = CBSSTAR_setbudget(cbsstar_level, 10000, 100000);
edfstar_level = EDFSTAR_register_level(mybudget, cbsstar_level);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
//keyb_def_ctrlC(kparms, NULL);
//keyb_def_map(kparms,itaMap);
KEYB_init(&kparms);
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
 
void *star(void *arg)
{
int i,j;
 
for (i=0; i<5; i++) {
for (j=0; j<100000; j++);
cputc('°');
cputs((char *)arg);
task_endcycle();
}
 
return NULL;
}
 
void *edftask(void *arg)
{
int i,j;
 
for (i=0; i<5; i++) {
for (j=0; j<100000; j++);
cputc('°');
cputs((char *)arg);
task_endcycle();
}
 
return NULL;
}
 
void create1()
{
HARD_TASK_MODEL m1, m2;
PID p1a, p1b, p1c, p1d, p2;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_level(m1,2);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
 
hard_task_def_arg(m1,(void *)"a");
hard_task_def_mit(m1,10000);
p1a = task_create("a", star, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"b");
hard_task_def_mit(m1,15000);
p1b = task_create("b", star, &m1, NULL);
if (p1b == -1) {
perror("Could not create task b ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"c");
hard_task_def_mit(m1,20000);
p1c = task_create("c", star, &m1, NULL);
if (p1c == -1) {
perror("Could not create task c ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"d");
hard_task_def_mit(m1,30000);
p1d = task_create("d", star, &m1, NULL);
if (p1d == -1) {
perror("Could not create task d ...");
sys_end();
}
 
hard_task_default_model(m2);
hard_task_def_mit(m2,50000); // the budget has dline 100,000!
hard_task_def_wcet(m2, 5000);
hard_task_def_arg(m2,(void *)"Û");
hard_task_def_group(m2,1);
hard_task_def_periodic(m2);
 
p2 = task_create("2", edftask, &m2, NULL);
if (p2 == -1) {
perror("Could not create task edf ...");
sys_end();
}
 
cprintf("stars=%d %d %d %d, star2=%d\n", p1a, p1b, p1c, p1d, p2);
 
group_activate(1);
}
 
int main(int argc, char **argv)
{
char c;
 
clear();
 
cprintf("Hello, world!\nPress ESC to end the demo...\n");
 
create1();
 
do {
c =keyb_getch(BLOCK);
} while (c != ESC);
 
cprintf("ESC pressed!");
 
sys_end();
 
return 0;
}
 
/advdemos/branches/advdemos/first/posixstar.h
0,0 → 1,142
/*
* 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: posixstar.h,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
This file contains the scheduling module compatible with POSIX
specifications
 
Title:
POSIX version 1
 
Task Models Accepted:
NRT_TASK_MODEL - Non-Realtime Tasks
weight field is ignored
slice field is used to set the slice of a task, if it is !=0
policy field is ignored
inherit field is ignored
 
Description:
This module schedule his tasks following the POSIX specifications...
 
A task can be scheduled in a Round Robin way or in a FIFO way.
The tasks have also a priority field.
 
The slices can be different one task from one another.
 
The module can SAVE or SKIP activations
 
Exceptions raised:
XUNVALID_GUEST
This level doesn't support guests. When a guest operation
is called, the exception is raised.
 
Restrictions & special features:
- if specified, it creates at init time a task,
called "Main", attached to the function __init__().
- There must be only one module in the system that creates a task
attached to the function __init__().
- The level tries to guarantee that a RR task uses a "full" timeslice
before going to the queue tail. "full" means that a task can execute
a maximum time of slice+sys_tick due to the approx. done by
the Virtual Machine. If a task execute more time than the slice,
the next time it execute less...
 
**/
 
/*
* 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 __POSIXSTAR_H__
#define __POSIXSTAR_H__
 
#include <ll/ll.h>
#include <kernel/config.h>
#include <sys/types.h>
#include <kernel/types.h>
//#define POSIXSTAR_DEBUG
 
/*+ Const: +*/
#define POSIXSTAR_MINIMUM_SLICE 1000 /*+ Minimum Timeslice +*/
#define POSIXSTAR_MAXIMUM_SLICE 500000 /*+ Maximum Timeslice +*/
 
/*+ Registration function:
TIME slice the slice for the Round Robin queue
int createmain 1 if the level creates the main task 0 otherwise
struct multiboot_info *mb used if createmain specified
 
returns the level number at which the module has been registered.
+*/
LEVEL POSIXSTAR_register_level(int budget, int master, TIME slice,
int prioritylevels);
 
/*+ this function forces the running task to go to his queue tail,
then calls the scheduler and changes the context
(it works only on the POSIX level) +*/
int POSIXSTAR_sched_yield(LEVEL l);
 
/* the following functions have to be called with interruptions DISABLED! */
 
/*+ this function returns the maximum level allowed for the POSIX level +*/
int POSIXSTAR_get_priority_max(LEVEL l);
 
/*+ this function returns the default timeslice for the POSIX level +*/
int POSIXSTAR_rr_get_interval(LEVEL l);
 
/*+ this functions returns some paramaters of a task;
policy must be NRT_RR_POLICY or NRT_FIFO_POLICY;
priority must be in the range [0..prioritylevels]
returns ENOSYS or ESRCH if there are problems +*/
int POSIXSTAR_getschedparam(LEVEL l, PID p, int *policy, int *priority);
 
/*+ this functions sets paramaters of a task +*/
int POSIXSTAR_setschedparam(LEVEL l, PID p, int policy, int priority);
 
#endif
 
/*
MANCANO
13.3.6 GETPRIORITYMin da mettere a 0
*/
/advdemos/branches/advdemos/first/cbsstar.c
0,0 → 1,674
/*
* 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: cbsstar.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
Read CBSSTAR.h for general details.
 
Basically, a budget can be in 2 states:
- Active -> the budget queue is not empty
- Idle -> the budget queue is empty
 
The fact that a task into a budget is inserted into the master module depends
on the value of the remaining time the tasks can spend in the period.
 
The module does handle only one oslib event, used to enforce the
temporal isolation between buffers. Note that all is implemented
without using the CONTROL_CAP field.
 
Basically, for each budget there can be at most one task inserted
into the master level. Its deadline is modified according to the
usage of its capacity, that is, when a budget is exausted its
deadline is postponed.
 
*/
 
/*
* Copyright (C) 2002 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 "cbsstar.h"
#include <ll/string.h>
 
#define ACTIVE 1
#define NOACTIVE 0
#define INIT 2
 
#define CBSSTAR_IDLE APER_STATUS_BASE
/*
* DEBUG stuffs begin
*/
 
//#define CBSSTAR_DEBUG
int event_monitor;
#ifdef CBSSTAR_DEBUG
 
 
static __inline__ void fake_printf(char *fmt, ...) {}
 
//#define cbsstar_printf kern_printf
//#define cbsstar_printf2 kern_printf
//#define cbsstar_printf3 kern_printf
 
#define cbsstar_printf fake_printf
#define cbsstar_printf2 fake_printf
#define cbsstar_printf3 fake_printf
 
#if 0
void cbsstar_printq(QQUEUE *q)
{
PID p;
kern_printf("[");
p = q->first;
kern_printf("->%d",p);
while (p != NIL) {
p = proc_table[p].next;
kern_printf("->%d",p);
}
kern_printf("]");
}
#else
static __inline__ void cbsstar_printq(QQUEUE *q) {}
#endif
 
#if 0
static __inline__ void cbsstar_printblob(int x) { if (x) cputc('±'); else cputc('Û'); }
#else
static __inline__ void cbsstar_printblob(int x) {}
#endif
 
#endif
 
/*
* DEBUG stuffs end
*/
/*+ Status used in the level +*/
#define CBSSTAR_WAIT APER_STATUS_BASE /*+ waiting the service +*/
 
/* this structure contains the status for a single budget */
struct budget_struct {
TIME Q; /* budget */
TIME T; /* period */
 
struct timespec dline; /* deadline */
int dline_timer; /* oslib event for budget reactivation*/
int avail; /* current budget */
 
PID current; /* the task currently put in execution */
int flags;
IQUEUE tasks; /* a FIFO queue for the tasks handled
using the budget */
};
 
typedef struct {
level_des l; /* the standard level descriptor */
 
struct budget_struct *b; /* the budgets! */
int n; /* the maximum index for the budgets */
int freebudgets; /* number of free budgets; starts from n */
 
int tb[MAX_PROC]; /* link task->budget (used in guest_end) */
 
bandwidth_t U; /*+ the used bandwidth by the server +*/
 
int cap_lev;
 
PID on_shadow;
 
LEVEL scheduling_level;
 
} CBSSTAR_level_des;
 
 
static void CBSSTAR_deadline_timer_hardreservation(void *a)
{
struct budget_struct *b = a;
struct timespec t;
//kern_printf("*********** %d", b->dline_timer);
b->dline_timer=NIL;
/* we modify the deadline according to rule 4 ... */
/* there is a while because if the wcet is << than the system tick
we need to postpone the deadline many times */
if (b->avail<=0) {
b->avail += b->Q;
if (b->avail>b->Q) b->avail=b->Q;
 
//kern_printf("budget recharge %d", b);
}
if (b->avail>0) b->flags=ACTIVE;
/* avail may be <0 because a task executed via a shadow fo many time
b->current == NIL only if the prec task was finished and there
was not any other task to be put in the ready queue
... we are now activating the next task */
if (b->current == NIL && b->flags) {
if (iq_query_first(&(b->tasks)) != NIL) {
//struct timespec t;
CBSSTAR_level_des *lev;
PID p;
JOB_TASK_MODEL job;
//kern_gettime(&t);
//TIMESPEC_ASSIGN(&b->dline, &schedule_time);
//ADDUSEC2TIMESPEC(b->T, &b->dline);
kern_gettime(&t);
TIMESPEC_ASSIGN(&b->dline, &t);
ADDUSEC2TIMESPEC(b->T, &b->dline);
 
p = iq_getfirst(&(b->tasks));
b->current=p;
lev = (CBSSTAR_level_des *)(level_table[proc_table[p].task_level]);
//kern_printf("reinsert task p = %d lev = %d ",p,proc_table[p].task_level);
/* and, finally, we reinsert the task in the master level */
job_task_default_model(job, b->dline);
job_task_def_noexc(job);
//kern_printf("(CR:iact p%d %ld.%ld av=%d)",p,b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail);
//kern_printf("**");
level_table[ lev->scheduling_level ]->
private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
event_need_reschedule();
}
} else
if (b->current !=NIL && b->avail>0) {
kern_printf("(cap&nil ");
}
if (b->flags==NOACTIVE && b->dline_timer!=NIL){
kern_gettime(&t);
TIMESPEC_ASSIGN(&b->dline, &t);
ADDUSEC2TIMESPEC(b->T, &b->dline);
b->dline_timer=kern_event_post(&b->dline, CBSSTAR_deadline_timer_hardreservation, b);
event_monitor=b->dline_timer;
//kern_printf("(dline hard %ld.%ld ev %d)",b->dline.tv_sec,b->dline.tv_nsec/1000, b->dline_timer);
}
}
static void CBSSTAR_activation(CBSSTAR_level_des *lev,
PID p,
struct timespec *acttime)
{
JOB_TASK_MODEL job;
struct budget_struct *b = &lev->b[lev->tb[p]];
/* we have to check if the deadline and the wcet are correct before
activating a new task or an old task... */
 
/* check 1: if the deadline is before than the actual scheduling time */
 
/* check 2: if ( avail_time >= (cbs_dline - acttime)* (wcet/period) )
(rule 7 in the CBS article!) */
TIME t;
struct timespec t2,t3;
 
t = (b->T * b->avail) / b->Q;
t3.tv_sec = t / 1000000;
t3.tv_nsec = (t % 1000000) * 1000;
 
SUBTIMESPEC(&b->dline, acttime, &t2);
if (/* 1 */ TIMESPEC_A_LT_B(&b->dline, acttime) ||
/* 2 */ TIMESPEC_A_GT_B(&t3, &t2) ) {
TIMESPEC_ASSIGN(&b->dline, acttime);
ADDUSEC2TIMESPEC(b->T, &b->dline);
}
/* and the capacity */
if (b->flags==INIT) {
b->avail = b->Q;
b->flags=ACTIVE;
}
 
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf3("±%d±",lev->tb[p]);
cbsstar_printblob(lev->tb[p]);
#endif
//}
//#endif
 
/* record the current task inserted in the master module */
b->current = p;
 
//#ifdef CBSSTAR_DEBUG
//kern_printf("(CA:iact p%d %ld.%ld av=%d at=%ld.%ld)",p,b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail, acttime->tv_sec, acttime->tv_nsec/1000);
//#endif
/* and, finally, we reinsert the task in the master level */
job_task_default_model(job, b->dline);
job_task_def_noexc(job);
level_table[ lev->scheduling_level ]->
private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
//b->dline_timer=kern_event_post(&b->dline, CBSSTAR_deadline_timer_hardreservation, b);
}
 
static void CBSSTAR_account_capacity(CBSSTAR_level_des *lev, PID p)
{
struct timespec ty;
TIME tx;
struct budget_struct *b = &lev->b[lev->tb[p]];
TIME t;
struct timespec t2,t3, acttime;
 
if (lev->cap_lev!=NIL && b->current==p) {
kern_event_delete(lev->cap_lev);
lev->cap_lev=NIL;
}
 
kern_gettime(&acttime);
t = (b->T * b->avail) / b->Q;
t3.tv_sec = t / 1000000;
t3.tv_nsec = (t % 1000000) * 1000;
 
SUBTIMESPEC(&b->dline, &acttime, &t2);
SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
tx = TIMESPEC2USEC(&ty);
lev->b[lev->tb[p]].avail -= tx;
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf2("(C:cap p%d av=%d)", p, lev->b[lev->tb[p]].avail);
#endif
if (lev->b[lev->tb[p]].avail<=0 || TIMESPEC_A_GT_B(&t3, &t2)) lev->b[lev->tb[p]].flags=NOACTIVE;
 
if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time) ) {
/* we modify the deadline ... */
TIMESPEC_ASSIGN(&b->dline, &schedule_time);
ADDUSEC2TIMESPEC(b->T, &b->dline);
}
 
//if (b->flags==NOACTIVE && b->dline_timer!=NIL)
// kern_printf("flags %d, dline_timer %d", b->flags, b->dline_timer);
if (b->flags==NOACTIVE && b->dline_timer==NIL) {
b->dline_timer=kern_event_post(&b->dline, CBSSTAR_deadline_timer_hardreservation, b);
event_monitor=b->dline_timer;
//kern_printf("(dline %ld.%ld ev %d)",b->dline.tv_sec,b->dline.tv_nsec/1000, b->dline_timer);
}
 
}
 
 
/* The on-line guarantee is enabled only if the appropriate flag is set... */
static int CBSSTAR_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(C:gua)");
#endif
 
if (*freebandwidth >= lev->U) {
*freebandwidth -= lev->U;
return 1;
}
else
return 0;
}
 
static void capacity_handler(void *l)
{
//kern_printf("!");
CBSSTAR_level_des *lev =l;
lev->cap_lev=NIL;
event_need_reschedule();
}
 
static int CBSSTAR_private_eligible(LEVEL l, PID p)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
struct budget_struct *b = &lev->b[lev->tb[p]];
JOB_TASK_MODEL job;
 
#ifdef CBSSTAR_DEBUG
//kern_printf("(C:eli %d",p);
#endif
 
/* we have to check if the deadline and the wcet are correct...
if the CBSSTAR level schedules in background with respect to others
levels, there can be the case in witch a task is scheduled by
schedule_time > CBSSTAR_deadline; in this case (not covered in the
article because if there is only the standard scheduling policy
this never apply) we reassign the deadline */
if (b->current==p) {
if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
if (lev->cap_lev!=NIL) {
kern_event_delete(lev->cap_lev);
lev->cap_lev=NIL;
}
/* we kill the current activation */
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level, p);
/* we modify the deadline ... */
TIMESPEC_ASSIGN(&b->dline, &schedule_time);
ADDUSEC2TIMESPEC(b->T, &b->dline);
 
/* and the capacity */
b->avail = b->Q;
b->flags=ACTIVE;
 
if (b->dline_timer!=NIL) {
kern_event_delete(b->dline_timer);
b->dline_timer=NIL;
}
//#ifdef CBSSTAR_DEBUG
//kern_printf(" %ld.%ld av=%d)",b->dline.tv_sec,b->dline.tv_nsec/1000, b->Q);
//cbsstar_printf3("±%d±",lev->tb[p]);
//cbsstar_printblob(lev->tb[p]);
//#endif
 
/* and, finally, we reinsert the task in the master level */
job_task_default_model(job, b->dline);
job_task_def_noexc(job);
//kern_printf("(CE:iact p%d %ld.%ld av=%d)",p,b->dline.tv_sec,b->dline.tv_nsec/1000, b->avail);
level_table[ lev->scheduling_level ]->
private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
//kern_printf("task %d, avail %d", p, b->avail);
return -1;
}
}
#ifdef CBSSTAR_DEBUG
cbsstar_printf(")");
#endif
 
return 0;
}
 
static void CBSSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
{
/* A task has been activated for some reason. Basically, the task is
inserted in the queue if the queue is empty, otherwise the task is
inserted into the master module, and an oslib event is posted. */
 
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
BUDGET_TASK_MODEL *budget;
 
if (m->pclass != BUDGET_PCLASS ||
(m->level != 0 && m->level != l)) {
kern_raise(XINVALID_TASK, p);
return;
}
budget = (BUDGET_TASK_MODEL *)m;
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(C:gcr %d b%d", p, budget->b);
#endif
 
lev->tb[p] = budget->b;
 
if (lev->b[budget->b].current == NIL && lev->b[budget->b].flags ) {
/* This is the first task in the budget,
the task have to be inserted into the master module */
struct timespec t;
kern_gettime(&t);
CBSSTAR_activation(lev,p,&t);
} else {
/* The budget is not empty, another task is already into the
master module, so the task is inserted at the end of the budget
queue */
iq_insertlast(p,&lev->b[budget->b].tasks);
//#ifdef CBSSTAR_DEBUG
//kern_printf(" ilast flag %d task %d",lev->b[budget->b].flags,lev->b[budget->b].current);
// cbsstar_printq(&lev->b[budget->b].tasks);
//#endif
}
#ifdef CBSSTAR_DEBUG
cbsstar_printf(")");
#endif
}
 
static void CBSSTAR_private_extract(LEVEL l, PID p)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
//#ifdef CBSSTAR_DEBUG
//kern_printf("(C:gend p%d c%d av=%d)", p, lev->b[lev->tb[p]].current, lev->b[lev->tb[p]].avail);
//cbsstar_printq(&lev->b[lev->tb[p]].tasks);
//#endif
 
/* a task is removed from execution for some reasons. It must be
that it is the first in its budget queue (only the first task in
a budget queue is put into execution!) */
 
/* remove the task from execution (or from the ready queue) */
if (lev->b[lev->tb[p]].current == p) {
 
CBSSTAR_account_capacity(lev,p);
/* remove the task from the master module */
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level, p);
 
#ifdef CBSSTAR_DEBUG
cbsstar_printq(&lev->b[lev->tb[p]].tasks);
#endif
 
/* check if the buffer has someone else to schedule */
if (iq_query_first(&lev->b[lev->tb[p]].tasks) == NIL) {
/* the buffer has no tasks! */
lev->b[lev->tb[p]].current = NIL;
}
else if (lev->b[lev->tb[p]].flags) {
/* if so, insert the new task into the master module */
PID n;
struct timespec t;
kern_gettime(&t);
n = iq_getfirst(&lev->b[lev->tb[p]].tasks);
//#ifdef CBSSTAR_DEBUG
//kern_printf("{p%d n%d}",p,n);
//#endif
CBSSTAR_activation(lev,n,&t); // it modifies b[lev->tb[p]].current
}
else
lev->b[lev->tb[p]].current=NIL;
 
}
else {
iq_extract(p, &lev->b[lev->tb[p]].tasks);
}
}
 
static void CBSSTAR_private_dispatch(LEVEL l, PID p, int nostop)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
struct timespec ty;
 
//#ifdef CBSSTAR_DEBUG
//kern_printf("(C:gdisp p%d c%d av=%d)", p, lev->b[lev->tb[p]].current, lev->b[lev->tb[p]].avail);
// cbsstar_printq(&lev->b[lev->tb[p]].tasks);
//#endif
 
/* the current task (that is the only one inserted in the master module
for the corresponding budget) is dispatched. Note that the current
task is not inserted in any FIFO queue, so the task does not have to
be extracted! */
 
/* ... then, we dispatch it to the master level */
level_table[ lev->scheduling_level ]->
private_dispatch(lev->scheduling_level,p,nostop);
 
/* ...and finally, we have to post a capacity event */
if (!nostop) {
TIMESPEC_ASSIGN(&ty, &schedule_time);
ADDUSEC2TIMESPEC(lev->b[lev->tb[p]].avail,&ty);
lev->cap_lev = kern_event_post(&ty,capacity_handler, lev);
}
}
 
static void CBSSTAR_private_epilogue(LEVEL l, PID p)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
struct budget_struct *b = &lev->b[lev->tb[p]];
 
 
//#ifdef CBSSTAR_DEBUG
//kern_printf("(C:gepi %d %d",p, b->current);
//#endif
 
if (p==b->current) {
CBSSTAR_account_capacity(lev,p);
 
// L'evento di capacità va cancellato perchè sarà ripristinato nella successiva dispatch
/* we have to check if the capacity is still available */
if (b->flags) {
/* there is capacity available, maybe it is simply a preemption;
the task have to return to the ready queue */
level_table[ lev->scheduling_level ]->
private_epilogue(lev->scheduling_level,p);
#ifdef CBSSTAR_DEBUG
//kern_printf("(ep *av=%d", b->avail);
#endif
} else {
/* we kill the current activation */
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level, p);
//kern_printf("extract");
iq_insertfirst(p, &b->tasks);
proc_table[p].status = CBSSTAR_IDLE;
b->current = NIL;
//kern_printf("budget finish %d", b);
}
#ifdef CBSSTAR_DEBUG
cbsstar_printf(")");
#endif
}
 
}
 
/* Registration functions }*/
 
/*+ Registration function:
int flags the init flags ... see CBSSTAR.h +*/
LEVEL CBSSTAR_register_level(int n, LEVEL master)
{
LEVEL l; /* the level that we register */
CBSSTAR_level_des *lev; /* for readableness only */
PID i; /* a counter */
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("CBSSTAR_register_level\n");
#endif
 
/* request an entry in the level_table */
l = level_alloc_descriptor(sizeof(CBSSTAR_level_des));
 
lev = (CBSSTAR_level_des *)level_table[l];
 
printk(" lev=%d\n",(int)lev);
 
/* fill the standard descriptor */
lev->l.private_insert = CBSSTAR_private_insert;
lev->l.private_extract = CBSSTAR_private_extract;
lev->l.private_eligible = CBSSTAR_private_eligible;
lev->l.private_dispatch = CBSSTAR_private_dispatch;
lev->l.private_epilogue = CBSSTAR_private_epilogue;
 
lev->l.public_guarantee = CBSSTAR_public_guarantee;
 
/* fill the CBSSTAR descriptor part */
lev->b = (struct budget_struct *)kern_alloc(sizeof(struct budget_struct)*n);
 
for (i=0; i<n; i++) {
lev->b[i].Q = 0;
lev->b[i].T = 0;
NULL_TIMESPEC(&lev->b[i].dline);
lev->b[i].dline_timer = NIL;
lev->b[i].avail = 0;
lev->b[i].current = -1;
lev->b[i].flags=INIT;
iq_init(&lev->b[i].tasks, &freedesc, 0);
}
 
lev->n = n;
lev->freebudgets = 0;
 
for (i=0; i<MAX_PROC; i++)
lev->tb[i] = NIL;
 
lev->U = 0;
lev->cap_lev=NIL;
lev->scheduling_level = master;
lev->on_shadow=NIL;
 
return l;
}
 
int CBSSTAR_setbudget(LEVEL l, TIME Q, TIME T)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(C:sbud)");
#endif
 
if (lev->freebudgets != lev->n) {
bandwidth_t b;
b = (MAX_BANDWIDTH / T) * Q;
/* really update lev->U, checking an overflow... */
if (Q< T && MAX_BANDWIDTH - lev->U > b) {
int r = lev->freebudgets; // the return value
lev->U += b;
lev->freebudgets++;
lev->b[r].Q = Q;
lev->b[r].T = T;
return r;
}
else
return -2;
}
else
return -1;
}
/advdemos/branches/advdemos/first/test2.c
0,0 → 1,241
/*
* 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: test2.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
The purpose of this test is to show that two budgets with different
period and capacity schedules correctly.
 
4 periodic tasks are involved
*/
 
/*
* Copyright (C) 2002 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 "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "edfstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
int cbsstar_level, edfstar_level, edfstar_level2, mybudget, mybudget2;
clear();
EDF_register_level(EDF_ENABLE_ALL);
 
cbsstar_level = CBSSTAR_register_level(3, 0);
 
mybudget = CBSSTAR_setbudget(cbsstar_level, 1000, 50000);
edfstar_level = EDFSTAR_register_level(mybudget, cbsstar_level);
 
mybudget2 = CBSSTAR_setbudget(cbsstar_level, 10000, 25000);
edfstar_level2 = EDFSTAR_register_level(mybudget2, cbsstar_level);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
cprintf("edfstar_level=%d, edfstar_level2=%d\n",
edfstar_level,edfstar_level2);
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
 
void *star(void *arg)
{
int i,j,z;
 
for (i=0; i<100; i++) {
for (z=0; z<5; z++) {
for (j=0; j<60000; j++);
cputs((char *)arg);
}
task_endcycle();
}
 
return NULL;
}
 
// version for the "slow" budget
void *slow(void *arg)
{
int i,j,z;
 
for (i=0; i<15; i++) {
for (z=0; z<5; z++) {
for (j=0; j<200000; j++);
cputs((char *)arg);
}
task_endcycle();
}
 
return NULL;
}
 
void create1()
{
HARD_TASK_MODEL m1;
PID p1a, p1b, p1c, p1d;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
 
 
 
 
hard_task_def_level(m1,2);
 
hard_task_def_arg(m1,(void *)".");
hard_task_def_mit(m1,5000);
p1a = task_create("a", slow, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)",");
hard_task_def_mit(m1,5000);
p1b = task_create("b", slow, &m1, NULL);
if (p1b == -1) {
perror("Could not create task b ...");
sys_end();
}
 
 
 
 
hard_task_def_level(m1,3);
 
hard_task_def_arg(m1,(void *)"o");
hard_task_def_mit(m1,5000);
p1c = task_create("c", star, &m1, NULL);
if (p1c == -1) {
perror("Could not create task c ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"O");
hard_task_def_mit(m1,5000);
p1d = task_create("d", star, &m1, NULL);
if (p1d == -1) {
perror("Could not create task d ...");
sys_end();
}
 
group_activate(1);
}
 
int main(int argc, char **argv)
{
char c;
 
cprintf("Hello, world!");
 
create1();
 
do {
c =keyb_getch(BLOCK);
} while (c != ESC);
 
cprintf("ESC pressed!");
 
sys_end();
 
return 0;
}
 
/advdemos/branches/advdemos/first/test3.c
0,0 → 1,213
/*
* 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: test3.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
The purpose of this test is to show that two budgets with different
period and budgets schedules correctly.
 
2 never ending tasks are involved
*/
 
/*
* Copyright (C) 2002 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 "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "edfstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
int cbsstar_level, edfstar_level, edfstar_level2, mybudget, mybudget2;
clear();
EDF_register_level(EDF_ENABLE_ALL);
 
cbsstar_level = CBSSTAR_register_level(3, 0);
 
mybudget = CBSSTAR_setbudget(cbsstar_level, 2000, 50000);
edfstar_level = EDFSTAR_register_level(mybudget, cbsstar_level);
 
mybudget2 = CBSSTAR_setbudget(cbsstar_level, 10000, 25000);
edfstar_level2 = EDFSTAR_register_level(mybudget2, cbsstar_level);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
cprintf("edfstar_level=%d, edfstar_level2=%d\n",
edfstar_level,edfstar_level2);
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
#include <semaphore.h>
 
sem_t s;
 
void *star(void *arg)
{
int j,z;
 
for (;;) {
for (z=0; z<5; z++) {
for (j=0; j<60000; j++);
sem_wait(&s);
cputs((char *)arg);
sem_post(&s);
}
}
 
return NULL;
}
 
 
void create1()
{
HARD_TASK_MODEL m1;
PID p1a, p1c;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
 
 
 
 
hard_task_def_level(m1,2);
 
hard_task_def_arg(m1,(void *)"O");
hard_task_def_mit(m1,5000);
p1a = task_create("a", star, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
 
hard_task_def_level(m1,3);
 
hard_task_def_arg(m1,(void *)".");
hard_task_def_mit(m1,5000);
p1c = task_create("c", star, &m1, NULL);
if (p1c == -1) {
perror("Could not create task c ...");
sys_end();
}
 
group_activate(1);
}
 
void endfun(KEY_EVT *k)
{
cprintf("ESC pressed!");
 
sys_end();
}
 
int main(int argc, char **argv)
{
KEY_EVT k;
 
sem_init(&s,0,1);
 
k.flag = 0;
k.scan = KEY_ESC;
k.ascii = 27;
keyb_hook(k,endfun);
 
create1();
 
return 0;
}
 
/advdemos/branches/advdemos/first/iqueue.h
0,0 → 1,172
/*
* 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: iqueue.h,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
*/
 
/*
* Copyright (C) 2002 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
*
*/
 
 
/*
IQUEUEs
 
This file contains functions that helps to manage task queues.
 
These functions are different from the functions that manages the
QUEUE and QQUEUE types. In particular, these functions no more relies
on the prev & next fields of the task descriptor. In that way, tasks
can be inserted in more than one queue at a time.
 
Basically, an IQUEUE has an "I"nternal prev/next structure, that may
be shared between one or more queue. Of course, the user MUST
guarantee that the same task will not be inserted in two IQUEUEs that
share the same prev/next buffer.
 
The queue insertion is made by the following functions:
iq_insert -> insertion based on the priority field.
iq_timespec_insert -> same as above but use the timespec_priority field
iq_insertfirst -> insert in the first position of the queue
*/
 
#include <kernel/const.h>
#include <kernel/types.h>
#include <sys/types.h>
 
#define IQUEUE_NO_PRIORITY 1
#define IQUEUE_NO_TIMESPEC 2
 
struct IQUEUE_shared {
PID prev[MAX_PROC];
PID next[MAX_PROC];
struct timespec *timespec_priority;
DWORD *priority;
};
 
typedef struct {
PID first;
PID last;
struct IQUEUE_shared *s;
} IQUEUE;
 
 
 
/* Internal queue initialization:
 
share = &x -> the internal data structure of the IQUEUE x is used
to enqueue the tasks.
 
share = NULL -> an internal data structure to handle prev/next
pairs is dynamically allocated (The amount of
memory that is allocated can be reduced using the
flags).
 
flags can be used to reduce the memory usage of an IQUEUE when share=NULL:
IQUEUE_NO_PRIORITY -> the iqueue do not provide internally a priority field
IQUEUE_NO_TIMESPEC -> the iqueue do not provide internally a timespec field
 
- note that, if these flags are used, the corresponding insert
functions will not work!
- the default value for the flags is, of course, 0
*/
void iq_init (IQUEUE *q, IQUEUE *share, int flags);
 
/* Queue insert functions:
 
- inserts a p into the q. p must not be already inserted into q.
- four versions of the function;
- iq_priority_insert -> ordered insertion using the priority field
- iq_timespec_insert -> ordered insertion using the timespec field
- iq_insertfirst -> insert at the first position of the queue
- iq_insertlast -> insert at the last position of the queue
*/
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);
 
/* Queue extract functions:
 
- extracts a task p from the queue q.
- three versions of the function;
- iq_extract -> extracts given a task p
(that must be inserted in the queue)
 
- iq_getfirst -> extracts the first task in the queue,
NIL if the queue is empty
- iq_getlast -> extracts the last task in the queue,
NIL if the queue is empty
 
*/
void iq_extract (PID p, IQUEUE *q);
PID iq_getfirst ( IQUEUE *q);
PID iq_getlast ( IQUEUE *q);
 
 
/* Queue query functions:
 
The first two functions return the first and the last task in the queue,
NIL if the queue is empty.
 
The second two functions can be used to get/set the priority or the
timespec field used when queuing.
*/
static __inline__ PID iq_queryfirst(IQUEUE *q)
{
return q->first;
}
 
static __inline__ PID iq_querylast(IQUEUE *q)
{
return q->last;
}
 
static __inline__ struct timespec *iq_query_timespec(PID p, IQUEUE *q)
{
return &q->s->timespec_priority[p];
}
 
static __inline__ DWORD *iq_query_priority (PID p, IQUEUE *q)
{
return &q->s->priority[p];
}
/advdemos/branches/advdemos/first/test4.c
0,0 → 1,231
/*
* 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: test4.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
The purpose of this test is to show that two budgets with different
period and budgets schedules correctly.
2 never ending tasks are involved
*/
 
/*
* Copyright (C) 2002 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 "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "edfstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
int cbsstar_level;
int edfstar_level, edfstar_level2, edfstar_level3;
int mybudget, mybudget2;
 
clear();
 
EDF_register_level(EDF_ENABLE_ALL);
 
cbsstar_level = CBSSTAR_register_level(3, 0);
 
mybudget = CBSSTAR_setbudget(cbsstar_level, 2000, 50000);
edfstar_level = EDFSTAR_register_level(mybudget, cbsstar_level);
 
mybudget2 = CBSSTAR_setbudget(cbsstar_level, 10000, 25000);
edfstar_level2 = EDFSTAR_register_level(mybudget2, cbsstar_level);
edfstar_level3 = EDFSTAR_register_level(mybudget2, cbsstar_level);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
cprintf("edfstar_level=%d, edfstar_level2=%d\n",
edfstar_level,edfstar_level2);
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
//keyb_def_ctrlC(kparms, NULL);
//keyb_def_map(kparms,itaMap);
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
#include <semaphore.h>
 
sem_t s;
 
void *star(void *arg)
{
int j,z;
 
for (;;) {
for (z=0; z<50; z++) {
for (j=0; j<60000; j++);
// sem_wait(&s);
cputs((char *)arg);
// sem_post(&s);
}
task_endcycle();
}
 
return NULL;
}
 
 
void create1()
{
HARD_TASK_MODEL m1;
PID p1a, p1b, p1c;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
 
 
 
 
hard_task_def_level(m1,2);
 
hard_task_def_arg(m1,(void *)"O");
hard_task_def_mit(m1,5000);
p1a = task_create("a", star, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
 
hard_task_def_level(m1,3);
 
hard_task_def_arg(m1,(void *)".");
hard_task_def_mit(m1,5000);
p1b = task_create("b", star, &m1, NULL);
if (p1b == -1) {
perror("Could not create task c ...");
sys_end();
}
 
hard_task_def_level(m1,4);
 
hard_task_def_arg(m1,(void *)",");
hard_task_def_mit(m1,5000);
p1c = task_create("c", star, &m1, NULL);
if (p1c == -1) {
perror("Could not create task c ...");
sys_end();
}
 
group_activate(1);
}
 
void endfun(KEY_EVT *k)
{
cprintf("ESC pressed!");
 
sys_end();
}
 
int main(int argc, char **argv)
{
KEY_EVT k;
 
sem_init(&s,0,1);
 
k.flag = 0;
k.scan = KEY_ESC;
k.ascii = 27;
keyb_hook(k,endfun);
 
create1();
 
return 0;
}
 
/advdemos/branches/advdemos/first/test5.c
0,0 → 1,248
/*
* 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: test5.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
The purpose of this test is to show that two budgets with different
period and budgets schedules correctly.
2 never ending tasks are involved
*/
 
/*
* Copyright (C) 2002 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 "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "edfstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
int cbsstar_level;
int edfstar_level, edfstar_level2, edfstar_level3;
int mybudget, mybudget2;
 
clear();
 
EDF_register_level(EDF_ENABLE_ALL);
 
cbsstar_level = CBSSTAR_register_level(3, 0);
 
mybudget = CBSSTAR_setbudget(cbsstar_level, 2000, 50000);
edfstar_level = EDFSTAR_register_level(mybudget, cbsstar_level);
 
mybudget2 = CBSSTAR_setbudget(cbsstar_level, 10000, 25000);
edfstar_level2 = EDFSTAR_register_level(mybudget2, cbsstar_level);
edfstar_level3 = EDFSTAR_register_level(mybudget2, cbsstar_level);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
cprintf("edfstar_level=%d, edfstar_level2=%d\n",
edfstar_level,edfstar_level2);
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
CBS_register_level(CBS_ENABLE_ALL, edfstar_level3);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
//keyb_def_ctrlC(kparms, NULL);
//keyb_def_map(kparms,itaMap);
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
#include <semaphore.h>
 
sem_t s;
 
void *star(void *arg)
{
int j,z;
 
for (;;) {
for (z=0; z<50; z++) {
for (j=0; j<60000; j++);
// sem_wait(&s);
cputs((char *)arg);
// sem_post(&s);
}
task_endcycle();
}
 
return NULL;
}
 
 
void create1()
{
HARD_TASK_MODEL m1;
SOFT_TASK_MODEL ms;
PID p1a, p1b, p1c, p2;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
 
 
 
 
hard_task_def_level(m1,2);
 
hard_task_def_arg(m1,(void *)"O");
hard_task_def_mit(m1,5000);
p1a = task_create("a", star, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
 
hard_task_def_level(m1,3);
 
hard_task_def_arg(m1,(void *)".");
hard_task_def_mit(m1,50000);
p1b = task_create("b", star, &m1, NULL);
if (p1b == -1) {
perror("Could not create task c ...");
sys_end();
}
 
hard_task_def_level(m1,4);
 
hard_task_def_arg(m1,(void *)",");
hard_task_def_mit(m1,50000);
p1c = task_create("c", star, &m1, NULL);
if (p1c == -1) {
perror("Could not create task c ...");
sys_end();
}
 
soft_task_default_model(ms);
soft_task_def_met(ms, 5000);
soft_task_def_period(ms, 30000);
soft_task_def_group(ms,1);
soft_task_def_periodic(ms);
soft_task_def_level(ms,8);
soft_task_def_arg(ms,(void *)"X");
p2 = task_create("S", star, &ms, NULL);
if (p2 == -1) {
perror("Could not create task S ...");
sys_end();
}
 
group_activate(1);
}
 
void endfun(KEY_EVT *k)
{
cprintf("ESC pressed!");
 
sys_end();
}
 
int main(int argc, char **argv)
{
KEY_EVT k;
 
sem_init(&s,0,1);
 
k.flag = 0;
k.scan = KEY_ESC;
k.ascii = 27;
keyb_hook(k,endfun);
 
create1();
 
return 0;
}
 
/advdemos/branches/advdemos/first/test6.c
0,0 → 1,248
/*
* 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: test6.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
this test shows a set of 5 tasks (+main+dummy+keyboard driver).
The first 4 tasks are scheduled by a RMSTAR Module, whereas the
fifth one is a standard traditional EDF task. The 4 tasks uses a
budget of 10000/100000.
if edfstar.c is compiled with edfstar_printf3 active, a couple
(dline, curtime) is showed (in ms).
if cbsstar.c is compiled with cbsstar_printf3 active, the budget
replenishments are showed.
*/
 
/*
* Copyright (C) 2002 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 "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "rmstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
int cbsstar_level, rmstar_level, mybudget;
 
EDF_register_level(EDF_ENABLE_ALL);
 
cbsstar_level = CBSSTAR_register_level(3, 0);
mybudget = CBSSTAR_setbudget(cbsstar_level, 10000, 100000);
rmstar_level = RMSTAR_register_level(mybudget, cbsstar_level);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
//keyb_def_ctrlC(kparms, NULL);
//keyb_def_map(kparms,itaMap);
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
 
void *star(void *arg)
{
int i,j;
 
for (i=0; i<5; i++) {
for (j=0; j<100000; j++);
cputc('°');
cputs((char *)arg);
task_endcycle();
}
 
return NULL;
}
 
void *edftask(void *arg)
{
int i,j;
 
for (i=0; i<5; i++) {
for (j=0; j<100000; j++);
cputc('°');
cputs((char *)arg);
task_endcycle();
}
 
return NULL;
}
 
void create1()
{
HARD_TASK_MODEL m1, m2;
PID p1a, p1b, p1c, p1d, p2;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_level(m1,2);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
 
hard_task_def_arg(m1,(void *)"a");
hard_task_def_mit(m1,10000);
p1a = task_create("a", star, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"b");
hard_task_def_mit(m1,15000);
p1b = task_create("b", star, &m1, NULL);
if (p1b == -1) {
perror("Could not create task b ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"c");
hard_task_def_mit(m1,20000);
p1c = task_create("c", star, &m1, NULL);
if (p1c == -1) {
perror("Could not create task c ...");
sys_end();
}
 
hard_task_def_arg(m1,(void *)"d");
hard_task_def_mit(m1,30000);
p1d = task_create("d", star, &m1, NULL);
if (p1d == -1) {
perror("Could not create task d ...");
sys_end();
}
 
hard_task_default_model(m2);
hard_task_def_mit(m2,50000); // the budget has dline 100,000!
hard_task_def_wcet(m2, 5000);
hard_task_def_arg(m2,(void *)"Û");
hard_task_def_group(m2,1);
hard_task_def_periodic(m2);
 
p2 = task_create("2", edftask, &m2, NULL);
if (p2 == -1) {
perror("Could not create task edf ...");
sys_end();
}
 
cprintf("stars=%d %d %d %d, star2=%d\n", p1a, p1b, p1c, p1d, p2);
 
group_activate(1);
}
 
int main(int argc, char **argv)
{
char c;
 
clear();
 
cprintf("Hello, world!");
 
create1();
 
do {
c =keyb_getch(BLOCK);
} while (c != ESC);
 
cprintf("ESC pressed!");
 
sys_end();
 
return 0;
}
 
/advdemos/branches/advdemos/first/test7.c
0,0 → 1,338
/*
* 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: test7.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
this test shows a set of 5 tasks (+main+dummy+keyboard driver).
The first 4 tasks are scheduled by a EDFSTAR Module, whereas the
fifth one is a standard traditional EDF task. The 4 tasks uses a
budget of 10000/100000.
if edfstar.c is compiled with edfstar_printf3 active, a couple
(dline, curtime) is showed (in ms).
if cbsstar.c is compiled with cbsstar_printf3 active, the budget
replenishments are showed.
*/
 
/*
* Copyright (C) 2002 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 "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "posixstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "modules/pi.h"
#include "modules/nop.h"
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
int cbsstar_level, posixstar_level, mybudget, mybudget1, posixstar_level1;
 
EDF_register_level(EDF_ENABLE_ALL);
 
cbsstar_level = CBSSTAR_register_level(3, 0);
mybudget = CBSSTAR_setbudget(cbsstar_level, 15000, 30000);
mybudget1 = CBSSTAR_setbudget(cbsstar_level, 14000, 56000);
posixstar_level = POSIXSTAR_register_level(mybudget, cbsstar_level, 3000,1);
posixstar_level1 = POSIXSTAR_register_level(mybudget1, cbsstar_level, 5000,1);
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
// for the keyboard...
//CBS_register_level(CBS_ENABLE_ALL, 0);
 
//SEM_register_module();
PI_register_module();
NOP_register_module();
return TICK;
}
 
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
//CABS_register_module();
//keyb_def_map(kparms,itaMap);
//KEYB_init(&kparms);
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
#include <semaphore.h>
 
mutex_t s;
 
void *star(void *arg)
{
int j;
for (;;) {
for (j=0; j<5000; j++);
//sem_wait(&s);
mutex_lock(&s);
cputc('°');
cputs((char *)arg);
mutex_unlock(&s);
//kern_printf("ril");
//sem_post(&s);
//task_endcycle();
}
 
return NULL;
}
 
void *edftask(void *arg)
{
int i,j;
while(1) {
for (i=0;i<5; i++) {
for (j=0; j<10; j++);
//sem_wait(&s);
//mutex_lock(&s);
cputc('°');
cputs((char *)arg);
//mutex_unlock(&s);
//sem_post(&s);
}
 
task_endcycle();
}
 
return NULL;
}
 
 
void create1()
{
int i;
NRT_TASK_MODEL m1;
HARD_TASK_MODEL m2;
PID p1a, p1b, p1c[20],p2,p3;
struct timespec fineprg;
nrt_task_default_model(m1);
nrt_task_def_group(m1, 1);
nrt_task_def_level(m1,2);
nrt_task_def_arg(m1,(void *)"A");
nrt_task_def_weight(m1,0);
p1a = task_create("a",star,&m1,NULL);
if (p1a == -1) {
perror("Could not create task <Write>");
sys_abort(-1);
}
nrt_task_def_arg(m1,(void *)"B");
nrt_task_def_group(m1, 1);
nrt_task_def_level(m1,2);
p1b = task_create("b", star, &m1, NULL);
if (p1b == -1) {
perror("Could not create task b ...");
sys_end();
}
nrt_task_def_arg(m1,(void *)"1");
nrt_task_def_group(m1, 1);
nrt_task_def_level(m1,2);
 
p1c[5] = task_create("1", star, &m1, NULL);
if (p1c[5] == -1) {
perror("Could not create task b ...");
sys_end();
}
 
nrt_task_def_arg(m1,(void *)"C");
nrt_task_def_group(m1, 1);
nrt_task_def_level(m1,2);
p1c[4] = task_create("c", star, &m1, NULL);
if (p1c[4] == -1) {
perror("Could not create task b ...");
sys_end();
}
 
nrt_task_def_arg(m1,(void *)"D");
nrt_task_def_group(m1, 1);
nrt_task_def_level(m1,2);
p1c[5] = task_create("d", star, &m1, NULL);
if (p1c[5] == -1) {
perror("Could not create task b ...");
sys_end();
}
nrt_task_def_arg(m1,(void *)"E");
nrt_task_def_group(m1, 1);
nrt_task_def_level(m1,2);
p1c[0] = task_create("e", star, &m1, NULL);
if (p1c[0] == -1) {
perror("Could not create task b ...");
sys_end();
}
 
nrt_task_def_arg(m1,(void *)"F");
p1c[1] = task_create("f", star, &m1, NULL);
if (p1c[1] == -1) {
perror("Could not create task b ...");
sys_end();
}
 
nrt_task_def_arg(m1,(void *)"G");
nrt_task_def_group(m1, 1);
nrt_task_def_level(m1,2);
p1c[2] = task_create("g", star, &m1, NULL);
if (p1c[2] == -1) {
perror("Could not create task b ...");
sys_end();
}
 
nrt_task_def_arg(m1,(void *)"H");
p1c[3] = task_create("h", star, &m1, NULL);
if (p1c[3] == -1) {
perror("Could not create task b ...");
sys_end();
}
nrt_task_def_arg(m1,(void *)"I");
p1c[4] = task_create("h", star, &m1, NULL);
if (p1c[4] == -1) {
perror("Could not create task b ...");
sys_end();
}
 
hard_task_default_model(m2);
hard_task_def_ctrl_jet(m2);
hard_task_def_mit(m2,32000); // the budget has dline 100,000!
hard_task_def_wcet(m2, 3000);
hard_task_def_arg(m2,(void *)"X");
hard_task_def_group(m2,1);
hard_task_def_periodic(m2);
p2 = task_create("2", edftask, &m2, NULL);
if (p2 == -1) {
perror("Could not create task edf ...");
sys_end();
}
 
hard_task_def_mit(m2,32000); // the budget has dline 100,000!
hard_task_def_wcet(m2, 3000);
hard_task_def_arg(m2,(void *)"K");
p3 = task_create("3", edftask, &m2, NULL);
if (p3 == -1) {
perror("Could not create task edf ...");
sys_end();
}
 
cprintf("stars=%d", p2);
fineprg.tv_sec=140;
fineprg.tv_nsec=0;
kern_event_post(&fineprg,(void(*)(void *))sys_end, NULL);
group_activate(1);
}
 
int main(int argc, char **argv)
{
char c='t';
PI_mutexattr_t a;
PI_mutexattr_default(a);
 
//NOP_mutexattr_t a;
//NOP_mutexattr_default(a);
 
 
mutex_init(&s,&a);
 
clear();
 
cprintf("Hello, world!\nPress ESC to end the demo...\n");
 
create1();
 
do {
//c =keyb_getch(BLOCK);
// cprintf("[]");
} while (c != ESC);
 
cprintf("ESC pressed!");
 
sys_end();
 
return 0;
}
 
/advdemos/branches/advdemos/first/cbsstar.h
0,0 → 1,157
/*
* 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: cbsstar.h,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
This file contains the budget support for the multiapplication
scheduling algorithm proposed in the framework of the FIRST Project
 
Title:
CBSSTAR
 
Task Models Accepted:
None!
 
Guest Models Accepted:
BUDGET_TASK_MODEL - A task that is attached to a budget
int b; --> the number of the budget which the task is attached to
 
Description:
This module schedule its tasks following the CBS scheme.
Every task is inserted using the guest calls.
The module defines a limited set of budgets that the application
can use. Every guest task will use a particular budget; FIFO
scheduling is used inside a budget to schedule more than one ready
task attached to the same budget.
 
The tasks are inserted in an EDF level (or similar) with a JOB_TASK_MODEL,
and the CBS level expects that the task is scheduled with the absolute
deadline passed in the model.
 
This module tries to implement a simplified version of the guest
task interface:
- To insert a guest task, use guest_create
- When a task is dispatched, use guest_dispatch
- When a task have to be suspended, you have to use:
-> preemption: use guest_epilogue
-> synchronization, end: use guest_end
Remember: no check is done on the budget number passed with the model!!!
 
Exceptions raised:
XUNVALID_TASK
This level doesn't support normal tasks, but just guest tasks.
When a task operation is called, an exception is raised.
 
Restrictions & special features:
- This level doesn't manage the main task.
- At init time we have to specify:
. guarantee check
(when all task are created the system will check that the task_set
will not use more than the available bandwidth)
- A function to return the used bandwidth of the level is provided.
 
- A function is provided to allocate a buffer.
*/
 
/*
* Copyright (C) 2002 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 __CBSSTAR_H__
#define __CBSSTAR_H__
 
#include <kernel/kern.h>
 
//#include <ll/ll.h>
//#include <kernel/config.h>
//#include <sys/types.h>
//#include <kernel/types.h>
//#include <modules/codes.h>
 
/* -----------------------------------------------------------------------
BUDGET_TASK_MODEL: a model for guest tasks
----------------------------------------------------------------------- */
 
#define BUDGET_PCLASS 0x0600
typedef struct {
TASK_MODEL t;
int b;
} BUDGET_TASK_MODEL;
 
#define budget_task_default_model(m,buf) \
task_default_model((m).t, BUDGET_PCLASS), \
(m).b = (buf);
 
 
 
/* some constants for registering the Module in the right place */
#define CBSSTAR_LEVELNAME "CBSSTAR"
#define CBSSTAR_LEVEL_CODE 106
#define CBSSTAR_LEVEL_VERSION 1
 
 
 
 
/* Registration function:
int N Maximum number of budgets allocated for the applications
LEVEL master the level that must be used as master level for the
CBS tasks
*/
LEVEL CBSSTAR_register_level(int n, LEVEL master);
 
/* Allocates a budget to be used for an application.
Input parameters:
Q The budget
T The period of the budget
Return value:
0..N The ID of the budget
-1 no more free budgets
-2 The budgets allocated locally to this module have bandwidth > 1
-3 wrong LEVEL id
*/
int CBSSTAR_setbudget(LEVEL l, TIME Q, TIME T);
 
#endif
/advdemos/branches/advdemos/first/rmstar.c
0,0 → 1,640
/*
* 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: rmstar.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
**/
 
/*
* Copyright (C) 2001 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 "rmstar.h"
#include <ll/stdio.h>
#include <ll/string.h>
#include <kernel/model.h>
#include <kernel/descr.h>
#include <kernel/var.h>
#include <kernel/func.h>
 
/* for iqueues */
/* #include "iqueue.h" Now iqueues are the only queue type into the kernel */
 
/* for BUDGET_TASK_MODEL */
#include "cbsstar.h"
 
/*
* DEBUG stuffs begin
*/
 
//#define RMSTAR_DEBUG
 
#ifdef RMSTAR_DEBUG
 
static __inline__ fake_printf(char *fmt, ...) {}
 
#define rmstar_printf fake_printf
#define rmstar_printf2 fake_printf
#define rmstar_printf3 fake_printf
 
//#define rmstar_printf kern_printf
//#define rmstar_printf2 kern_printf
//#define rmstar_printf3 kern_printf
#endif
 
/*
* DEBUG stuffs end
*/
 
/* Status used in the level */
#define RMSTAR_READY MODULE_STATUS_BASE /* - Ready status */
#define RMSTAR_IDLE MODULE_STATUS_BASE+4 /* to wait the deadline */
 
/* flags */
#define RMSTAR_FLAG_NORAISEEXC 2
 
/* the level redefinition for the Earliest Deadline First level */
typedef struct {
level_des l; /* the standard level descriptor */
 
TIME period[MAX_PROC]; /* The task periods; the deadlines are
stored in the priority field */
int deadline_timer[MAX_PROC];
/* The task deadline timers */
 
struct timespec deadline_timespec[MAX_PROC];
 
int dline_miss[MAX_PROC]; /* Deadline miss counter */
int wcet_miss[MAX_PROC]; /* Wcet miss counter */
 
int nact[MAX_PROC]; /* Wcet miss counter */
 
int flag[MAX_PROC];
/* used to manage the JOB_TASK_MODEL and the
periodicity */
 
IQUEUE ready; /* the ready queue */
 
PID activated; /* the task that has been inserted into the
master module */
 
int budget;
 
int scheduling_level;
} RMSTAR_level_des;
 
static void RMSTAR_check_preemption(RMSTAR_level_des *lev)
{
PID first;
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:chk)");
#endif
 
if ((first = iq_query_first(&lev->ready)) != lev->activated) {
if (lev->activated != NIL)
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level, lev->activated);
 
lev->activated = first;
 
if (first != NIL) {
BUDGET_TASK_MODEL b;
budget_task_default_model(b, lev->budget);
 
level_table[ lev->scheduling_level ]->
private_insert(lev->scheduling_level, first, (TASK_MODEL *)&b);
}
}
}
 
static void RMSTAR_timer_deadline(void *par);
 
static void RMSTAR_internal_activate(RMSTAR_level_des *lev, PID p,
struct timespec *t)
{
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:iact)");
#endif
 
ADDUSEC2TIMESPEC(lev->period[p], t);
 
*iq_query_timespec(p, &lev->ready) = *t;
lev->deadline_timespec[p] = *t;
 
/* Insert task in the correct position */
proc_table[p].status = RMSTAR_READY;
iq_priority_insert(p,&lev->ready);
 
/* needed because when there is a wcet miss I disable CONTROL_CAP */
proc_table[p].control |= CONTROL_CAP;
 
/* check for preemption */
RMSTAR_check_preemption(lev);
}
 
static void RMSTAR_timer_deadline(void *par)
{
PID p = (PID) par;
RMSTAR_level_des *lev;
 
#ifdef RMSTAR_DEBUG
// rmstar_printf("(E:tdl ");
#endif
 
lev = (RMSTAR_level_des *)level_table[proc_table[p].task_level];
 
switch (proc_table[p].status) {
case RMSTAR_IDLE:
#ifdef RMSTAR_DEBUG
// rmstar_printf2("I%d",p);
#endif
/* set the request time */
RMSTAR_internal_activate(lev,p,iq_query_timespec(p, &lev->ready));
 
event_need_reschedule();
break;
 
default:
#ifdef RMSTAR_DEBUG
// rmstar_printf2("D%d",p);
#endif
/* else, a deadline miss occurred!!! */
lev->dline_miss[p]++;
 
/* the task is into another state */
lev->nact[p]++;
 
/* Set the deadline timer */
ADDUSEC2TIMESPEC(lev->period[p], &lev->deadline_timespec[p]);
}
 
/* Set the deadline timer */
lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
RMSTAR_timer_deadline,
(void *)p);
 
#ifdef RMSTAR_DEBUG
// rmstar_printf(")");
#endif
}
 
static void RMSTAR_timer_guest_deadline(void *par)
{
PID p = (PID) par;
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:gdl)");
#endif
 
kern_raise(XDEADLINE_MISS,p);
}
 
static int RMSTAR_public_create(LEVEL l, PID p, TASK_MODEL *m)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
/* if the RMSTAR_task_create is called, then the pclass must be a
valid pclass. */
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 || h->periodicity != PERIODIC) return -1;
/* now we know that m is a valid model */
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:tcr)");
#endif
 
lev->period[p] = h->mit;
*iq_query_priority(p, &lev->ready) = h->mit;
 
lev->flag[p] = 0;
lev->deadline_timer[p] = -1;
lev->dline_miss[p] = 0;
lev->wcet_miss[p] = 0;
lev->nact[p] = 0;
 
/* Enable wcet check */
proc_table[p].avail_time = h->wcet;
proc_table[p].wcet = h->wcet;
proc_table[p].control |= CONTROL_CAP;
 
return 0; /* OK, also if the task cannot be guaranteed... */
}
 
static void RMSTAR_public_dispatch(LEVEL l, PID p, int nostop)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:dis)");
 
rmstar_printf3("(%d %d)",
iq_query_timespec(p, &lev->ready)->tv_nsec/1000000,
schedule_time.tv_nsec/1000000);
#endif
 
level_table[ lev->scheduling_level ]->
private_dispatch(lev->scheduling_level,p,nostop);
}
 
static void RMSTAR_public_epilogue(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:epi ");
#endif
 
/* check if the wcet is finished... */
if (proc_table[p].avail_time <= 0 && proc_table[p].control&CONTROL_CAP) {
/* wcet finished: disable wcet event and count wcet miss */
#ifdef RMSTAR_DEBUG
rmstar_printf2("W%d",p);
#endif
proc_table[p].control &= ~CONTROL_CAP;
lev->wcet_miss[p]++;
}
#ifdef RMSTAR_DEBUG
rmstar_printf(")");
#endif
 
level_table[ lev->scheduling_level ]->
private_epilogue(lev->scheduling_level,p);
 
proc_table[p].status = RMSTAR_READY;
}
 
static void RMSTAR_public_activate(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
struct timespec t;
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:act)");
#endif
 
/* Test if we are trying to activate a non sleeping task */
/* save activation (only if needed... */
if (proc_table[p].status != SLEEP) {
/* a periodic task cannot be activated when it is already active */
kern_raise(XACTIVATION,p);
return;
}
 
kern_gettime(&t);
 
RMSTAR_internal_activate(lev,p, &t);
 
/* Set the deadline timer */
lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
RMSTAR_timer_deadline,
(void *)p);
 
}
 
static void RMSTAR_public_unblock(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:ins)");
#endif
 
/* Insert task in the correct position */
proc_table[p].status = RMSTAR_READY;
iq_priority_insert(p,&lev->ready);
 
/* and check for preemption! */
RMSTAR_check_preemption(lev);
}
 
static void RMSTAR_public_block(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:ext)");
#endif
 
/* the task is blocked on a synchronization primitive. we have to
remove it from the master module -and- from the local queue! */
iq_extract(p,&lev->ready);
 
/* and finally, a preemption check! (it will also call guest_end) */
RMSTAR_check_preemption(lev);
}
 
static int RMSTAR_public_message(LEVEL l, PID p, void *m)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
struct timespec temp;
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:ecy ");
#endif
 
/* we call guest_end directly here because the same task may
be reinserted in the queue before calling the preemption check! */
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level,p); lev->activated = NIL;
 
iq_extract(p,&lev->ready);
 
/* we reset the capacity counters... */
proc_table[p].avail_time = proc_table[p].wcet;
 
if (lev->nact[p] > 0) {
#ifdef RMSTAR_DEBUG
rmstar_printf2("E%d",p);
#endif
 
/* Pending activation: reactivate the thread!!! */
lev->nact[p]--;
 
/* see also RMSTAR_timer_deadline */
kern_gettime(&temp);
 
RMSTAR_internal_activate(lev,p,&temp);
 
/* check if the deadline has already expired */
temp = *iq_query_timespec(p, &lev->ready);
if (TIMESPEC_A_LT_B(&temp, &schedule_time)) {
/* count the deadline miss */
lev->dline_miss[p]++;
kern_event_delete(lev->deadline_timer[p]);
}
 
}
else {
#ifdef RMSTAR_DEBUG
rmstar_printf("e%d",p);
#endif
 
/* the task has terminated his job before it consume the wcet. All OK! */
proc_table[p].status = RMSTAR_IDLE;
 
/* and finally, a preemption check! */
RMSTAR_check_preemption(lev);
 
/* when the deadline timer fire, it recognize the situation and set
correctly all the stuffs (like reactivation, etc... ) */
}
#ifdef RMSTAR_DEBUG
rmstar_printf(")");
#endif
 
jet_update_endcycle(); /* Update the Jet data... */
 
return 0;
}
 
static void RMSTAR_public_end(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
#ifdef RMSTAR_DEBUG
rmstar_printf("(E:end)");
#endif
 
iq_extract(p,&lev->ready);
 
/* we finally put the task in the ready queue */
proc_table[p].status = FREE;
iq_insertfirst(p,&freedesc);
if (lev->deadline_timer[p] != -1) {
kern_event_delete(lev->deadline_timer[p]);
}
 
/* and finally, a preemption check! (it will also call guest_end) */
RMSTAR_check_preemption(lev);
}
 
 
/* Guest Functions
These functions manages a JOB_TASK_MODEL, that is used to put
a guest task in the RMSTAR ready queue. */
 
static void RMSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
JOB_TASK_MODEL *job;
 
if (m->pclass != JOB_PCLASS || (m->level != 0 && m->level != l) ) {
kern_raise(XINVALID_TASK, p);
return;
}
 
job = (JOB_TASK_MODEL *)m;
 
*iq_query_timespec(p, &lev->ready) = job->deadline;
lev->deadline_timer[p] = -1;
lev->dline_miss[p] = 0;
lev->wcet_miss[p] = 0;
lev->nact[p] = 0;
 
if (job->noraiseexc)
lev->flag[p] = RMSTAR_FLAG_NORAISEEXC;
else {
lev->flag[p] = 0;
lev->deadline_timer[p] = kern_event_post(iq_query_timespec(p, &lev->ready),
RMSTAR_timer_guest_deadline,
(void *)p);
}
 
lev->period[p] = job->period;
*iq_query_priority(p, &lev->ready) = job->period;
 
/* there is no bandwidth guarantee at this level, it is performed
by the level that inserts guest tasks... */
 
/* Insert task in the correct position */
iq_priority_insert(p,&lev->ready);
proc_table[p].status = RMSTAR_READY;
 
/* check for preemption */
RMSTAR_check_preemption(lev);
}
 
static void RMSTAR_private_dispatch(LEVEL l, PID p, int nostop)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
level_table[ lev->scheduling_level ]->
private_dispatch(lev->scheduling_level,p,nostop);
}
 
static void RMSTAR_private_epilogue(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
/* the task has been preempted. it returns into the ready queue... */
level_table[ lev->scheduling_level ]->
private_epilogue(lev->scheduling_level,p);
 
proc_table[p].status = RMSTAR_READY;
}
 
static void RMSTAR_private_extract(LEVEL l, PID p)
{
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
#ifdef RMSTAR_DEBUG
//kern_printf("RMSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
#endif
 
iq_extract(p, &lev->ready);
 
/* we remove the deadline timer, because the slice is finished */
if (lev->deadline_timer[p] != NIL) {
#ifdef RMSTAR_DEBUG
// kern_printf("RMSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
#endif
kern_event_delete(lev->deadline_timer[p]);
lev->deadline_timer[p] = NIL;
}
 
/* and finally, a preemption check! (it will also call guest_end() */
RMSTAR_check_preemption(lev);
}
 
/* Registration functions */
 
/* Registration function:
int flags the init flags ... see RMSTAR.h */
LEVEL RMSTAR_register_level(int budget, int master)
{
LEVEL l; /* the level that we register */
RMSTAR_level_des *lev; /* for readableness only */
PID i; /* a counter */
 
#ifdef RMSTAR_DEBUG
printk("RMSTAR_register_level\n");
#endif
 
/* request an entry in the level_table */
l = level_alloc_descriptor(sizeof(RMSTAR_level_des));
 
lev = (RMSTAR_level_des *)level_table[l];
 
printk(" lev=%d\n",(int)lev);
 
/* fill the standard descriptor */
lev->l.private_insert = RMSTAR_private_insert;
lev->l.private_extract = RMSTAR_private_extract;
lev->l.private_dispatch = RMSTAR_private_dispatch;
lev->l.private_epilogue = RMSTAR_private_epilogue;
 
lev->l.public_guarantee = NULL;
lev->l.public_create = RMSTAR_public_create;
lev->l.public_end = RMSTAR_public_end;
lev->l.public_dispatch = RMSTAR_public_dispatch;
lev->l.public_epilogue = RMSTAR_public_epilogue;
lev->l.public_activate = RMSTAR_public_activate;
lev->l.public_unblock = RMSTAR_public_unblock;
lev->l.public_block = RMSTAR_public_block;
lev->l.public_message = RMSTAR_public_message;
 
/* fill the RMSTAR descriptor part */
for(i=0; i<MAX_PROC; i++) {
lev->period[i] = 0;
lev->deadline_timer[i] = -1;
lev->flag[i] = 0;
lev->dline_miss[i] = 0;
lev->wcet_miss[i] = 0;
lev->nact[i] = 0;
}
 
iq_init(&lev->ready, NULL, 0);
lev->activated = NIL;
 
lev->budget = budget;
lev->scheduling_level = master;
 
return l;
}
 
int RMSTAR_get_dline_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
return lev->dline_miss[p];
}
 
int RMSTAR_get_wcet_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
return lev->wcet_miss[p];
}
 
int RMSTAR_get_nact(PID p)
{
LEVEL l = proc_table[p].task_level;
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
return lev->nact[p];
}
 
int RMSTAR_reset_dline_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
lev->dline_miss[p] = 0;
return 0;
}
 
int RMSTAR_reset_wcet_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
 
lev->wcet_miss[p] = 0;
return 0;
}
 
/advdemos/branches/advdemos/first/testiq.c
0,0 → 1,260
/*
* 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: testiq.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 $
------------
 
The purpose of this test is to show that two budgets with different
period and budgets schedules correctly.
2 never ending tasks are involved
 
This test cannot compile because of the fact that QUEUE and QQUEUE
types does not exist anymore!
*/
 
/*
* Copyright (C) 2002 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 "modules/edf.h"
#include "modules/cbs.h"
#include "cbsstar.h"
#include "edfstar.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
// --------------------------------------------------
// --------------------------------------------------
// Init Part
// --------------------------------------------------
// --------------------------------------------------
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
clear();
 
EDF_register_level(EDF_ENABLE_ALL);
 
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
// for the keyboard...
CBS_register_level(CBS_ENABLE_ALL, 0);
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
//keyb_def_ctrlC(kparms, NULL);
//keyb_def_map(kparms,itaMap);
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
// --------------------------------------------------
// --------------------------------------------------
// The Test
// --------------------------------------------------
// --------------------------------------------------
 
 
#include <kernel/kern.h>
#include <drivers/keyb.h>
#include "iqueue.h"
 
sem_t s;
 
PID p2,p3,p4;
 
void *star(void *arg)
{
int j;
TIME last[5];
 
QUEUE i = NIL;
IQUEUE ii;
 
q_timespec_insert(p2,&i);
q_timespec_insert(p3,&i);
 
iq_init(&ii,NULL,0);
*iq_query_timespec(p2,&ii) = proc_table[p2].timespec_priority;
*iq_query_timespec(p3,&ii) = proc_table[p3].timespec_priority;
*iq_query_timespec(p4,&ii) = proc_table[p4].timespec_priority;
iq_timespec_insert(p2,&ii);
iq_timespec_insert(p3,&ii);
 
cprintf("p2=%ld.%ld\n",proc_table[p2].timespec_priority.tv_sec,proc_table[p2].timespec_priority.tv_nsec/1000);
cprintf("p3=%ld.%ld\n",proc_table[p3].timespec_priority.tv_sec,proc_table[p3].timespec_priority.tv_nsec/1000);
cprintf("p4=%ld.%ld\n",proc_table[p4].timespec_priority.tv_sec,proc_table[p4].timespec_priority.tv_nsec/1000);
 
task_endcycle();
 
for (j=0; j<200000; j++) {
q_timespec_insert(p4,&i);
q_extract(p4,&i);
}
 
 
task_endcycle();
 
for (j=0; j<200000; j++) {
iq_timespec_insert(p4,&ii);
iq_extract(p4,&ii);
}
 
task_endcycle();
 
jet_gettable(exec_shadow, &last[0], 3);
 
cprintf("\ninit=%d queue=%d iqueue=%d\n",
(int)last[0], (int)last[1], (int)last[2]);
 
sys_end();
return NULL;
}
 
void *fake(void *arg)
{
cputs("#");
task_endcycle();
 
return NULL;
}
 
 
void create1()
{
HARD_TASK_MODEL m1;
PID p1a;
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 500000);
hard_task_def_group(m1,1);
hard_task_def_periodic(m1);
hard_task_def_mit(m1,1000000);
hard_task_def_ctrl_jet(m1);
p1a = task_create("a", star, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
hard_task_default_model(m1);
hard_task_def_wcet(m1, 5000);
hard_task_def_aperiodic(m1);
hard_task_def_group(m1,1);
 
hard_task_def_mit(m1,100000);
p2 = task_create("a", fake, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
hard_task_def_mit(m1,100001);
p3 = task_create("a", fake, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
hard_task_def_mit(m1,100002);
p4 = task_create("a", fake, &m1, NULL);
if (p1a == -1) {
perror("Could not create task a ...");
sys_end();
}
 
group_activate(1);
}
 
void endfun(KEY_EVT *k)
{
cprintf("ESC pressed!");
 
sys_end();
}
 
int main(int argc, char **argv)
{
KEY_EVT k;
 
sem_init(&s,0,1);
 
k.flag = 0;
k.scan = KEY_ESC;
k.ascii = 27;
keyb_hook(k,endfun);
 
create1();
 
return 0;
}
 
/advdemos/branches/advdemos/first/rmstar.h
0,0 → 1,128
/*
* 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: rmstar.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 $
------------
 
Title:
RMSTAR
 
Task Models Accepted:
HARD_TASK_MODEL - Hard Tasks (only Periodic)
wcet field and mit field must be != 0. They are used to set the wcet
and period of the tasks.
periodicity field can be only PERIODIC
drel field is ignored
Guest Models Accepted:
JOB_TASK_MODEL - a single guest task activation
Identified by an absolute deadline and a period.
period field is ignored
 
Description:
 
This module schedule his tasks following the classic RM
scheme.
 
Note: This module is derived from the EDFSTAR Scheduling Module. I
have just changed RM in EDF and iq_timespec_insert with
iq_priority_insert...
 
Exceptions raised:
XUNVALID_GUEST XUNVALID_TASK
some primitives are not implemented:
task_sleep, task_delay, guest_endcycle, guest_sleep, guest_delay
 
XACTIVATION
If a task is actiated through task_activate or guest_activate more than
one time
Restrictions & special features:
see edfstar.h
 
**/
 
/*
* Copyright (C) 2001 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 __RMSTAR_H__
#define __RMSTAR_H__
 
#include <ll/ll.h>
#include <kernel/config.h>
#include <sys/types.h>
#include <kernel/types.h>
 
 
 
/* flags... */
#define RMSTAR_ENABLE_GUARANTEE 1 /* Task Guarantee enabled */
#define RMSTAR_ENABLE_ALL 1
 
#define RMSTAR_FAILED_GUARANTEE 8 /* used in the module, unsettabl
in RM_register_level... */
 
 
 
#define RMSTAR_LEVELNAME "RMSTAR base"
#define RMSTAR_LEVEL_CODE 166
#define RMSTAR_LEVEL_VERSION 1
 
 
/* Registration function:
int budget The budget used by this module (see CBSSTAR.h)
int master The master module used by RMSTAR
*/
LEVEL RMSTAR_register_level(int budget, int master);
 
/* returns respectively the number of dline, wcet or nact; -1 if error */
int RMSTAR_get_dline_miss(PID p);
int RMSTAR_get_wcet_miss(PID p);
int RMSTAR_get_nact(PID p);
 
/* resets respectively the number of dline, wcet miss; -1 if error */
int RMSTAR_reset_dline_miss(PID p);
int RMSTAR_reset_wcet_miss(PID p);
 
#endif
 
/advdemos/branches/advdemos/first/edfstar.c
0,0 → 1,657
/*
* 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: edfstar.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
**/
 
/*
* Copyright (C) 2001 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 "edfstar.h"
#include <ll/stdio.h>
#include <ll/string.h>
#include <kernel/model.h>
#include <kernel/descr.h>
#include <kernel/var.h>
#include <kernel/func.h>
 
/* for iqueues */
/* #include "iqueue.h" Now iqueues are the only queue type available
into the kernel */
#include <kernel/iqueue.h>
 
/* for BUDGET_TASK_MODEL */
#include "cbsstar.h"
 
/*
* DEBUG stuffs begin
*/
 
//#define EDFSTAR_DEBUG
 
#ifdef EDFSTAR_DEBUF
 
static __inline__ fake_printf(char *fmt, ...) {}
 
#define edfstar_printf fake_printf
#define edfstar_printf2 fake_printf
#define edfstar_printf3 fake_printf
 
//#define edfstar_printf kern_printf
//#define edfstar_printf2 kern_printf
//#define edfstar_printf3 kern_printf
#endif
 
/*
* DEBUG stuffs end
*/
 
/* Status used in the level */
#define EDFSTAR_READY MODULE_STATUS_BASE /* - Ready status */
#define EDFSTAR_IDLE MODULE_STATUS_BASE+4 /* to wait the deadline */
 
/* flags */
#define EDFSTAR_FLAG_NORAISEEXC 2
 
/* the level redefinition for the Earliest Deadline First level */
typedef struct {
level_des l; /* the standard level descriptor */
 
TIME period[MAX_PROC]; /* The task periods; the deadlines are
stored in the priority field */
int deadline_timer[MAX_PROC];
/* The task deadline timers */
 
struct timespec deadline_timespec[MAX_PROC];
 
int dline_miss[MAX_PROC]; /* Deadline miss counter */
int wcet_miss[MAX_PROC]; /* Wcet miss counter */
 
int nact[MAX_PROC]; /* Wcet miss counter */
 
int flag[MAX_PROC];
/* used to manage the JOB_TASK_MODEL and the
periodicity */
 
IQUEUE ready; /* the ready queue */
 
PID activated; /* the task that has been inserted into the
master module */
 
int budget;
 
int scheduling_level;
} EDFSTAR_level_des;
 
static void EDFSTAR_check_preemption(EDFSTAR_level_des *lev)
{
PID first;
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:chk)");
#endif
 
if ((first = iq_query_first(&lev->ready)) != lev->activated) {
if (lev->activated != NIL)
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level, lev->activated);
 
lev->activated = first;
 
if (first != NIL) {
BUDGET_TASK_MODEL b;
budget_task_default_model(b, lev->budget);
 
level_table[ lev->scheduling_level ]->
private_insert(lev->scheduling_level, first, (TASK_MODEL *)&b);
}
}
}
 
static void EDFSTAR_timer_deadline(void *par);
 
static void EDFSTAR_internal_activate(EDFSTAR_level_des *lev, PID p,
struct timespec *t)
{
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:iact)");
#endif
 
ADDUSEC2TIMESPEC(lev->period[p], t);
 
*iq_query_timespec(p, &lev->ready) = *t;
lev->deadline_timespec[p] = *t;
 
/* Insert task in the correct position */
proc_table[p].status = EDFSTAR_READY;
iq_timespec_insert(p,&lev->ready);
 
/* needed because when there is a wcet miss I disable CONTROL_CAP */
proc_table[p].control |= CONTROL_CAP;
 
/* check for preemption */
EDFSTAR_check_preemption(lev);
}
 
static void EDFSTAR_timer_deadline(void *par)
{
PID p = (PID) par;
EDFSTAR_level_des *lev;
 
#ifdef EDFSTAR_DEBUG
// edfstar_printf("(E:tdl ");
#endif
 
lev = (EDFSTAR_level_des *)level_table[proc_table[p].task_level];
 
switch (proc_table[p].status) {
case EDFSTAR_IDLE:
#ifdef EDFSTAR_DEBUG
// edfstar_printf2("I%d",p);
#endif
/* set the request time */
EDFSTAR_internal_activate(lev,p,iq_query_timespec(p, &lev->ready));
 
event_need_reschedule();
break;
 
default:
#ifdef EDFSTAR_DEBUG
// edfstar_printf2("D%d",p);
#endif
/* else, a deadline miss occurred!!! */
lev->dline_miss[p]++;
 
/* the task is into another state */
lev->nact[p]++;
 
/* Set the deadline timer */
ADDUSEC2TIMESPEC(lev->period[p], &lev->deadline_timespec[p]);
}
 
/* Set the deadline timer */
lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
EDFSTAR_timer_deadline,
(void *)p);
 
#ifdef EDFSTAR_DEBUG
// edfstar_printf(")");
#endif
}
 
static void EDFSTAR_timer_guest_deadline(void *par)
{
PID p = (PID) par;
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:gdl)");
#endif
 
kern_raise(XDEADLINE_MISS,p);
}
 
static int EDFSTAR_public_create(LEVEL l, PID p, TASK_MODEL *m)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
/* if the EDFSTAR_task_create is called, then the pclass must be a
valid pclass. */
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 || h->periodicity != PERIODIC) return -1;
/* now we know that m is a valid model */
 
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:tcr)");
#endif
 
lev->period[p] = h->mit;
 
lev->flag[p] = 0;
lev->deadline_timer[p] = -1;
lev->dline_miss[p] = 0;
lev->wcet_miss[p] = 0;
lev->nact[p] = 0;
 
/* Enable wcet check */
proc_table[p].avail_time = h->wcet;
proc_table[p].wcet = h->wcet;
proc_table[p].control |= CONTROL_CAP;
 
return 0; /* OK, also if the task cannot be guaranteed... */
}
 
static int EDFSTAR_public_eligible(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf2("(E:eli)");
#endif
 
return level_table[ lev->scheduling_level ]->
private_eligible(lev->scheduling_level,p);
}
 
static void EDFSTAR_public_dispatch(LEVEL l, PID p, int nostop)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:dis)");
 
edfstar_printf3("(%d %d)",
iq_query_timespec(p, &lev->ready)->tv_nsec/1000000,
schedule_time.tv_nsec/1000000);
#endif
 
level_table[ lev->scheduling_level ]->
private_dispatch(lev->scheduling_level,p,nostop);
}
 
static void EDFSTAR_public_epilogue(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:epi ");
#endif
 
/* check if the wcet is finished... */
if (proc_table[p].avail_time <= 0 && proc_table[p].control&CONTROL_CAP) {
/* wcet finished: disable wcet event and count wcet miss */
#ifdef EDFSTAR_DEBUG
edfstar_printf2("W%d",p);
#endif
proc_table[p].control &= ~CONTROL_CAP;
lev->wcet_miss[p]++;
}
#ifdef EDFSTAR_DEBUG
edfstar_printf(")");
#endif
 
level_table[ lev->scheduling_level ]->
private_epilogue(lev->scheduling_level,p);
 
proc_table[p].status = EDFSTAR_READY;
}
 
static void EDFSTAR_public_activate(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
struct timespec t;
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:act)");
#endif
 
/* Test if we are trying to activate a non sleeping task */
/* save activation (only if needed... */
if (proc_table[p].status != SLEEP) {
/* a periodic task cannot be activated when it is already active */
kern_raise(XACTIVATION,p);
return;
}
 
kern_gettime(&t);
 
EDFSTAR_internal_activate(lev,p, &t);
 
/* Set the deadline timer */
lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
EDFSTAR_timer_deadline,
(void *)p);
 
}
 
static void EDFSTAR_public_unblock(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:ins)");
#endif
 
/* Insert task in the correct position */
proc_table[p].status = EDFSTAR_READY;
iq_timespec_insert(p,&lev->ready);
 
/* and check for preemption! */
EDFSTAR_check_preemption(lev);
}
 
static void EDFSTAR_public_block(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:ext)");
#endif
 
/* the task is blocked on a synchronization primitive. we have to
remove it from the master module -and- from the local queue! */
iq_extract(p,&lev->ready);
 
/* and finally, a preemption check! (it will also call guest_end) */
EDFSTAR_check_preemption(lev);
}
 
static int EDFSTAR_public_message(LEVEL l, PID p, void *m)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
struct timespec temp;
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:ecy ");
#endif
 
/* we call guest_end directly here because the same task may
be reinserted in the queue before calling the preemption check! */
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level,p);
lev->activated = NIL;
 
iq_extract(p,&lev->ready);
 
/* we reset the capacity counters... */
proc_table[p].avail_time = proc_table[p].wcet;
 
if (lev->nact[p] > 0) {
#ifdef EDFSTAR_DEBUG
edfstar_printf2("E%d",p);
#endif
 
/* Pending activation: reactivate the thread!!! */
lev->nact[p]--;
 
/* see also EDFSTAR_timer_deadline */
kern_gettime(&temp);
 
EDFSTAR_internal_activate(lev,p, &temp);
 
/* check if the deadline has already expired */
temp = *iq_query_timespec(p, &lev->ready);
if (TIMESPEC_A_LT_B(&temp, &schedule_time)) {
/* count the deadline miss */
lev->dline_miss[p]++;
kern_event_delete(lev->deadline_timer[p]);
}
 
}
else {
#ifdef EDFSTAR_DEBUG
edfstar_printf("e%d",p);
#endif
 
/* the task has terminated his job before it consume the wcet. All OK! */
proc_table[p].status = EDFSTAR_IDLE;
 
/* and finally, a preemption check! */
EDFSTAR_check_preemption(lev);
 
/* when the deadline timer fire, it recognize the situation and set
correctly all the stuffs (like reactivation, etc... ) */
}
#ifdef EDFSTAR_DEBUG
edfstar_printf(")");
#endif
 
jet_update_endcycle(); /* Update the Jet data... */
 
return 0;
}
 
static void EDFSTAR_public_end(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:end)");
#endif
 
iq_extract(p,&lev->ready);
 
/* we finally put the task in the ready queue */
proc_table[p].status = FREE;
iq_insertfirst(p,&freedesc);
if (lev->deadline_timer[p] != -1) {
kern_event_delete(lev->deadline_timer[p]);
}
 
/* and finally, a preemption check! (it will also call guest_end) */
EDFSTAR_check_preemption(lev);
}
 
/* Guest Functions
These functions manages a JOB_TASK_MODEL, that is used to put
a guest task in the EDFSTAR ready queue. */
 
static void EDFSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
JOB_TASK_MODEL *job;
 
if (m->pclass != JOB_PCLASS || (m->level != 0 && m->level != l) ) {
kern_raise(XINVALID_TASK, p);
return;
}
 
job = (JOB_TASK_MODEL *)m;
 
/* if the EDFSTAR_guest_create is called, then the pclass must be a
valid pclass. */
 
*iq_query_timespec(p, &lev->ready) = job->deadline;
lev->deadline_timer[p] = -1;
lev->dline_miss[p] = 0;
lev->wcet_miss[p] = 0;
lev->nact[p] = 0;
 
if (job->noraiseexc)
lev->flag[p] = EDFSTAR_FLAG_NORAISEEXC;
else {
lev->flag[p] = 0;
lev->deadline_timer[p] = kern_event_post(iq_query_timespec(p, &lev->ready),
EDFSTAR_timer_guest_deadline,
(void *)p);
}
 
lev->period[p] = job->period;
 
/* Insert task in the correct position */
iq_timespec_insert(p,&lev->ready);
proc_table[p].status = EDFSTAR_READY;
 
/* check for preemption */
EDFSTAR_check_preemption(lev);
 
/* there is no bandwidth guarantee at this level, it is performed
by the level that inserts guest tasks... */
}
 
static void EDFSTAR_private_dispatch(LEVEL l, PID p, int nostop)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
level_table[ lev->scheduling_level ]->
private_dispatch(lev->scheduling_level,p,nostop);
}
 
static void EDFSTAR_private_epilogue(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
/* the task has been preempted. it returns into the ready queue... */
level_table[ lev->scheduling_level ]->
private_epilogue(lev->scheduling_level,p);
 
proc_table[p].status = EDFSTAR_READY;
}
 
static void EDFSTAR_private_extract(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
//kern_printf("EDFSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
#endif
 
iq_extract(p, &lev->ready);
 
/* we remove the deadline timer, because the slice is finished */
if (lev->deadline_timer[p] != NIL) {
#ifdef EDFSTAR_DEBUG
// kern_printf("EDFSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
#endif
kern_event_delete(lev->deadline_timer[p]);
lev->deadline_timer[p] = NIL;
}
 
/* and finally, a preemption check! (it will also call guest_end() */
EDFSTAR_check_preemption(lev);
}
 
/* Registration functions */
 
/* Registration function:
int flags the init flags ... see EDFSTAR.h */
LEVEL EDFSTAR_register_level(int budget, int master)
{
LEVEL l; /* the level that we register */
EDFSTAR_level_des *lev; /* for readableness only */
PID i; /* a counter */
 
#ifdef EDFSTAR_DEBUG
printk("EDFSTAR_register_level\n");
#endif
 
/* request an entry in the level_table */
l = level_alloc_descriptor(sizeof(EDFSTAR_level_des));
 
lev = (EDFSTAR_level_des *)level_table[l];
 
printk(" lev=%d\n",(int)lev);
 
/* fill the standard descriptor */
lev->l.private_insert = EDFSTAR_private_insert;
lev->l.private_extract = EDFSTAR_private_extract;
lev->l.private_dispatch = EDFSTAR_private_dispatch;
lev->l.private_epilogue = EDFSTAR_private_epilogue;
 
lev->l.public_guarantee = NULL;
lev->l.public_eligible = EDFSTAR_public_eligible;
lev->l.public_create = EDFSTAR_public_create;
lev->l.public_end = EDFSTAR_public_end;
lev->l.public_dispatch = EDFSTAR_public_dispatch;
lev->l.public_epilogue = EDFSTAR_public_epilogue;
lev->l.public_activate = EDFSTAR_public_activate;
lev->l.public_unblock = EDFSTAR_public_unblock;
lev->l.public_block = EDFSTAR_public_block;
lev->l.public_message = EDFSTAR_public_message;
 
/* fill the EDFSTAR descriptor part */
for(i=0; i<MAX_PROC; i++) {
lev->period[i] = 0;
lev->deadline_timer[i] = -1;
lev->flag[i] = 0;
lev->dline_miss[i] = 0;
lev->wcet_miss[i] = 0;
lev->nact[i] = 0;
}
 
iq_init(&lev->ready, NULL, IQUEUE_NO_PRIORITY);
lev->activated = NIL;
 
lev->budget = budget;
lev->scheduling_level = master;
 
return l;
}
 
int EDFSTAR_get_dline_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
return lev->dline_miss[p];
}
 
int EDFSTAR_get_wcet_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
return lev->wcet_miss[p];
}
 
int EDFSTAR_get_nact(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
return lev->nact[p];
}
 
int EDFSTAR_reset_dline_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
lev->dline_miss[p] = 0;
return 0;
}
 
int EDFSTAR_reset_wcet_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
lev->wcet_miss[p] = 0;
return 0;
}
 
/advdemos/branches/advdemos/first/posixstar.c
0,0 → 1,541
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Trimarchi Michael <trimarchi@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: posixstar.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
This file contains the scheduling module compatible with POSIX
specifications
 
Read posixstar.h for further details.
 
RR tasks have the CONTROL_CAP bit set
 
**/
 
/*
* 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 WARR2ANTY; without even the implied waRR2anty 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 <ll/stdio.h>
#include <ll/string.h>
#include <kernel/model.h>
#include <kernel/descr.h>
#include <kernel/var.h>
#include <kernel/func.h>
#include "posixstar.h"
#include "cbsstar.h"
//#define POSIXSTAR_DEBUG
/*+ Status used in the level +*/
#define POSIXSTAR_READY MODULE_STATUS_BASE
 
/*+ the level redefinition for the Round Robin level +*/
typedef struct {
level_des l; /*+ the standard level descriptor +*/
 
int nact[MAX_PROC]; /*+ number of pending activations +*/
int priority[MAX_PROC]; /*+ priority of each task +*/
 
IQUEUE *ready; /*+ the ready queue array +*/
 
int slice; /*+ the level's time slice +*/
 
// the multiboot is not usefull for this module
// struct multiboot_info *multiboot; /*+ used if the level have to insert
// the main task +*/
int maxpriority; /*+ the priority are from 0 to maxpriority
(i.e 0 to 31) +*/
 
int yielding; /*+ equal to 1 when a sched_yield is called +*/
 
int budget;
 
PID activated;
int scheduling_level;
} POSIXSTAR_level_des;
 
/* the private scheduler choice a task and insert in cbsstar module */
/* This is not efficient but very fair :-)
The need of all this stuff is because if a task execute a long time
due to (shadow!) priority inheritance, then the task shall go to the
tail of the queue many times... */
 
static void POSIXSTAR_private_scheduler(POSIXSTAR_level_des * lev)
{
/* the old posix scheduler select the private job for CBS */
PID p=NIL;
 
int prio;
 
prio = lev->maxpriority;
 
for (;;) {
p = iq_query_first(&lev->ready[prio]);
if (p == NIL) {
if (prio) {
prio--;
continue;
}
else {
p=NIL;
break;
}
}
//if (p != NIL && (proc_table[p].control & CONTROL_CAP))
// kern_printf("CC SET %d",p);
//kern_printf("task %d", p);
 
if ((proc_table[p].control & CONTROL_CAP) &&
(proc_table[p].avail_time <= 0)) {
if (proc_table[p].avail_time<=0)
proc_table[p].avail_time += proc_table[p].wcet;
//kern_printf("RR policy");
iq_extract(p,&lev->ready[prio]);
iq_insertlast(p,&lev->ready[prio]);
}
else {
break;
}
}
 
if (p!=lev->activated) {
if (lev->activated != NIL ) {
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level, lev->activated);
//kern_printf("CBS ext %d",p);
}
lev->activated = p;
if (p != NIL) {
BUDGET_TASK_MODEL b;
budget_task_default_model(b, lev->budget);
//kern_printf("(Act %d",p);
level_table[ lev->scheduling_level ]->
private_insert(lev->scheduling_level, p, (TASK_MODEL *)&b);
}
}
}
 
static int POSIXSTAR_public_eligible(LEVEL l, PID p)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
if (p==lev->activated) {
//kern_printf("eli %d", p);
 
return level_table[ lev->scheduling_level ]->
private_eligible(lev->scheduling_level,p);
}
return 0;
}
 
static int POSIXSTAR_public_create(LEVEL l, PID p, TASK_MODEL *m)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
NRT_TASK_MODEL *nrt;
 
if (m->pclass != NRT_PCLASS) return -1;
if (m->level != 0 && m->level != l) return -1;
 
nrt = (NRT_TASK_MODEL *)m;
 
/* the task state is set at SLEEP by the general task_create */
 
/* I used the wcet field because using wcet can account if a task
consume more than the timeslice... */
 
if (nrt->inherit == NRT_INHERIT_SCHED &&
proc_table[exec_shadow].task_level == l) {
/* We inherit the scheduling properties if the scheduling level
*is* the same */
lev->priority[p] = lev->priority[exec_shadow];
proc_table[p].avail_time = proc_table[exec_shadow].avail_time;
proc_table[p].wcet = proc_table[exec_shadow].wcet;
 
proc_table[p].control = (proc_table[p].control & ~CONTROL_CAP) |
(proc_table[exec_shadow].control & CONTROL_CAP);
lev->nact[p] = (lev->nact[exec_shadow] == -1) ? -1 : 0;
}
else {
if (nrt->weight<=lev->maxpriority)
lev->priority[p] = nrt->weight;
else lev->priority[p]=lev->maxpriority;
if (nrt->slice) {
proc_table[p].avail_time = nrt->slice;
proc_table[p].wcet = nrt->slice;
}
else {
proc_table[p].avail_time = lev->slice;
proc_table[p].wcet = lev->slice;
}
if (nrt->policy == NRT_RR_POLICY) {
proc_table[p].control |= CONTROL_CAP;
//kern_printf("CCAP set:%d",p);
 
}
if (nrt->arrivals == SAVE_ARRIVALS)
lev->nact[p] = 0;
else
lev->nact[p] = -1;
}
 
return 0; /* OK */
}
 
static void POSIXSTAR_public_dispatch(LEVEL l, PID p, int nostop)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
//#ifdef POSIXSTAR_DEBUG
 
//#endif
/* the task state is set EXE by the scheduler()
we extract the task from the ready queue
NB: we can't assume that p is the first task in the queue!!! */
//iq_extract(p, &lev->ready[lev->priority[p]]);
//if (!nostop) {
//kern_printf("PDisp:%d(%d)",p, lev->activated);
if (p==lev->activated)
level_table[lev->scheduling_level]->private_dispatch(lev->scheduling_level, p, nostop);
//} else
// kern_printf("PDisp:%d(%d)",p, lev->activated);
}
 
static void POSIXSTAR_public_epilogue(LEVEL l, PID p)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
//#ifdef POSIXSTAR_DEBUG
//kern_printf("PEpic:%d",p);
//#endif
if (p==lev->activated) {
if (lev->yielding) {
lev->yielding = 0;
iq_extract(p,&lev->ready[lev->priority[p]]);
iq_insertlast(p,&lev->ready[lev->priority[p]]);
}
/* check if the slice is finished and insert the task in the coPOSIXect
qqueue position */
else if (proc_table[p].control & CONTROL_CAP &&
proc_table[p].avail_time <= 0) {
//proc_table[p].avail_time += proc_table[p].wcet;
//kern_printf("avail_time %d", proc_table[p].avail_time);
iq_extract(p,&lev->ready[lev->priority[p]]);
iq_insertlast(p,&lev->ready[lev->priority[p]]);
//level_table[lev->scheduling_level]->private_extract(lev->scheduling_level,p);
//lev->activated=NIL;
POSIXSTAR_private_scheduler(lev);
if (p==lev->activated)
level_table[lev->scheduling_level]->private_epilogue(lev->scheduling_level,p);
}
else {
//iq_insertfirst(p,&lev->ready[lev->priority[p]]);
level_table[lev->scheduling_level]->private_epilogue(lev->scheduling_level,p);
}
proc_table[p].status = POSIXSTAR_READY;
}
}
 
static void POSIXSTAR_internal_activate(POSIXSTAR_level_des *lev, PID p)
{
 
/* Insert task in the correct position */
proc_table[p].status = POSIXSTAR_READY;
iq_insertlast(p,&lev->ready[lev->priority[p]]);
 
}
 
static void POSIXSTAR_public_activate(LEVEL l, PID p)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
/* Test if we are trying to activate a non sleeping task */
/* save activation (only if needed...) */
if (proc_table[p].status != SLEEP) {
if (lev->nact[p] != -1)
lev->nact[p]++;
return;
}
#ifdef POSIXSTAR_DEBUG
kern_printf("PA:%d",p);
#endif
POSIXSTAR_internal_activate(lev, p);
POSIXSTAR_private_scheduler(lev);
 
}
 
 
static void POSIXSTAR_public_unblock(LEVEL l, PID p)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
/* Similar to POSIX_task_activate, but we don't check in what state
the task is */
 
/* Insert task in the coPOSIXect position */
//kern_printf("PU:%d", p);
proc_table[p].status = POSIXSTAR_READY;
iq_insertlast(p,&lev->ready[lev->priority[p]]);
POSIXSTAR_private_scheduler(lev);
}
 
static void POSIXSTAR_public_block(LEVEL l, PID p)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
/* 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
 
So, we do nothing!!!
*/
 
//#ifdef POSIXSTAR_DEBUG
//kern_printf("PB:%d", p);
//#endif
iq_extract(p,&lev->ready[lev->priority[p]]);
POSIXSTAR_private_scheduler(lev);
}
 
static int POSIXSTAR_public_message(LEVEL l, PID p, void *m)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
if (lev->nact[p] > 0) {
/* continue!!!! */
lev->nact[p]--;
iq_extract(p,&lev->ready[lev->priority[p]]);
iq_insertfirst(p,&lev->ready[lev->priority[p]]);
proc_table[p].status = POSIXSTAR_READY;
}
else {
proc_table[p].status = SLEEP;
 
}
//#ifdef POSIXSTAR_DEBUG
kern_printf("PM:%d",p);
//#endif
POSIXSTAR_private_scheduler(lev);
return 0;
}
 
static void POSIXSTAR_public_end(LEVEL l, PID p)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
#ifdef POSIXSTAR_DEBUG
kern_printf("PEnd:%d", p);
#endif
lev->nact[p] = -1;
 
/* then, we insert the task in the free queue */
proc_table[p].status = FREE;
iq_priority_insert(p,NULL);
POSIXSTAR_private_scheduler(lev);
}
 
/* Registration functions */
 
/*+ Registration function:
TIME slice the slice for the Round Robin queue
struct multiboot_info *mb used if createmain specified +*/
LEVEL POSIXSTAR_register_level(int budget, int master, TIME slice,
int prioritylevels)
{
LEVEL l; /* the level that we register */
POSIXSTAR_level_des *lev; /* for readableness only */
PID i; /* a counter */
int x; /* a counter */
 
printk("POSIXSTAR_register_level\n");
 
l = level_alloc_descriptor(sizeof(POSIXSTAR_level_des));
 
lev = (POSIXSTAR_level_des *)level_table[l];
 
printk(" lev=%d\n",(int)lev);
 
/* fill the standard descriptor */
/*
lev->l.private_insert = NULL;
lev->l.private_extract = NULL;
lev->l.private_dispatch = NULL;
lev->l.private_epilogue = NULL;
*/
 
//lev->l.public_scheduler = NULL;
lev->l.public_create = POSIXSTAR_public_create;
lev->l.public_end = POSIXSTAR_public_end;
lev->l.public_dispatch = POSIXSTAR_public_dispatch;
lev->l.public_epilogue = POSIXSTAR_public_epilogue;
lev->l.public_activate = POSIXSTAR_public_activate;
lev->l.public_unblock = POSIXSTAR_public_unblock;
lev->l.public_block = POSIXSTAR_public_block;
lev->l.public_message = POSIXSTAR_public_message;
lev->l.public_eligible = POSIXSTAR_public_eligible;
 
/* fill the POSIX descriptor part */
for (i = 0; i < MAX_PROC; i++)
lev->nact[i] = -1;
 
lev->maxpriority = prioritylevels -1;
 
lev->ready = (IQUEUE *)kern_alloc(sizeof(IQUEUE) * prioritylevels);
 
for (x = 0; x < prioritylevels; x++)
iq_init(&lev->ready[x], NULL, 0);
 
if (slice < POSIXSTAR_MINIMUM_SLICE) slice = POSIXSTAR_MINIMUM_SLICE;
if (slice > POSIXSTAR_MAXIMUM_SLICE) slice = POSIXSTAR_MAXIMUM_SLICE;
lev->slice = slice;
lev->activated=NIL;
lev->budget = budget;
lev->scheduling_level = master;
//lev->multiboot = mb;
 
//if (createmain)
// sys_atrunlevel(POSIXSTAR_call_main,(void *) l, RUNLEVEL_INIT);
 
return l;
}
 
/*+ this function forces the running task to go to his queue tail;
(it works only on the POSIX level) +*/
int POSIXSTAR_sched_yield(LEVEL l)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
if (proc_table[exec_shadow].task_level != l)
return -1;
 
proc_table[exec_shadow].context = kern_context_save();
lev->yielding = 1;
scheduler();
kern_context_load(proc_table[exec_shadow].context);
return 0;
}
 
/*+ this function returns the maximum level allowed for the POSIX level +*/
int POSIXSTAR_get_priority_max(LEVEL l)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
return lev->maxpriority;
}
 
/*+ this function returns the default timeslice for the POSIX level +*/
int POSIXSTAR_rr_get_interval(LEVEL l)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
return lev->slice;
}
 
/*+ this functions returns some paramaters of a task;
policy must be NRT_RR_POLICY or NRT_FIFO_POLICY;
priority must be in the range [0..prioritylevels]
returns ENOSYS or ESRCH if there are problems +*/
int POSIXSTAR_getschedparam(LEVEL l, PID p, int *policy, int *priority)
{
if (p<0 || p>= MAX_PROC || proc_table[p].status == FREE)
return ESRCH;
 
if (proc_table[p].task_level != l)
return ENOSYS;
 
if (proc_table[p].control & CONTROL_CAP)
*policy = NRT_RR_POLICY;
else
*policy = NRT_FIFO_POLICY;
 
*priority = ((POSIXSTAR_level_des *)(level_table[l]))->priority[p];
 
return 0;
}
 
/*+ this functions sets paramaters of a task +*/
int POSIXSTAR_setschedparam(LEVEL l, PID p, int policy, int priority)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
if (p<0 || p>= MAX_PROC || proc_table[p].status == FREE)
return ESRCH;
 
if (proc_table[p].task_level != l)
return ENOSYS;
 
if (policy == SCHED_RR)
proc_table[p].control |= CONTROL_CAP;
else if (policy == SCHED_FIFO)
proc_table[p].control &= ~CONTROL_CAP;
else
return EINVAL;
 
if (lev->priority[p] != priority) {
if (proc_table[p].status == POSIXSTAR_READY) {
iq_extract(p,&lev->ready[lev->priority[p]]);
lev->priority[p] = priority;
iq_insertlast(p,&lev->ready[priority]);
}
else
lev->priority[p] = priority;
}
 
return 0;
}
 
 
 
/advdemos/branches/advdemos/first/makefile
0,0 → 1,35
#
#
 
ifndef BASE
BASE=../..
endif
include $(BASE)/config/config.mk
 
PROGS= test1 test2 test3 test4 test5 test6 test7 testiq
 
include $(BASE)/config/example.mk
 
test1:
make -f $(SUBMAKE) APP=test1 INIT= OTHEROBJS="edfstar.o cbsstar.o" OTHERINCL= SHARKOPT=__OLDCHAR__
 
test2:
make -f $(SUBMAKE) APP=test2 INIT= OTHEROBJS="edfstar.o cbsstar.o" OTHERINCL= SHARKOPT=__OLDCHAR__
 
test3:
make -f $(SUBMAKE) APP=test3 INIT= OTHEROBJS="edfstar.o cbsstar.o" OTHERINCL= SHARKOPT=__OLDCHAR__
 
test4:
make -f $(SUBMAKE) APP=test4 INIT= OTHEROBJS="edfstar.o cbsstar.o" OTHERINCL= SHARKOPT=__OLDCHAR__
 
test5:
make -f $(SUBMAKE) APP=test5 INIT= OTHEROBJS="edfstar.o cbsstar.o" OTHERINCL= SHARKOPT=__OLDCHAR__
 
test6:
make -f $(SUBMAKE) APP=test6 INIT= OTHEROBJS="rmstar.o cbsstar.o" OTHERINCL= SHARKOPT=__OLDCHAR__
 
test7:
make -f $(SUBMAKE) APP=test7 INIT= OTHEROBJS="posixstar.o cbsstar.o" OTHERINCL= SHARKOPT=__OLDCHAR__
 
#testiq:
# make -f $(SUBMAKE) APP=testiq INIT= OTHEROBJS="iqueue.o " OTHERINCL=
/advdemos/branches/advdemos/first/edfstar.h
0,0 → 1,138
/*
* 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: edfstar.h,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
Title:
EDFSTAR
 
Task Models Accepted:
HARD_TASK_MODEL - Hard Tasks (only Periodic)
wcet field and mit field must be != 0. They are used to set the wcet
and period of the tasks.
periodicity field can be only PERIODIC
drel field is ignored
Guest Models Accepted:
JOB_TASK_MODEL - a single guest task activation
Identified by an absolute deadline and a period.
period field is ignored
 
Description:
 
This module schedule his tasks following the classic EDF
scheme. This module is derived from the EDFACT Scheduling Module.
 
This module can not stay alone: when it have to schedule a task, it
simply inserts it into another master module using a
BUDGET_TASK_MODEL.
 
No Task guarantee is performed at all.
The tasks scheduled are only periodic.
All the task are put in a queue and the scheduling is based on the
deadline value.
If a task miss a deadline a counter is incremented.
If a task exausts the wcet a counter is incremented
No ZOMBIE support!!!!!!
 
Exceptions raised:
XUNVALID_GUEST XUNVALID_TASK
some primitives are not implemented:
task_sleep, task_delay, guest_endcycle, guest_sleep, guest_delay
 
XACTIVATION
If a task is actiated through task_activate or guest_activate more than
one time
Restrictions & special features:
- This level doesn't manage the main task.
- Functions to return and reset the nact, wcet and dline miss
counters are provided
 
**/
 
/*
* Copyright (C) 2001 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 __EDFSTAR_H__
#define __EDFSTAR_H__
 
#include <ll/ll.h>
#include <kernel/config.h>
#include <sys/types.h>
#include <kernel/types.h>
 
 
 
/* flags... */
#define EDFSTAR_ENABLE_GUARANTEE 1 /* Task Guarantee enabled */
#define EDFSTAR_ENABLE_ALL 1
 
#define EDFSTAR_FAILED_GUARANTEE 8 /* used in the module, unsettabl
in EDF_register_level... */
 
 
 
#define EDFSTAR_LEVELNAME "EDFSTAR base"
#define EDFSTAR_LEVEL_CODE 166
#define EDFSTAR_LEVEL_VERSION 1
 
 
/* Registration function:
int budget The budget used by this module (see CBSSTAR.h)
int master The master module used by EDFSTAR
*/
LEVEL EDFSTAR_register_level(int budget, int master);
 
/* returns respectively the number of dline, wcet or nact; -1 if error */
int EDFSTAR_get_dline_miss(PID p);
int EDFSTAR_get_wcet_miss(PID p);
int EDFSTAR_get_nact(PID p);
 
/* resets respectively the number of dline, wcet miss; -1 if error */
int EDFSTAR_reset_dline_miss(PID p);
int EDFSTAR_reset_wcet_miss(PID p);
 
#endif
 
/advdemos/branches/advdemos/first/iqueue.c
0,0 → 1,221
/*
* 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: iqueue.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1.1.1 $
Last update: $Date: 2004-05-24 17:54:51 $
------------
 
*/
 
/*
* Copyright (C) 2002 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 "iqueue.h"
#include <kernel/mem.h>
 
void iq_init (IQUEUE *q, IQUEUE *share, int flags)
{
q->first = NIL;
q->last = NIL;
 
if (share)
q->s = share->s;
else {
q->s = (struct IQUEUE_shared *)kern_alloc(sizeof(struct IQUEUE_shared));
 
if (!(flags & IQUEUE_NO_PRIORITY))
q->s->priority = (DWORD *)kern_alloc(sizeof(DWORD) * MAX_PROC);
if (!(flags & IQUEUE_NO_TIMESPEC))
q->s->timespec_priority = (struct timespec *)
kern_alloc(sizeof(struct timespec) * MAX_PROC);
}
}
 
/*+
This function insert the task with PID i in the queue que.
The insertion is made respecting the priority field.
(the first item in the queue have the less priority)
+*/
void iq_priority_insert (PID i, IQUEUE *que)
{
DWORD prio;
PID p,q;
p = NIL;
q = que->first;
prio = que->s->priority[i];
while ((q != NIL) && (prio >= que->s->priority[q])) {
p = q;
q = que->s->next[q];
}
if (p != NIL)
que->s->next[p] = i;
else
que->first = i;
if (q != NIL)
que->s->prev[q] = i;
else
que->last = i;
que->s->next[i] = q;
que->s->prev[i] = p;
}
 
 
/*
This function insert the task with PID i in the queue que.
The insertion is made respecting the timespec priority field.
(the first item in the queue have the less priority)
*/
void iq_timespec_insert(PID i, IQUEUE *que)
{
struct timespec prio;
PID p,q;
 
p = NIL;
q = que->first;
 
TIMESPEC_ASSIGN(&prio, &que->s->timespec_priority[i]);
while ((q != NIL) &&
!TIMESPEC_A_LT_B(&prio, &que->s->timespec_priority[q])) {
p = q;
q = que->s->next[q];
}
if (p != NIL)
que->s->next[p] = i;
else
que->first = i;
if (q != NIL)
que->s->prev[q] = i;
else
que->last = i;
que->s->next[i] = q;
que->s->prev[i] = p;
}
 
 
 
void iq_insertfirst(PID p, IQUEUE *q)
{
if (q->first != NIL) {
q->s->next[p] = q->first;
q->s->prev[q->first] = p;
}
else {
q->last = p;
q->s->next[p] = NIL;
}
q->s->prev[p] = NIL;
q->first = p;
}
 
 
void iq_insertlast(PID p, IQUEUE *q)
{
if (q->last != NIL) {
q->s->prev[p] = q->last;
q->s->next[q->last] = p;
}
else {
q->first = p;
q->s->prev[p] = NIL;
}
q->s->next[p] = NIL;
q->last = p;
}
 
 
void iq_extract(PID i, IQUEUE *que)
{
PID p,q;
p = que->s->prev[i];
q = que->s->next[i];
if (p != NIL)
que->s->next[p] = que->s->next[i];
else
que->first = q;
if (q != NIL)
que->s->prev[q] = que->s->prev[i];
else
que->last = p;
}
 
PID iq_getfirst(IQUEUE *q)
{
PID p = q->first;
if (p == NIL)
return NIL;
 
q->first = q->s->next[q->first];
 
if (q->first != NIL)
q->s->prev[q->first] = NIL;
else
q->last = NIL;
return p;
}
 
PID iq_getlast(IQUEUE *q)
{
PID p = q->last;
if (p == NIL)
return NIL;
 
q->last = q->s->prev[q->last];
 
if (q->last != NIL)
q->s->next[q->last] = NIL;
else
q->first = NIL;
return p;
}
/advdemos/branches/advdemos/chimera/udpdump.c
0,0 → 1,115
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Giacomo Guidi <giacomo@gandalf.sssup.it>
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
#include <netinet/in.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>/* close() */
#include <stdlib.h>
#include <signal.h>
#include <string.h>
 
#define SERVER_PORT 20000
#define MAX_MSG 10000
 
FILE *output_file;
 
int miss;
 
void close_and_exit()
{
 
printf("Closing...\n");
 
if (miss == 1) printf("Possible error receiving packets !\n");
 
fclose(output_file);
 
exit(0);
 
}
 
int main(int argc, char *argv[])
{
int sd, rc, n, cliLen,count;
struct sockaddr_in cliAddr, servAddr;
char msg[MAX_MSG];
 
if (argc < 2) {
printf("%s: Enter the output file name [%s filename]\n",argv[0],argv[0]);
exit(1);
}
 
// socket creation
sd = socket(AF_INET, SOCK_DGRAM, 0);
if(sd < 0) {
printf("%s: cannot open socket \n",argv[0]);
exit(1);
}
 
output_file = fopen(argv[1],"w+b");
if (output_file == NULL) {
printf("%s: Cannot open the file\n",argv[0]);
exit(1);
}
 
// bind local server port
servAddr.sin_family = AF_INET;
 
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(SERVER_PORT);
 
rc = bind (sd, (struct sockaddr *)&servAddr,sizeof(servAddr));
if(rc < 0) {
printf("%s: cannot bind port number %d \n",
argv[0], SERVER_PORT);
exit(1);
}
 
signal(SIGINT, close_and_exit);
 
count = 1;
miss = 0;
 
while(1) {
 
printf("Wait packet...\n");
 
// receive message
cliLen = sizeof(cliAddr);
n = recvfrom(sd, msg, MAX_MSG, 0,(struct sockaddr *)&cliAddr, &cliLen);
 
if (n > 0) {
 
count++;
 
fwrite((void *)(msg),n,1,output_file);
}
 
}
 
fclose(output_file);
 
return 0;
 
}
 
/advdemos/branches/advdemos/chimera/linux.c
0,0 → 1,130
#include <stdio.h>
#include <math.h>
 
#define LEG_A 100.0
#define LEG_B 66.0
#define LEG_C 26.0
#define LEG_D 38.0
#define LEG_CD_2IPO 92.087 /* 2 * sqrt(LEG_C^2 + LEG_D^2) */
#define LEG_CD_ANG 0.600 /* arctg(LEG_C/LEG_D) in radianti */
 
#define PI 3.1415
 
const float c0 = LEG_C * LEG_C;
const float c1 = LEG_B * LEG_B;
const float c2 = LEG_B * LEG_B - LEG_A * LEG_A;
const float todeg = 180.0 / PI;
const float torad = PI / 180.0;
 
int leg_to_ang(float px, float py, float pz, int *alfa, int *beta, int *gamma)
{
float px2 = px * px;
float py2 = py * py;
float pz2 = pz * pz;
 
float pxz2 = px2 + pz2;
 
float alfa1,beta1,alfa2,beta2,gamma1,gamma2;
float m,dsqrt;
 
float delta_xz = pxz2 - c0;
float s,k,k2,y1,delta_xy;
 
if (delta_xz < 0.0) return -1;
 
if (pz >= LEG_C) {
gamma2 = acos((pz * LEG_C + px * sqrt(delta_xz)) / pxz2);
gamma1 = gamma2 * todeg;
} else {
gamma2 = -acos((pz * LEG_C + px * sqrt(delta_xz)) / pxz2);
gamma1 = gamma2 * todeg;
}
 
m = pxz2 - LEG_CD_2IPO * (px * cos(gamma2+LEG_CD_ANG) + pz * sin(gamma2+LEG_CD_ANG) - LEG_CD_2IPO/4);
 
printf("M = %f\n",sqrt(m));
 
s = m + py2;
k = c2 + s;
k2 = k * k;
delta_xy = py2 * k2 - s * (k2 - 4.0 * m * c1);
 
if (delta_xy >= 0.0) {
dsqrt = sqrt(delta_xy);
y1 = (py * k + dsqrt) / (2.0 * s);
beta1 = asin(y1/LEG_B) * todeg;
alfa1 = asin((y1 - py)/LEG_A) * todeg + beta1;
y1 = (py * k - dsqrt) / (2.0 * s);
beta2 = asin(y1/LEG_B) * todeg;
alfa2 = asin((y1 - py)/LEG_A) * todeg + beta2;
 
if ((alfa1 >= 0.0 && alfa1 <= 180.0) && (beta1 >= -90.0 && beta1 <= 90.0)) {
*alfa = (int)(alfa1 * 3600.0);
*beta = (int)(beta1 * 3600.0);
*gamma = (int)(gamma1 * 3600.0);
return 0;
} else if ((alfa2 >= 0.0 && alfa2 <= 180.0) && (beta2 >= -90.0 && beta2 <= 90.0)) {
*alfa = (int)(alfa2 * 3600.0);
*beta = (int)(beta2 * 3600.0);
*gamma = (int)(gamma1 * 3600.0);
return 0;
} else {
return -1;
}
} else
return -1;
 
return -1;
 
}
 
int ang_to_leg(int alfa, int beta, int gamma, float *px, float *py, float *pz) {
 
float alfa1 = (float)(alfa)/3600.0 * torad;
float beta1 = (float)(beta)/3600.0 * torad;
float sin_gamma = sin((float)(gamma)/3600.0 * torad);
float cos_gamma = cos((float)(gamma)/3600.0 * torad);
float m;
m = LEG_B * cos(beta1) + LEG_A * cos(alfa1 - beta1);
*py = LEG_B * sin(beta1) - LEG_A * sin(alfa1 - beta1);
 
*pz = (LEG_D + m) * sin_gamma + LEG_C * cos_gamma;
*px = (LEG_D + m) * cos_gamma - LEG_C * sin_gamma;
 
return 0;
 
}
 
int main() {
 
float px,py,pz;
int a,b,c;
 
while(1) {
 
printf("Insert PX: ");
scanf("%f",&px);
 
printf("Insert PY: ");
scanf("%f",&py);
 
printf("Insert PZ: ");
scanf("%f",&pz);
 
printf("PX: %3.3f PY: %3.3f PZ: %3.3f\n",px,py,pz);
 
if (leg_to_ang(px,py,pz,&a,&b,&c))
printf("Error leg position\n");
 
ang_to_leg(a,b,c,&px,&py,&pz);
 
printf(" A: %7d B: %7d C: %7d\n",a/3600,b/3600,c/3600);
printf("PX: %.3f PY: %.3f PZ: %.3f\n",px,py,pz);
 
}
 
return 0;
 
}
/advdemos/branches/advdemos/chimera/initfile.c
0,0 → 1,66
/*
* Project: HARTIK (HA-rd R-eal TI-me K-ernel)
*
* Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
* Gerardo Lamastra <gerardo@sssup.it>
*
* Authors : Mauro Marinoni <mauro.marinoni@unipv.it>
* Giacomo Guidi <giacomo@gandalf.sssup.it>
* (see authors.txt for full list of hartik's authors)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://hartik.sssup.it
*/
 
#include "chimera.h"
#include "modules/edf.h"
#include "modules/hardcbs.h"
#include "modules/rr.h"
#include "modules/dummy.h"
#include "modules/intdrive.h"
 
#include <drivers/keyb.h>
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
#define INTDRIVE_Q 1000
#define INTDRIVE_T 10000
#define INTDRIVE_FLAGS 0
 
int main(int argc, char **argv);
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
EDF_register_level(EDF_ENABLE_ALL);
HCBS_register_level(HCBS_ENABLE_ALL, 0);
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
SEM_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
/advdemos/branches/advdemos/chimera/calibrate.c
0,0 → 1,188
/*
* Project: S.Ha.R.K.
*
* Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
*
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
#include "chimera.h"
#include <ll/i386/64bit.h>
 
volatile int calibrate_status = 0;
volatile int calibrate_exec_step = 0;
 
extern HEXAPOD_STATE status;
extern unsigned char active_leg;
 
struct leg_calibration {
int side;
int pos[6];
int delta_90[3];
int zero[3];
};
 
struct leg_calibration calibration_table[] = {
{1,{0,90,-45,45,-90,0},{432001,403201,432001},{-201600,28800,241201}},
{-1,{0,90,-45,45,-90,0},{413949,453599,431999},{216000,50401,-215599}},
{1,{0,90,-45,45,-45,45},{417601,388801,424741},{-216000,-43200,82770}},
{-1,{0,90,-45,45,-45,45},{421199,421199,443799},{165600,-8999,30600}},
{1,{0,90,-45,45,0,90},{414001,424801,410401},{-162000,39600,-122400}},
{-1,{0,90,-45,45,0,90},{410399,446399,399599},{154800,-3599,108000}},
};
 
int adjust(int angle_sec, int leg, int num) {
 
int temp;
 
smul32div32to32(angle_sec,calibration_table[leg].delta_90[num],324000,temp);
 
return calibration_table[leg].side * temp + calibration_table[leg].zero[num];
}
 
TASK calibrate(void *arg) {
 
int i, num = 0, angsec = 0, angsec_temp[6];
static int test_angle[20],set,turn_on,servo_count;
char servo_name[10];
 
for (i=0;i<20;i++) test_angle[i] = 0;
 
clear();
servo_turn_off(com(active_leg*3), pin(active_leg*3));
servo_turn_off(com(active_leg*3+1), pin(active_leg*3+1));
servo_turn_off(com(active_leg*3+2), pin(active_leg*3+2));
 
servo_count = 0;
servo_turn_on(com(active_leg*3), pin(active_leg*3));
turn_on = 0;
 
while (calibrate_status == 1) {
 
if (calibrate_exec_step == 100000) {
angsec_temp[servo_count] = test_angle[3*active_leg+num];
printf_xy(0,10+servo_count,WHITE,"%08d",test_angle[3*active_leg+num]);
servo_turn_off(com(3*active_leg+num),pin(3*active_leg+num));
servo_count++;
 
if (servo_count == 6) {
 
for (i=0;i<3;i++) {
calibration_table[active_leg].delta_90[i] = abs(angsec_temp[2*i+1] - angsec_temp[2*i] + 1);
calibration_table[active_leg].zero[i] = calibration_table[active_leg].side * abs(calibration_table[active_leg].pos[2*i] * calibration_table[active_leg].delta_90[i] / 90) + angsec_temp[2*i];
 
printf_xy(22*i,22,WHITE,"D%d %7d Z%d %7d",
i,calibration_table[active_leg].delta_90[i],
i,calibration_table[active_leg].zero[i]);
 
}
 
calibrate_status = 0;
calibrate_exec_step = 0;
 
task_kill(exec_shadow);
task_testcancel();
 
}
 
turn_on = 1;
 
calibrate_exec_step = 0;
 
}
 
switch (servo_count) {
case 0:
case 1:
sprintf(servo_name,"ALFA ");
num = 0;
break;
case 2:
case 3:
sprintf(servo_name,"BETA ");
num = 1;
break;
case 4:
case 5:
sprintf(servo_name,"GAMMA");
num = 2;
break;
}
 
if (turn_on == 1) {
servo_turn_on(com(3*active_leg+num),pin(3*active_leg+num));
turn_on = 0;
}
 
set = calibration_table[active_leg].pos[servo_count];
printf_xy(10,10+servo_count,WHITE,"Set servo %s to position %d",servo_name,set);
servo_turn_on(com(3*active_leg+num),pin(3*active_leg+num));
 
if (calibrate_exec_step != 0) {
test_angle[3*active_leg+num] += calibrate_exec_step;
printf_xy(10,20,WHITE,"Set %08d to servo %03d",test_angle[3*active_leg+num],3*active_leg+num);
servo_set_angle_sec(com(3*active_leg+num), pin(3*active_leg+num), test_angle[3*active_leg+num]);
 
calibrate_exec_step = 0;
 
}
 
angsec = servo_get_angle_sec(com(3*active_leg+num), pin(3*active_leg+num));
printf_xy(10,21,WHITE,"Angle Seconds = %08d",angsec);
 
task_endcycle();
 
}
 
return 0;
 
}
 
void calibrate_init() {
 
SOFT_TASK_MODEL st;
PID st_pid;
 
if (calibrate_status == 0) {
calibrate_status = 1;
 
soft_task_default_model(st);
soft_task_def_period(st,300000);
soft_task_def_met(st,30000);
soft_task_def_usemath(st);
soft_task_def_ctrl_jet(st);
 
st_pid = task_create("Calibration task",calibrate,&st,NULL);
if (st_pid == NIL) {
cprintf("Error creating calibration task\n");
sys_end();
}
 
task_activate(st_pid);
 
} else {
return;
}
}
 
void calibrate_step(int step) {
 
if (calibrate_status != 0 && calibrate_exec_step == 0) {
 
calibrate_exec_step = step;
 
}
 
}
/advdemos/branches/advdemos/chimera/chimera.c
0,0 → 1,293
/*
* Project: S.Ha.R.K.
*
* Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
#include "chimera.h"
 
#define POS_B_REF 0
#define POS_B_UP 50
 
int vel_dx = 15;
int vel_sx = 15;
 
void program_key_end(KEY_EVT* e)
{
 
int i;
TIME tmp;
 
end_send();
 
for (i=3; i<MAX_PROC; i++){
if (!jet_getstat(i, NULL, &tmp, NULL, NULL))
kern_printf("Task Name : %s - Max Time : %d\n", proc_table[i].name, (int)tmp);
}
 
trace_send();
 
sys_end();
 
}
 
int beta = 30;
 
void action_stand_up(void) {
struct action_event e;
int event,alfa;
status.power = 1;
 
kern_gettime(&(e.time));
 
for (alfa=0;alfa<=90;alfa+=15) {
 
ADDUSEC2TIMESPEC(5000000,&(e.time));
e.type = EVT_SET_MASK_LEG_ANGLE;
e.mask = 0x3F;
e.ang.a = alfa * 3600;
e.ang.b = beta * 3600;
e.ang.c = 0 * 3600;
e.pwm = 7;
event = insert_action_event(&(e));
cprintf("Event num = %d\n",event);
 
}
 
}
 
TASK walk_auto_6()
{
short i, n;
int vd, vs, auto_count = 0;
int pos_a[6], pos_b[6], pos_c[6];
struct action_event e;
 
float fake_sin[36] = { .00, .50, .80, 1.0, .80, .50, .00, .00, .00, .00, .00, .00,
.00, .00, .00, .00, .00, .00, .00, .00, .00, .00, .00, .00,
.00, .00, .00, .00, .00, .00, .00, .00, .00, .00, .00, .00};
 
float fake_cos[36] = {-1.0,-.75,-.50, .00, .50, .75, 1.0, .93, .86, .80, .73, .66,
.60, .53, .46, .40, .33, .26, .20, .13, .06, .00,-.06, .13,
-.20,-.26,-.33,-.40,-.46,-.53,-.60,-.66,-.73,-.80,-.86,-.93};
 
while (1) {
vd = vel_dx;
vs = vel_sx;
 
kern_gettime(&(e.time));
ADDUSEC2TIMESPEC(10000,&(e.time));
for (i = 0; i<6; i++) {
switch(i) {
case 0:
n = 0;
break;
case 1:
n = 3;
break;
case 2:
n = 4;
break;
case 3:
n = 1;
break;
case 4:
n = 2;
break;
case 5:
n = 5;
break;
}
if (i%3)
pos_c[i] = vd * fake_cos[(auto_count+6*n)%36];
else
pos_c[i] = vs * fake_cos[(auto_count+6*n)%36];
if ((vs) || (vd))
pos_b[i] = POS_B_REF + fake_sin[(auto_count+6*n)%36] * POS_B_UP;
else
pos_b[i] = POS_B_REF;
 
e.type = EVT_SET_MASK_LEG_ANGLE;
e.mask = 1 << i;
e.ang.a = (80) * 3600;
e.ang.b = (pos_b[i]) * 3600;
e.ang.c = (pos_c[i]) * 3600;
e.pwm = 7;
insert_action_event(&(e));
}
auto_count++;
if (auto_count > 35) auto_count = 0;
 
task_testcancel();
task_endcycle();
}
return 0;
}
 
TASK walk_auto_3()
{
short i;
int vd, vs, auto_count = 0;
float cos_a;
int pos_a[6], pos_b[6], pos_c[6];
 
struct action_event e;
 
 
float fake_cos[32] = { 1.0000, .99518, .98079, .95694, .92388, .88192, .83147, .77301,
.70711, .63439, .55557, .47140, .38268, .29028, .19509, .09802,
.00000,-.09802,-.19509,-.29028,-.38268,-.47140,-.55557,-.63439,
-.70711,-.77301,-.83147,-.88192,-.92388,-.95694,-.98079,-.99518};
float fake_sin[64] = { -0.50, -0.45, -0.40, -0.30, -0.20, -0.15, -0.10, -0.05,
0.00, 0.00, 0.40, 0.40, 0.70, 0.70, 0.90, 0.90,
1.00, 1.00, 0.90, 0.90, 0.70, 0.70, 0.40, 0.40,
0.00, 0.00, -0.05, -0.10, -0.15, -0.20, -0.30, -0.40,
-0.45, -0.50, -0.50, -0.50, -0.50, -0.50, -0.50, -0.50,
-0.50, -0.50, -0.50, -0.50, -0.50, -0.50, -0.50, -0.50,
-0.50, -0.50, -0.50, -0.50, -0.50, -0.50, -0.50, -0.50,
-0.50, -0.50, -0.50, -0.50, -0.50, -0.50, -0.50, -0.50 };
 
while (1) {
cos_a = (auto_count < 32) ? fake_cos[auto_count] : -fake_cos[auto_count-32];
 
vd = vel_dx;
vs = vel_sx;
 
kern_gettime(&(e.time));
ADDUSEC2TIMESPEC(10000,&(e.time));
for (i = 0; i<6; i++) {
switch (i) {
case 0:
/* Leg 0 */
pos_c[i] = vs * cos_a;
if ((vs) || (vd))
pos_b[i] = POS_B_REF + fake_sin[(auto_count+32)%64] * POS_B_UP;
else
pos_b[i] = POS_B_REF;
break;
case 1:
/* Leg 1 */
pos_c[i] = -vd * cos_a;
if ((vs) || (vd))
pos_b[i] = POS_B_REF + fake_sin[auto_count] * POS_B_UP;
else
pos_b[i] = POS_B_REF;
break;
case 2:
/* Leg 2 */
pos_c[i] = -vs * cos_a;
if ((vs) || (vd))
pos_b[i] = POS_B_REF + fake_sin[auto_count] * POS_B_UP;
else
pos_b[i] = POS_B_REF;
break;
case 3:
/* Leg 3 */
pos_c[i] = vd * cos_a;
if ((vs) || (vd))
pos_b[i] = POS_B_REF + fake_sin[(auto_count+32)%64] * POS_B_UP;
else
pos_b[i] = POS_B_REF;
break;
case 4:
/* Leg 4 */
pos_c[i] = vs * cos_a;
if ((vs) || (vd))
pos_b[i] = POS_B_REF + fake_sin[(auto_count+32)%64] * POS_B_UP;
else
pos_b[i] = POS_B_REF;
break;
case 5:
/* Leg 5 */
pos_c[i] = -vd * cos_a;
if ((vs) || (vd))
pos_b[i] = POS_B_REF + fake_sin[auto_count] * POS_B_UP;
else
pos_b[i] = POS_B_REF;
break;
}
 
e.type = EVT_SET_MASK_LEG_ANGLE;
e.mask = 1 << i;
e.ang.a = (80) * 3600;
e.ang.b = (pos_b[i]) * 3600;
e.ang.c = (pos_c[i]) * 3600;
e.pwm = 7;
insert_action_event(&(e));
}
 
auto_count += 4;
if (auto_count > 63) auto_count = 0;
 
task_testcancel();
task_endcycle();
}
return 0;
}
 
void action_walk(void) {
HARD_TASK_MODEL ms;
PID pid_walk;
hard_task_default_model(ms);
hard_task_def_ctrl_jet(ms);
hard_task_def_wcet(ms, 1000);
hard_task_def_mit(ms, 30000);
hard_task_def_usemath(ms);
pid_walk = task_create("Walk_Task", walk_auto_3, &ms, NULL);
if (pid_walk == NIL) {
perror("Could not create task <Walk_Auto>");
sys_end();
} else
task_activate(pid_walk);
}
 
int main(int argc, char **argv)
{
TIME seme;
KEY_EVT k;
 
seme = sys_gettime(NULL);
srand(seme);
 
k.flag = ALTL_BIT;
k.scan = KEY_C;
k.ascii = 'c';
keyb_hook(k,program_key_end);
 
clear();
 
trace_init(1000000);
 
init_send(); /* Comunication */
init_key(); /* Keyboard */
 
init_action_event(100);
 
if (argc < 2) sys_end();
 
beta = atoi(argv[1]);
cprintf("Beta = %d\n",beta);
 
//action_stand_up();
action_walk();
 
return 0;
 
}
/advdemos/branches/advdemos/chimera/send.c
0,0 → 1,453
/*
* Project: S.Ha.R.K.
*
* Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
#include "chimera.h"
#include "tracer.h"
#include "unistd.h"
 
//#define DEBUG_SEND /* Print Sent Values */
#define SERIAL_ON /* Send Data using Serial Port */
 
/* Servo Tasks Constants */
#ifdef DUBUG_SEND
#define SEND_TASK_WCET 26000
#else
#define SEND_TASK_WCET 26000
#endif
#define SEND_TASK_MIT 30000
 
#define LEG_A 100.0
#define LEG_B 66.0
#define LEG_C 26.0
#define LEG_D 38.0
#define LEG_CD_2IPO 92.087 /* 2 * sqrt(LEG_C^2 + LEG_D^2) */
#define LEG_CD_ANG 0.600 /* arctg(LEG_C/LEG_D) in radianti */
 
const float c0 = LEG_C * LEG_C;
const float c1 = LEG_B * LEG_B;
const float c2 = LEG_B * LEG_B - LEG_A * LEG_A;
const float todeg = 180.0 / PI;
const float torad = PI / 180.0;
 
HEXAPOD_STATE status;
 
void *start_tracer = NULL;
void *end_tracer = NULL;
void *trace_pointer = NULL;
 
extern struct leg_calibration calibration_table[];
 
void print_status(int n){
}
 
int leg_to_ang(float px, float py, float pz, int *alfa, int *beta, int *gamma)
{
float px2 = px * px;
float py2 = py * py;
float pz2 = pz * pz;
 
float pxz2 = px2 + pz2;
 
float alfa1,beta1,alfa2,beta2,gamma1,gamma2;
float m,dsqrt;
 
float delta_xz = pxz2 - c0;
float s,k,k2,y1,delta_xy;
 
if (delta_xz < 0.0) return -1;
 
if (pz >= LEG_C) {
gamma2 = acos((pz * LEG_C + px * sqrt(delta_xz)) / pxz2);
gamma1 = gamma2 * todeg;
} else {
gamma2 = -acos((pz * LEG_C + px * sqrt(delta_xz)) / pxz2);
gamma1 = gamma2 * todeg;
}
 
m = pxz2 - LEG_CD_2IPO * (pz * sin(gamma2+LEG_CD_ANG) + px * cos(gamma2+LEG_CD_ANG) - LEG_CD_2IPO / 4.0);
 
s = m + py2;
k = c2 + s;
k2 = k * k;
delta_xy = py2 * k2 - s * (k2 - 4.0 * m * c1);
 
if (delta_xy >= 0.0) {
dsqrt = sqrt(delta_xy);
y1 = (py * k + dsqrt) / (2.0 * s);
beta1 = asin(y1/LEG_B) * todeg;
alfa1 = asin((y1 - py)/LEG_A) * todeg + beta1;
y1 = (py * k - dsqrt) / (2.0 * s);
beta2 = asin(y1/LEG_B) * todeg;
alfa2 = asin((y1 - py)/LEG_A) * todeg + beta2;
 
if ((alfa1 >= 0.0 && alfa1 <= 180.0) && (beta1 >= -90.0 && beta1 <= 90.0)) {
*alfa = (int)(alfa1 * 3600.0);
*beta = (int)(beta1 * 3600.0);
*gamma = (int)(gamma1 * 3600.0);
return 0;
} else if ((alfa2 >= 0.0 && alfa2 <= 180.0) && (beta2 >= -90.0 && beta2 <= 90.0)) {
*alfa = (int)(alfa2 * 3600.0);
*beta = (int)(beta2 * 3600.0);
*gamma = (int)(gamma1 * 3600.0);
return 0;
} else {
return -1;
}
} else
return -1;
 
return -1;
 
}
 
int ang_to_leg(int alfa, int beta, int gamma, float *px, float *py, float *pz) {
 
float alfa1 = (float)(alfa)/3600.0 * torad;
float beta1 = (float)(beta)/3600.0 * torad;
float sin_gamma = sin((float)(gamma)/3600.0 * torad);
float cos_gamma = cos((float)(gamma)/3600.0 * torad);
float m;
m = LEG_B * cos(beta1) + LEG_A * cos(alfa1 - beta1);
*py = LEG_B * sin(beta1) - LEG_A * sin(alfa1 - beta1);
 
*pz = (LEG_D + m) * sin_gamma + LEG_C * cos_gamma;
*px = (LEG_D + m) * cos_gamma - LEG_C * sin_gamma;
 
return 0;
 
}
 
void update_event_action(void) {
 
struct timespec t;
struct action_event *e;
int i;
 
kern_gettime(&t);
 
while ((e = get_first_old_event(&t)) != NULL) {
 
if (e->type == EVT_SET_MASK_LEG_ANGLE) {
 
for (i=0;i<6;i++)
if ((e->mask >> i) & 1) {
 
status.ang[i].a = e->ang.a;
status.ang[i].b = e->ang.b;
status.ang[i].c = e->ang.c;
 
status.cfg[i].pwm = e->pwm;
 
#ifdef DEBUG_SEND
printf_xy(3,2,WHITE,"%8d: Update leg %2d angle",(int)kern_gettime(NULL),i);
#endif
 
 
}
 
e->status = EVT_STATUS_DONE;
 
}
 
}
 
}
 
int trace_init(int buffer_size)
{
 
start_tracer = trace_pointer = (void *)malloc(buffer_size);
end_tracer = start_tracer + buffer_size;
memset(trace_pointer,0,buffer_size);
 
if (trace_pointer == NULL) return -1;
 
return 0;
}
 
/* Init the network stack */
int init_network(char *local_ip)
{
struct net_model m = net_base;
net_setudpip(m, local_ip, "255.255.255.255");
if (net_init(&m) != 1) {
cprintf("Network: Init Error.\n");
return -1;
}
return 0;
}
 
int trace_consumption(int sensor, int value)
{
 
struct timespec t;
SYS_FLAGS f;
 
if (trace_pointer == NULL) return -1;
 
if (trace_pointer >= (end_tracer-16)) return -1;
 
f = kern_fsave();
 
sys_gettime(&t);
 
*(unsigned int *)trace_pointer = (sensor & 0xFF) | 0xAABBFF00;
*(unsigned int *)(trace_pointer + 4) = value;
*(unsigned int *)(trace_pointer + 8) = t.tv_sec;
*(unsigned int *)(trace_pointer + 12) = t.tv_nsec;
 
trace_pointer += 16;
 
kern_frestore(f);
 
return 0;
 
}
 
int trace_send() {
 
static char pkg_buffer[1100];
int actual = 0;
 
UDP_ADDR target, local;
char local_ip[20], target_ip[20];
int socket;
IP_ADDR bindlist[5];
strcpy(local_ip, "192.168.0.99");
strcpy(target_ip, "192.168.0.104");
if (init_network(local_ip)) sys_end();
/* local IP string to addr */
ip_str2addr(local_ip,&(local.s_addr));
/* set the source port */
local.s_port = 20000;
/* target IP string to addr */
ip_str2addr(target_ip,&(bindlist[0]));
memset(&(bindlist[1]), 0, sizeof(IP_ADDR));
/* bind */
socket = udp_bind(&local, NULL);
/* target IP string to addr */
ip_str2addr(target_ip,&(target.s_addr));
/* target port */
target.s_port = 20000;
 
trace_pointer = start_tracer;
actual = 0;
 
while(trace_pointer < end_tracer) {
 
if (((*(int *)(trace_pointer) >> 8) & 0xAABBFF) == 0xAABBFF) {
 
cprintf(".");
 
memcpy(&(pkg_buffer[actual]),trace_pointer,16);
 
actual += 16;
 
if (actual > 800) {
pkg_buffer[actual] = 0;
cprintf("X");
udp_sendto(socket, pkg_buffer, actual, &target);
usleep(100000);
actual = 0;
}
 
}
 
trace_pointer += 16;
 
}
 
pkg_buffer[actual] = 0;
cprintf("X");
udp_sendto(socket, pkg_buffer, actual+1, &target);
usleep(10000);
actual = 0;
 
return 0;
 
}
 
TASK servo_send()
{
HEXAPOD_STATE old_status;
register char new_pos, new_pwm, new_power;
int res,n;
struct timespec t;
int actual_leg = 0;
 
for (n=0; n<6;n++) {
old_status.ang[n].a = 0;
old_status.ang[n].b = 0;
old_status.ang[n].c = 0;
old_status.cfg[n].pwm = 0;
}
old_status.power = 0;
 
while (1) {
new_pos = 0;
new_pwm = 0;
new_power = 0;
 
update_event_action();
 
if (status.power != old_status.power) {
#ifdef SERIAL_ON
task_nopreempt();
if (old_status.power) {
servo_set_RC5_switch(COM2, 1);
} else {
servo_set_RC5_switch(COM2, 0);
}
task_preempt();
old_status.power = status.power;
#endif
}
 
for (n=0; n<6; n++){
#ifdef SERIAL_ON
task_nopreempt();
status.cfg[actual_leg].adc_in = servo_get_analog(COM1, actual_leg);
trace_consumption(actual_leg,status.cfg[actual_leg].adc_in);
task_preempt();
#endif
sys_gettime(&t);
printf_xy(1,20,WHITE,"(%d) (%d) (%d) (%d) (%d) (%d) ",
status.cfg[0].adc_in,
status.cfg[1].adc_in,
status.cfg[2].adc_in,
status.cfg[3].adc_in,
status.cfg[4].adc_in,
status.cfg[5].adc_in);
actual_leg = (actual_leg+1)%6;
 
if ((status.ang[n].a != old_status.ang[n].a) ||
(status.ang[n].b != old_status.ang[n].b) ||
(status.ang[n].c != old_status.ang[n].c)) {
old_status.ang[n].a = status.ang[n].a;
old_status.ang[n].b = status.ang[n].b;
old_status.ang[n].c = status.ang[n].c;
new_pos += 1 << n;
}
 
if (status.cfg[n].pwm != old_status.cfg[n].pwm) {
old_status.cfg[n].pwm = status.cfg[n].pwm;
new_pwm += 1 << n;
}
if (new_pos && (1<<n)) {
#ifdef SERIAL_ON
task_nopreempt();
res = servo_set_angle_sec(com(n*3 ), pin(n*3 ), adjust(status.ang[n].a,n,0));
if (res != 0) cprintf("Error send data\n");
res = servo_set_angle_sec(com(n*3+1), pin(n*3+1), adjust(status.ang[n].b,n,1));
if (res != 0) cprintf("Error send data\n");
res = servo_set_angle_sec(com(n*3+2), pin(n*3+2), adjust(status.ang[n].c,n,2));
if (res != 0) cprintf("Error send data\n");
task_preempt();
#endif
 
}
if (new_pwm && (1<<n)) {
#ifdef SERIAL_ON
task_nopreempt();
(old_status.cfg[n].pwm & 1) ? servo_turn_on(com(n*3 ), pin(n*3 )) : servo_turn_off(com(n*3 ), pin(n*3 ));
(old_status.cfg[n].pwm & 2) ? servo_turn_on(com(n*3+1), pin(n*3+1)) : servo_turn_off(com(n*3+1), pin(n*3+1));
(old_status.cfg[n].pwm & 4) ? servo_turn_on(com(n*3+2), pin(n*3+2)) : servo_turn_off(com(n*3+2), pin(n*3+2));
task_preempt();
#endif
}
}
 
task_testcancel();
task_endcycle();
}
return 0;
}
 
int init_serial()
{
int err;
err = servo_open(COM1, COM_SPEED);
if (!err)
err = servo_open(COM2, COM_SPEED);
 
return err;
}
 
void end_serial()
{
servo_close(COM1);
servo_close(COM2);
}
 
PID servo_pid;
 
void init_send_task()
{
HARD_TASK_MODEL ms;
 
hard_task_default_model(ms);
hard_task_def_ctrl_jet(ms);
hard_task_def_wcet(ms, SEND_TASK_WCET);
hard_task_def_mit(ms, SEND_TASK_MIT);
hard_task_def_usemath(ms);
servo_pid = task_create("Servo_Task", servo_send, &ms, NULL);
if (servo_pid == NIL) {
perror("Could not create task <Send_Task>");
sys_end();
} else
task_activate(servo_pid);
 
}
 
void init_send()
{
int i;
 
if (init_serial()) {
perror("Could not initialize serial port.");
sys_end();
}
 
for (i=0; i<6;i++) {
status.ang[i].a = 0;
status.ang[i].b = 0;
status.ang[i].c = 0;
status.cfg[i].pwm = 0;
}
status.power = 0;
 
init_send_task();
 
}
 
void end_send()
{
task_kill(servo_pid);
 
end_serial();
}
/advdemos/branches/advdemos/chimera/keys.c
0,0 → 1,200
/*
* Project: S.Ha.R.K.
*
* Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
*
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
#include "chimera.h"
 
unsigned char active_leg;
 
extern volatile int calibrate_status;
 
void pad(KEY_EVT *k)
{
switch (k->scan) {
case KEY_Z:
status.power ^= 1;
break;
case KEY_Q:
status.cfg[active_leg].pwm ^= 0x1;
break;
case KEY_W:
status.cfg[active_leg].pwm ^= 0x2;
break;
case KEY_E:
status.cfg[active_leg].pwm ^= 0x4;
break;
case KEY_1:
active_leg = 0;
break;
case KEY_2:
active_leg = 1;
break;
case KEY_3:
active_leg = 2;
break;
case KEY_4:
active_leg = 3;
break;
case KEY_5:
active_leg = 4;
break;
case KEY_6:
active_leg = 5;
break;
case KEY_C:
if (calibrate_status != 0) calibrate_step(100000);
else calibrate_init();
break;
 
case KEY_A:
calibrate_step(-108000);
break;
case KEY_S:
calibrate_step(-3600);
break;
case KEY_D:
calibrate_step(-60);
break;
case KEY_F:
calibrate_step(+60);
break;
case KEY_G:
calibrate_step(+3600);
break;
case KEY_H:
calibrate_step(+108000);
break;
}
}
 
void init_key()
{
KEY_EVT k;
 
k.flag = 0;
k.scan = KEY_1;
k.ascii = '1';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_2;
k.ascii = '2';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_3;
k.ascii = '3';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_4;
k.ascii = '4';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_5;
k.ascii = '5';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_6;
k.ascii = '6';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_J;
k.ascii = 'j';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_K;
k.ascii = 'k';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_L;
k.ascii = 'l';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_U;
k.ascii = 'u';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_I;
k.ascii = 'i';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_O;
k.ascii = 'o';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_Q;
k.ascii = 'q';
keyb_hook(k,pad);
k.flag = 0;
k.scan = KEY_W;
k.ascii = 'w';
keyb_hook(k,pad);
k.flag = 0;
k.scan = KEY_E;
k.ascii = 'e';
keyb_hook(k,pad);
k.flag = 0;
k.scan = KEY_Z;
k.ascii = 'z';
keyb_hook(k,pad);
 
 
k.flag = 0;
k.scan = KEY_C;
k.ascii = 'c';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_A;
k.ascii = 'a';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_S;
k.ascii = 's';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_D;
k.ascii = 'd';
keyb_hook(k,pad);
k.flag = 0;
k.scan = KEY_F;
k.ascii = 'f';
keyb_hook(k,pad);
 
k.flag = 0;
k.scan = KEY_G;
k.ascii = 'g';
keyb_hook(k,pad);
k.flag = 0;
k.scan = KEY_H;
k.ascii = 'h';
keyb_hook(k,pad);
}
/advdemos/branches/advdemos/chimera/list.c
0,0 → 1,87
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Giacomo Guidi <giacomo@gandalf.sssup.it>
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
 
#define READ_BUFFER 2000
#define DELTA_BUFFER 100
 
int main(int argc, char *argv[])
{
 
char buffer[READ_BUFFER+DELTA_BUFFER];
void *p, *last;
int n,delta,size;
 
unsigned long long ev = 0;
 
FILE *input_file;
if (argc < 2) {
printf("%s: Enter the input file name [%s filename]\n",argv[0],argv[0]);
exit(1);
}
 
input_file = fopen(argv[1],"rb");
 
last = buffer + READ_BUFFER;
 
while(!feof(input_file)) {
//move remaining byte
delta = (unsigned int)(buffer) + READ_BUFFER - (unsigned int)(last);
if (delta > 0) memcpy(buffer,last,delta);
 
n = fread(buffer+delta,1,READ_BUFFER+10,input_file);
fseek(input_file,-(delta+10),SEEK_CUR);
 
p = buffer;
 
while ((unsigned int)(p) + 16 <= (unsigned int)(buffer + READ_BUFFER) &&
(unsigned int)(p) + 16 <= (unsigned int)(buffer + n + delta)) {
 
printf("Sensor = %02x ",(*(unsigned int *)(p) & 0xFF));
 
printf("Current = %8d ",*(unsigned int *)(p+4));
printf("TIME = %8d:%8d\n",*(unsigned int *)(p+8),*(unsigned int *)(p+12));
 
size = 16;
 
ev++;
p += 16;
 
if ((unsigned int)(p) + 10 > (unsigned int)(buffer + n + delta)) break;
 
last = p;
}
 
if ((unsigned int)(p) + 10 > (unsigned int)(buffer + n + delta)) break;
}
 
fclose(input_file);
 
return 0;
 
}
 
/advdemos/branches/advdemos/chimera/makefile
0,0 → 1,24
#
#
#
 
ifndef BASE
BASE=../..
endif
include $(BASE)/config/config.mk
 
PROGS= chimera udpdump list
 
include $(BASE)/config/example.mk
 
chimera:
make -f $(SUBMAKE) APP=chimera INIT= OTHEROBJS="initfile.o calibrate.o send.o action.o keys.o" SHARKOPT="__OLDCHAR__ __SERVO__"
 
udpdump: udpdump.c
gcc -Wimplicit-function-declaration -Wall -ggdb\
-I$(BASE)/oslib udpdump.c -o udpdump
 
list: list.c
gcc -Wimplicit-function-declaration -Wall -ggdb\
-I$(BASE)/include/trace -I$(BASE)/oslib list.c -o list
 
/advdemos/branches/advdemos/chimera/chimera.h
0,0 → 1,115
/*
* Project: HARTIK (HA-rd R-eal TI-me K-ernel)
*
* Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
* Gerardo Lamastra <gerardo@sssup.it>
*
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://hartik.sssup.it
*/
 
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <kernel/kern.h>
#include <kernel/func.h>
#include <semaphore.h>
#include "modules/sem.h"
#include "modules/hartport.h"
#include <drivers/keyb.h>
 
#include <servo.h>
#include <drivers/udpip.h>
 
/* COM Port Constants */
#define COM_PORT COM1
#define COM_SPEED 115200
 
#define com(i) ((i) / 12) ? COM1 : COM2
#define pin(i) (i) % 12
 
/* Angle bounds */
#define POS_X_MIN 0
#define POS_X_MAX 200
#define POS_Y_MIN -200
#define POS_Y_MAX 200
#define POS_Z_MIN -150
#define POS_Z_MAX 150
 
typedef struct {
int adc_in;
unsigned char pwm;
} LEG_CFG_STATE;
 
typedef struct { /*describe the position of leg*/
int x;
int y;
int z;
} LEG_POS_STATE;
 
typedef struct { /*describe the servo angles*/
int a;
int b;
int c;
} LEG_ANG_STATE;
 
typedef struct {
LEG_CFG_STATE cfg[6];
LEG_ANG_STATE ang[6];
char power;
} HEXAPOD_STATE;
 
/*****************************************/
 
#define EVT_SET_MASK_LEG_ANGLE 0x01
 
#define EVT_STATUS_FREE 0x00
#define EVT_STATUS_WAIT 0x01
#define EVT_STATUS_EXEC 0x02
#define EVT_STATUS_DONE 0x03
 
struct action_event {
 
unsigned char type;
unsigned char status;
struct timespec time;
unsigned char mask;
LEG_ANG_STATE ang; //Servo angle data
unsigned char pwm;
struct action_event *next;
 
};
 
struct action_event *get_first_old_event(struct timespec *time);
 
extern sem_t mx_status;
extern HEXAPOD_STATE status;
 
void init_send(void);
void end_send(void);
 
void init_key(void);
 
/* Calibration */
 
void calibrate_init(void);
void calibrate_step(int step);
int adjust(int angle_sec, int leg, int num);
 
/* Actions */
 
int init_action_event(int number_of_events);
int insert_action_event(struct action_event *e);
int delete_action_event(int event);
struct action_event * get_first_old_event(struct timespec *time);
 
/* Tracer */
 
int trace_init(int buffer_size);
int trace_consumption(int sensor, int value);
int trace_send();
 
/advdemos/branches/advdemos/chimera/action.c
0,0 → 1,161
/*
* Project: S.Ha.R.K.
*
* Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
#include "chimera.h"
 
struct action_event *first_action_event = NULL;
struct action_event *action_event_list;
int total_events = 0;
 
int get_free_slot();
 
int init_action_event(int number_of_events) {
 
action_event_list = malloc(number_of_events * sizeof(struct action_event));
memset(action_event_list,0,number_of_events * sizeof(struct action_event));
total_events = number_of_events;
 
if (action_event_list != NULL) return 0;
 
total_events = 0;
return -1;
 
}
 
int insert_action_event(struct action_event *e) {
 
struct action_event *t = first_action_event, *k = NULL;
int free;
 
SYS_FLAGS f;
 
f = kern_fsave();
 
free = get_free_slot();
 
if (free != -1) {
memcpy(&(action_event_list[free]),e,sizeof(struct action_event));
e = &(action_event_list[free]);
 
} else {
 
return -1;
 
}
 
e->status = EVT_STATUS_WAIT;
 
if (!t) {
first_action_event = e;
e->next = NULL;
kern_frestore(f);
return 0;
}
 
while(t) {
if (TIMESPEC_A_LT_B(&e->time,&t->time))
break;
k = t;
t = t->next;
}
 
t = k->next;
k->next = e;
e->next = t;
 
t = first_action_event;
 
kern_frestore(f);
 
return free;
 
}
 
int delete_action_event(int event) {
struct action_event *t = first_action_event;
struct action_event *e = &(action_event_list[event]);
SYS_FLAGS f;
if ((!t || !e) && (e->status != EVT_STATUS_FREE)) return -1;
f = kern_fsave();
if (t == e) {
 
first_action_event = t->next;
e->status = EVT_STATUS_FREE;
kern_frestore(f);
return 0;
 
}
while(t) {
if (t->next == e)
break;
t = t->next;
}
if (t) {
t->next = e->next;
e->status = EVT_STATUS_FREE;
kern_frestore(f);
return 0;
}
kern_frestore(f);
return -1;
}
 
int get_free_slot() {
 
int k = 0;
 
while (k < total_events) {
 
if (action_event_list[k].status == EVT_STATUS_FREE ||
action_event_list[k].status == EVT_STATUS_DONE)
return k;
k++;
 
}
 
return -1;
 
}
 
struct action_event * get_first_old_event(struct timespec *time) {
 
struct action_event *t = first_action_event;
SYS_FLAGS f;
 
if (!t) return NULL;
 
f = kern_fsave();
 
if (TIMESPEC_A_GT_B(time,&(t->time))) {
first_action_event = t->next;
t->status = EVT_STATUS_EXEC;
kern_frestore(f);
return t;
}
 
kern_frestore(f);
return NULL;
 
}
/advdemos/branches/advdemos/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/branches/advdemos/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/branches/advdemos/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/branches/advdemos/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/branches/advdemos/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/branches/advdemos/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;
}
 
 
/advdemos/branches/advdemos/block/idetest0.c
0,0 → 1,15
/*
*
*
*
*/
 
#include <fs/bdev.h>
 
#include "common.h"
 
int main(int argc,char *argv[])
{
showmessage("Have ide devices been found?\n");
return 0;
}
/advdemos/branches/advdemos/block/idetest1.c
0,0 → 1,20
/*
*
*
*
*/
 
#include <fs/bdev.h>
 
#include "common.h"
 
int main(int argc,char *argv[])
{
 
showmessage("This test try to identify the partions of all hard disks\n");
bdev_dump_names();
 
waitend();
return 0;
}
/advdemos/branches/advdemos/block/idetest2.c
0,0 → 1,77
/*
*
*
*
*/
 
#include <ll/i386/cons.h>
#include <drivers/keyb.h>
 
#include <fs/bdevinit.h>
#include <fs/bdev.h>
 
#include <string.h>
 
#include "common.h"
 
#define DISKDEVICE "ide/hda1"
 
__uint8_t buffer[2048] __attribute__ ((aligned (4)));
__dev_t dev;
 
extern char *ide_error_msg[];
 
int main(int argc,char *argv[])
{
__blkcnt_t blk;
int res;
int c;
 
showmessage("This test try to read some blocks from first hard disk\n");
 
dev=bdev_find_byname(DISKDEVICE);
if (dev<0) {
cprintf("Can't find device to operate with\n");
return -1;
}
cprintf("Using device %s (dev=%04x)\n",DISKDEVICE,dev);
 
blk=0;
for (;;) {
cprintf("Commands: x-exit r-read n-next block p-prev block\n");
c = keyb_getchar();
switch(c) {
case 'x':
return 0;
 
case 'n':
blk++;
cprintf("Block %li\n",(long)blk);
break;
 
case 'p':
if (blk>=0) blk--;
cprintf("Block %li\n",(long)blk);
break;
case 'r':
cprintf("Reading block %li...\n",(long)blk);
memset(buffer,0xff,sizeof(buffer));
res=bdev_read(dev,blk,buffer);
cprintf("Result %i\n",res);
//cprintf("Soft reset done %i\n",ide[0].errors);
if (res!=0) {
cprintf(" %s\n",(char*)ide_error_msg[-res]);
}
debug_dump_buffer(buffer,64);
break;
 
default:
cprintf("Invalid command!\n");
break;
}
cprintf("\n");
}
return 0;
}
/advdemos/branches/advdemos/block/idetest3.c
0,0 → 1,66
/*
*
*
*
*/
 
#include <ll/i386/cons.h>
#include <drivers/keyb.h>
 
#include <fs/bdevinit.h>
#include <fs/bdev.h>
 
#include <string.h>
 
#include "common.h"
 
#define DISKDEVICE "ide/hda1"
#define BLOCKNUMBER 58549
 
__uint8_t buffer[2048] __attribute__ ((aligned (4)));
 
extern char *ide_error_msg[];
 
int main(int argc,char *argv[])
{
__dev_t dev;
__blkcnt_t blk;
int res;
// int c;
 
showmessage("This test tries to read a block from the first hard disk\n"
"and then it tries to write it to disk\n"
"Press [CTRL-C] to abort...");
dev=bdev_find_byname(DISKDEVICE);
if ((int)dev<0) {
cprintf("Can't find device to operate with\n");
cprintf("%s not present!\n",DISKDEVICE);
return -1;
}
cprintf("Using device %s (dev=%04x)\n",DISKDEVICE,dev);
blk=BLOCKNUMBER;
 
cprintf("Reading block %li...\n",(long)blk);
memset(buffer,0xff,sizeof(buffer));
res=bdev_read(dev,blk,buffer);
cprintf("Result %i\n",res);
//cprintf("Soft reset done %i\n",ide[0].errors);
if (res!=0) {
cprintf(" %s\n",(char*)ide_error_msg[-res]);
return -1;
}
debug_dump_buffer(buffer,64);
 
cprintf("Writing block %li...\n",(long)blk);
res=bdev_write(dev,blk,buffer);
cprintf("Result %i\n",res);
//cprintf("Soft reset done %i\n",ide[0].errors);
if (res!=0) {
cprintf(" %s\n",(char*)ide_error_msg[-res]);
}
 
waitend();
return 0;
}
/advdemos/branches/advdemos/block/idelin.c
0,0 → 1,71
/*
*
*
*
*/
 
#include <ll/i386/cons.h>
#include <kernel/func.h>
 
#include <fs/bdevinit.h>
#include <fs/bdev.h>
 
#include <stdlib.h>
#include <string.h>
 
#include "common.h"
 
#define DISKDEVICE "ide/hda"
 
#define TEST_MB 16
 
#define NUMBLOCK (TEST_MB*1024l*1024l/512l)
 
__dev_t dev;
 
__uint8_t buffer[2048];
 
int main(int argc,char *argv[])
{
__blkcnt_t blk;
int res;
int errors;
TIME sttime,etime;
 
showmessage("\n"
"This test read data from first hard disk to test\n"
"disk throughtput.\n"
"Remeber that the reads are made block by block so\n"
"don't worry if you see a low throughtput.\n"
);
dev=bdev_find_byname(DISKDEVICE);
if (dev<0) {
cprintf("\nCan't find device to operate with\n");
return -1;
}
cprintf("\nUsing device %s (dev=%04x)\n",DISKDEVICE,dev);
 
cprintf("Please wait (reading %i MB linearly?!?)...",TEST_MB);
 
sttime=sys_gettime(NULL);
errors=0;
for (blk=0;blk<NUMBLOCK;blk++) {
res=bdev_read(dev,blk,buffer);
//res=bdev_seek(dev,blk);
if (res!=0) errors++;
}
etime=sys_gettime(NULL)-sttime;
 
cprintf("\nDone\n\n");
cprintf("elapse time : %li sec %li msec\n",
etime/1000000l,
(etime/1000l)%1000l);
cprintf("throughtput : %6.3f MB/s\n",
NUMBLOCK*512.0/1024.0/1024.0/etime*1000000.0);
//cprintf("soft reset made: %i\n",ide[0].errors);
cprintf("errors : %i\n",errors);
cprintf("\n");
return 0;
}
/advdemos/branches/advdemos/block/idernd.c
0,0 → 1,68
/*
*
*
*
*/
 
#include <ll/i386/cons.h>
#include <kernel/func.h>
 
#include <fs/bdevinit.h>
#include <fs/bdev.h>
 
#include <stdlib.h>
#include <string.h>
 
#include "common.h"
 
#define DISKDEVICE "ide/hda1"
 
#define NUMBLOCK 1000
 
__dev_t dev;
__uint8_t buffer[2048];
 
int main(int argc,char *argv[])
{
__blkcnt_t blk;
int res;
int errors;
TIME sttime,etime;
showmessage("\n"
"This test read RAMDOMLY data from first hard disk to test\n"
"disk throughtput.\n"
"Remeber that the reads are made RANDOMLY block by block so\n"
"don't worry if you see a VERY low throughtput.\n"
);
srand(7);
 
dev=bdev_find_byname(DISKDEVICE);
if (dev<0) {
cprintf("\nCan't find device to operate with\n");
return -1;
}
cprintf("\nUsing device %s (dev=%04x)\n",DISKDEVICE,dev);
 
cprintf("Please wait (reading %i KB ramdomly)...",NUMBLOCK/2);
 
sttime=sys_gettime(NULL);
errors=0;
for (blk=0;blk<NUMBLOCK;blk++) {
res=bdev_read(dev,rand()%5000,buffer);
if (res!=0) errors++;
}
etime=sys_gettime(NULL)-sttime;
 
cprintf("\nDone\n\n");
cprintf("elapse time : %li sec %li msec\n",
etime/1000000l,
(etime/1000l)%1000l);
cprintf("throughtput : %6.3f KB/s\n",
NUMBLOCK*512.0/1024.0/etime*1000000.0);
//cprintf("soft reset made: %i\n",ide[0].errors);
cprintf("errors : %i\n",errors);
cprintf("\n");
return 0;
}
/advdemos/branches/advdemos/block/common.c
0,0 → 1,74
 
#include <kernel/func.h>
 
#include <fs/bdevinit.h>
#include <fs/fsinit.h>
#include <fs/bdev.h>
 
#include <drivers/keyb.h>
 
#include <sys/mount.h>
 
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
 
/* -- */
 
int __register_sub_init(void)
{
return 0;
}
 
/* -- */
 
int __bdev_sub_init(void)
{
BDEV_PARMS bdev=BASE_BDEV;
bdev_def_showinfo(bdev,TRUE);
bdev_init(&bdev);
 
return 0;
}
 
/* -- */
 
void ctrlc_exit(KEY_EVT *k)
{
cprintf("CTRL-C pressed!\n");
sys_end();
}
 
/* -- */
 
void showmessage(char *s)
{
cputs(s);
cprintf("Press [x] to begin...");
while (keyb_getchar()!='x');
cprintf("\n");
}
 
void waitend(void)
{
int c;
cprintf("Press [x] to exit...");
while ((c=keyb_getchar())!='x');
cprintf("\n");
}
 
/* -- */
 
void debug_dump_buffer(char *buf, int size)
{
int i;
for (i=0;i<size;i++) {
if (i%16==0) {
if (i!=0) cprintf("\n");
cprintf("%04x: ",i);
}
cprintf("%02x ",(unsigned char)*(buf+i));
}
cprintf("\n");
}
/advdemos/branches/advdemos/block/makefile
0,0 → 1,34
#
#
#
 
ifndef BASE
BASE=../..
endif
include $(BASE)/config/config.mk
 
PROGS=idetest0 idetest1 idetest2 idetest3 idelin idernd idetx430
 
include $(BASE)/config/example.mk
 
#
#
#
 
idetest0:
make -f $(SUBMAKE) BASE=$(BASE) APP=idetest0 OTHEROBJS="common.o initblk.o" SHARKOPT=__OLDCHAR__
 
idetest1:
make -f $(SUBMAKE) BASE=$(BASE) APP=idetest1 OTHEROBJS="common.o initblk.o" SHARKOPT=__OLDCHAR__
 
idetest2:
make -f $(SUBMAKE) BASE=$(BASE) APP=idetest2 OTHEROBJS="common.o initblk.o" SHARKOPT=__OLDCHAR__
 
idetest3:
make -f $(SUBMAKE) BASE=$(BASE) APP=idetest3 OTHEROBJS="common.o initblk.o" SHARKOPT=__OLDCHAR__
 
idelin:
make -f $(SUBMAKE) BASE=$(BASE) APP=idelin OTHEROBJS="common.o initblk.o" SHARKOPT=__OLDCHAR__
 
idernd:
make -f $(SUBMAKE) BASE=$(BASE) APP=idernd OTHEROBJS="common.o initblk.o" SHARKOPT=__OLDCHAR__
/advdemos/branches/advdemos/block/initblk.c
0,0 → 1,113
/*
* 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
*/
 
/*
* 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
*
*/
 
/*
* CVS : $Id: initblk.c,v 1.1.1.1 2004-05-24 17:54:51 giacomo Exp $
*
* File: $File$
* Revision: $Revision: 1.1.1.1 $
* Last update: $Date: 2004-05-24 17:54:51 $
*/
 
#include "kernel/kern.h"
#include "modules/edf.h"
#include "modules/rr.h"
#include "modules/cbs.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
#include "modules/pi.h"
#include "modules/pc.h"
#include "modules/srp.h"
#include "modules/npp.h"
#include "modules/nop.h"
#include "modules/nopm.h"
 
#include "drivers/keyb.h"
 
/*+ sysyem tick in us +*/
#define TICK 1000
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
extern int __register_sub_init(void);
EDF_register_level(EDF_ENABLE_ALL);
RR_register_level(RRTICK, RR_MAIN_YES, mb);
CBS_register_level(CBS_ENABLE_ALL, 0);
dummy_register_level();
 
SEM_register_module();
 
CABS_register_module();
 
PI_register_module();
PC_register_module();
NPP_register_module();
SRP_register_module();
NOP_register_module();
NOPM_register_module();
 
__register_sub_init();
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
KEYB_PARMS keyb = BASE_KEYB;
extern int __bdev_sub_init(void);
extern void ctrlc_exit(KEY_EVT *k);
HARTPORT_init();
keyb_def_ctrlC(keyb, ctrlc_exit);
KEYB_init(&keyb);
 
__bdev_sub_init();
__call_main__(mb);
 
return (void *)0;
}
/advdemos/branches/advdemos/block/readme
0,0 → 1,33
Hi,
 
These are the block devices demos.
 
- THEY DO NOT WRITE ON YOUR HD, so they are not dangerous.
 
- They do not require a FAT16 Filesystem.
 
 
idetest0:
The demo identifies your Hard Disk characteristics and prints it on
the screen.
 
idetest1:
The demo identifies all the partitions of your HD.
 
idetest2:
The demo allows you to select a sector on the HD and to read it.
 
idetest3:
The demo reads a random sector and then it writes it in the same position.
 
idelin:
The demo reads 16Mb of data from the HD. The data is read block by
block, linearly.
 
idernd:
The demo reads 512Kb of data from the HD. The data is read block by
block, randomly.
 
Enjoy,
 
PJ
/advdemos/branches/advdemos/block/common.h
0,0 → 1,11
 
#ifndef __COMMON_H
#define __COMMON_H
 
void showmessage(char *s);
void waitend(void);
 
void debug_dump_buffer(char *buf, int size);
 
#endif
/advdemos/branches/advdemos/mpeg2/ieee1180
0,0 → 1,245
IEEE 1180 report for mpeg2decode fast integer IDCT:
 
From stefan@lis.e-technik.tu-muenchen.de Thu May 26 08:18:36 1994
 
IEEE test conditions: -L = -256, +H = 255, sign = 1, #iters = 10000
Peak absolute values of errors:
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
Worst peak error = 1 (meets spec limit 1)
 
Mean square errors:
0.0058 0.0118 0.0097 0.0057 0.0055 0.0117 0.0120 0.0063
0.0106 0.0157 0.0142 0.0099 0.0115 0.0168 0.0154 0.0123
0.0128 0.0156 0.0152 0.0095 0.0115 0.0147 0.0173 0.0096
0.0055 0.0115 0.0103 0.0078 0.0069 0.0092 0.0113 0.0071
0.0057 0.0134 0.0123 0.0067 0.0050 0.0109 0.0128 0.0065
0.0101 0.0172 0.0159 0.0093 0.0097 0.0148 0.0163 0.0130
0.0113 0.0171 0.0148 0.0103 0.0110 0.0153 0.0149 0.0093
0.0064 0.0123 0.0104 0.0065 0.0064 0.0111 0.0099 0.0066
Worst pmse = 0.017300 (meets spec limit 0.06)
Overall mse = 0.010998 (meets spec limit 0.02)
 
Mean errors:
0.0014 0.0004 0.0003 0.0017 0.0003 0.0011 0.0010 -0.0001
0.0000 0.0003 0.0010 0.0003 0.0007 -0.0006 0.0004 0.0033
0.0000 -0.0008 -0.0006 0.0009 -0.0015 -0.0013 -0.0017 -0.0008
-0.0017 0.0019 -0.0005 0.0010 0.0005 0.0000 -0.0017 -0.0001
0.0007 0.0034 0.0015 0.0021 0.0016 0.0007 -0.0006 0.0011
-0.0007 0.0004 -0.0001 0.0003 0.0003 0.0004 0.0031 -0.0010
0.0009 -0.0005 -0.0004 0.0003 0.0008 -0.0015 -0.0007 -0.0007
0.0024 0.0001 0.0018 -0.0003 -0.0006 -0.0001 0.0009 0.0018
Worst mean error = 0.003400 (meets spec limit 0.015)
Overall mean error = 0.000352 (meets spec limit 0.0015)
 
0 elements of IDCT(0) were not zero
 
 
25.8u 0.1s 0:27 95% 0+216k 0+2io 0pf+0w
IEEE test conditions: -L = -5, +H = 5, sign = 1, #iters = 10000
Peak absolute values of errors:
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
Worst peak error = 1 (meets spec limit 1)
 
Mean square errors:
0.0008 0.0008 0.0006 0.0006 0.0006 0.0006 0.0007 0.0005
0.0005 0.0003 0.0005 0.0001 0.0003 0.0007 0.0007 0.0004
0.0004 0.0012 0.0011 0.0007 0.0010 0.0008 0.0010 0.0003
0.0004 0.0004 0.0001 0.0002 0.0004 0.0007 0.0009 0.0004
0.0005 0.0005 0.0004 0.0002 0.0006 0.0004 0.0012 0.0003
0.0008 0.0006 0.0007 0.0007 0.0003 0.0012 0.0011 0.0004
0.0006 0.0002 0.0001 0.0002 0.0005 0.0005 0.0007 0.0005
0.0008 0.0004 0.0006 0.0003 0.0008 0.0006 0.0002 0.0003
Worst pmse = 0.001200 (meets spec limit 0.06)
Overall mse = 0.000561 (meets spec limit 0.02)
 
Mean errors:
0.0008 0.0006 0.0000 0.0006 0.0006 0.0002 0.0005 0.0003
0.0005 0.0003 0.0003 0.0001 0.0001 0.0001 0.0005 0.0002
0.0004 0.0006 0.0005 0.0007 0.0006 0.0004 0.0002 -0.0001
0.0002 0.0002 0.0001 0.0002 0.0004 0.0005 0.0003 0.0002
0.0003 0.0003 0.0004 0.0002 0.0006 0.0000 0.0002 0.0003
-0.0002 0.0004 0.0007 0.0005 0.0001 0.0010 0.0005 -0.0002
0.0004 0.0000 0.0001 0.0000 0.0001 0.0003 0.0005 0.0003
0.0006 0.0000 0.0002 0.0003 0.0004 0.0002 0.0002 0.0001
Worst mean error = 0.001000 (meets spec limit 0.015)
Overall mean error = 0.000311 (meets spec limit 0.0015)
 
0 elements of IDCT(0) were not zero
 
 
25.7u 0.1s 0:27 95% 0+216k 0+3io 0pf+0w
IEEE test conditions: -L = -300, +H = 300, sign = 1, #iters = 10000
Peak absolute values of errors:
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
Worst peak error = 1 (meets spec limit 1)
 
Mean square errors:
0.0068 0.0097 0.0119 0.0064 0.0065 0.0105 0.0112 0.0050
0.0088 0.0130 0.0128 0.0088 0.0111 0.0152 0.0139 0.0109
0.0114 0.0127 0.0157 0.0099 0.0114 0.0137 0.0153 0.0109
0.0052 0.0097 0.0120 0.0060 0.0067 0.0114 0.0099 0.0065
0.0062 0.0096 0.0091 0.0064 0.0076 0.0092 0.0111 0.0058
0.0096 0.0139 0.0166 0.0112 0.0092 0.0141 0.0122 0.0103
0.0121 0.0138 0.0131 0.0089 0.0108 0.0172 0.0127 0.0104
0.0070 0.0109 0.0092 0.0055 0.0057 0.0128 0.0102 0.0069
Worst pmse = 0.017200 (meets spec limit 0.06)
Overall mse = 0.010316 (meets spec limit 0.02)
 
Mean errors:
-0.0010 0.0015 0.0001 -0.0004 0.0005 -0.0001 0.0008 0.0000
0.0004 0.0016 0.0006 0.0000 -0.0001 0.0004 0.0011 0.0001
-0.0008 0.0013 0.0015 0.0003 0.0010 0.0005 -0.0005 0.0021
0.0006 0.0013 -0.0004 0.0000 0.0007 -0.0002 -0.0009 0.0003
0.0004 0.0004 -0.0001 -0.0004 0.0014 0.0018 0.0017 -0.0002
0.0024 0.0007 -0.0002 -0.0018 0.0004 0.0001 0.0010 0.0009
0.0001 -0.0002 0.0005 0.0003 -0.0016 0.0004 0.0013 -0.0006
-0.0012 -0.0017 -0.0008 0.0003 0.0001 0.0018 0.0008 -0.0005
Worst mean error = 0.002400 (meets spec limit 0.015)
Overall mean error = 0.000309 (meets spec limit 0.0015)
 
0 elements of IDCT(0) were not zero
 
 
25.8u 0.0s 0:27 95% 0+216k 0+4io 0pf+0w
IEEE test conditions: -L = -256, +H = 255, sign = -1, #iters = 10000
Peak absolute values of errors:
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
Worst peak error = 1 (meets spec limit 1)
 
Mean square errors:
0.0061 0.0118 0.0097 0.0057 0.0058 0.0113 0.0115 0.0061
0.0105 0.0159 0.0138 0.0097 0.0113 0.0166 0.0149 0.0123
0.0129 0.0155 0.0152 0.0095 0.0112 0.0145 0.0173 0.0094
0.0059 0.0112 0.0105 0.0076 0.0071 0.0091 0.0113 0.0073
0.0061 0.0130 0.0128 0.0066 0.0051 0.0108 0.0126 0.0067
0.0099 0.0168 0.0161 0.0095 0.0100 0.0149 0.0166 0.0132
0.0113 0.0171 0.0150 0.0101 0.0110 0.0157 0.0152 0.0094
0.0062 0.0121 0.0102 0.0065 0.0061 0.0112 0.0099 0.0065
Worst pmse = 0.017300 (meets spec limit 0.06)
Overall mse = 0.010980 (meets spec limit 0.02)
 
Mean errors:
-0.0005 0.0006 0.0001 -0.0007 0.0006 -0.0003 -0.0003 0.0011
0.0011 0.0003 -0.0002 0.0005 -0.0001 0.0008 0.0001 -0.0027
0.0013 0.0015 0.0010 -0.0001 0.0020 0.0019 0.0025 0.0016
0.0023 -0.0008 0.0011 -0.0002 0.0007 0.0003 0.0019 0.0009
-0.0003 -0.0030 -0.0002 -0.0012 -0.0009 0.0000 0.0010 -0.0005
0.0009 0.0002 0.0015 0.0007 0.0002 0.0001 -0.0026 0.0018
0.0001 0.0011 0.0010 0.0005 -0.0004 0.0023 0.0014 0.0014
-0.0014 0.0007 -0.0014 0.0009 0.0013 0.0006 -0.0007 -0.0007
Worst mean error = 0.003000 (meets spec limit 0.015)
Overall mean error = 0.000355 (meets spec limit 0.0015)
 
0 elements of IDCT(0) were not zero
 
 
25.8u 0.1s 0:27 95% 0+216k 0+3io 0pf+0w
IEEE test conditions: -L = -5, +H = 5, sign = -1, #iters = 10000
Peak absolute values of errors:
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
Worst peak error = 1 (meets spec limit 1)
 
Mean square errors:
0.0010 0.0007 0.0008 0.0004 0.0008 0.0004 0.0005 0.0007
0.0005 0.0007 0.0005 0.0004 0.0006 0.0005 0.0005 0.0003
0.0003 0.0011 0.0009 0.0007 0.0008 0.0006 0.0011 0.0006
0.0003 0.0004 0.0002 0.0002 0.0003 0.0006 0.0008 0.0006
0.0004 0.0005 0.0006 0.0006 0.0003 0.0007 0.0007 0.0003
0.0013 0.0006 0.0008 0.0005 0.0004 0.0006 0.0008 0.0004
0.0003 0.0003 0.0003 0.0002 0.0005 0.0004 0.0006 0.0005
0.0005 0.0003 0.0006 0.0005 0.0011 0.0007 0.0005 0.0003
Worst pmse = 0.001300 (meets spec limit 0.06)
Overall mse = 0.000561 (meets spec limit 0.02)
 
Mean errors:
0.0002 0.0005 0.0008 0.0000 0.0002 0.0004 0.0003 0.0007
0.0001 0.0003 0.0003 0.0002 0.0006 0.0003 0.0001 0.0003
-0.0001 0.0007 0.0003 0.0001 0.0002 0.0006 0.0005 0.0006
0.0001 0.0004 0.0002 0.0002 0.0001 0.0002 0.0004 0.0004
0.0002 0.0005 0.0006 0.0004 0.0001 0.0005 0.0005 0.0003
0.0009 0.0002 0.0000 0.0001 0.0004 0.0000 0.0006 0.0004
0.0003 0.0003 0.0003 0.0002 0.0003 0.0000 0.0004 0.0003
0.0003 0.0003 0.0004 0.0003 0.0007 0.0005 0.0005 0.0003
Worst mean error = 0.000900 (meets spec limit 0.015)
Overall mean error = 0.000333 (meets spec limit 0.0015)
 
0 elements of IDCT(0) were not zero
 
 
25.7u 0.1s 0:27 95% 0+216k 0+0io 0pf+0w
IEEE test conditions: -L = -300, +H = 300, sign = -1, #iters = 10000
Peak absolute values of errors:
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
Worst peak error = 1 (meets spec limit 1)
 
Mean square errors:
0.0067 0.0097 0.0118 0.0060 0.0066 0.0107 0.0113 0.0049
0.0082 0.0132 0.0128 0.0088 0.0110 0.0152 0.0140 0.0109
0.0122 0.0125 0.0156 0.0098 0.0113 0.0139 0.0152 0.0106
0.0054 0.0097 0.0121 0.0064 0.0067 0.0110 0.0096 0.0062
0.0064 0.0099 0.0090 0.0067 0.0078 0.0089 0.0112 0.0057
0.0098 0.0136 0.0165 0.0111 0.0090 0.0138 0.0120 0.0103
0.0121 0.0135 0.0131 0.0087 0.0107 0.0168 0.0128 0.0102
0.0069 0.0109 0.0091 0.0057 0.0061 0.0125 0.0103 0.0070
Worst pmse = 0.016800 (meets spec limit 0.06)
Overall mse = 0.010283 (meets spec limit 0.02)
 
Mean errors:
0.0015 -0.0009 0.0006 0.0012 0.0002 0.0007 -0.0001 0.0005
0.0004 -0.0010 0.0000 0.0004 0.0006 0.0004 -0.0004 0.0007
0.0018 -0.0009 -0.0006 0.0000 -0.0003 -0.0001 0.0014 -0.0006
-0.0002 -0.0011 0.0009 0.0004 -0.0003 0.0010 0.0010 0.0000
0.0004 0.0001 0.0010 0.0011 -0.0008 -0.0017 -0.0006 0.0009
-0.0020 0.0000 0.0007 0.0021 0.0002 0.0002 -0.0004 -0.0003
0.0003 0.0005 -0.0003 -0.0001 0.0017 0.0002 -0.0004 0.0010
0.0015 0.0023 0.0013 0.0003 0.0005 -0.0011 -0.0003 0.0006
Worst mean error = 0.002300 (meets spec limit 0.015)
Overall mean error = 0.000252 (meets spec limit 0.0015)
 
0 elements of IDCT(0) were not zero
 
 
25.8u 0.0s 0:27 94% 0+216k 0+3io 0pf+0w
 
/advdemos/branches/advdemos/mpeg2/makefile.lib
0,0 → 1,54
#
# The mpeg library
#
 
# (see sources for copyrights)
 
ifndef BASE
BASE=../..
endif
include $(BASE)/config/config.mk
 
LIBRARY = mpeg2
 
OBJS_PATH = $(BASE)/ports/mpeg2
 
DECODER_SRC = util.c \
video.c \
parseblock.c \
motionvector.c \
decoders.c \
jrevdct.c \
wrapper.c \
gdith.c \
gdithmni.c \
readfile.c \
16bit.c
 
DITHER_SRC = fs2.c \
fs2fast.c \
fs4.c \
hybrid.c \
hybriderr.c \
2x2.c \
gray.c \
mono.c \
ordered.c \
ordered2.c \
mb_ordered.c
 
SRCS= $(DECODER_SRC) $(DITHER_SRC)
 
OBJS= mpeg2dec.o getpic.o motion.o getvlc.o \
gethdr.o getblk.o getbits.o store.o \
recon.o spatscal.o idct.o idctref.o \
display.o systems.o subspic.o verify.o
 
#C_WARN += -Wno-unused -Wno-uninitialized -Wno-implicit-function-declaration \
# -Wno-switch -Wno-return-type
 
#C_DEF += -DNOCONTROLS
#C_INC += -I.
 
include $(BASE)/config/lib.mk
 
/advdemos/branches/advdemos/mpeg2/jetctrl.c
0,0 → 1,163
/*
* 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: jetctrl.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 $
------------
**/
 
/*
* 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
*
*/
 
/*
* this file is directly derived from the demos/jumpball/jetctrl.c .
* I just added this controls to check when the system will become overloaded
*/
 
#define WCET_JETDUMMY 200
#define PERIOD_JETDUMMY 100000
#define DUMMY_PID 1
 
#define JET_DUMMY_WIDTH (CMD_WIDTH-370)
#define JET_DUMMY_HEIGHT (CMD_HEIGHT-40)
 
/* the point (x, y) is the top left corner */
#define JET_DUMMY_X (TRACK_X1+360)
#define JET_DUMMY_Y (TRACK_Y2+32)
 
// from jetdummy in the auto demo
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
/* Track dimensions */
#define TRACK_WIDTH 500
#define TRACK_HEIGHT 500
/* Track position */
#define TRACK_X1 0
#define TRACK_Y1 0
#define TRACK_X2 TRACK_X1+TRACK_WIDTH-1
#define TRACK_Y2 TRACK_Y1+TRACK_HEIGHT-1
#define CMD_WIDTH TRACK_WIDTH
#define CMD_HEIGHT (SCREEN_HEIGHT-TRACK_HEIGHT-3)
 
// JetControl
 
#include "kernel/func.h"
#include "drivers/glib.h"
 
/* useful colors... */
int white;
int black;
int red;
int lightgray;
 
TASK jetdummy_task(void *arg)
{
TIME now_dummy, last_dummy, diff_dummy, slice;
struct timespec now, last, diff;
int x = 0;
int height;
 
NULL_TIMESPEC(&last);
last_dummy = 0;
for (;;) {
task_nopreempt();
jet_getstat(DUMMY_PID, NULL, NULL, NULL, &now_dummy);
sys_gettime(&now);
task_preempt();
 
SUBTIMESPEC(&now, &last, &diff);
slice = diff.tv_sec * 1000000 + diff.tv_nsec/1000;
diff_dummy = now_dummy - last_dummy;
 
height = (int)(JET_DUMMY_HEIGHT*((float)diff_dummy)/((float)slice));
 
TIMESPEC_ASSIGN(&last, &now);
last_dummy = now_dummy;
 
grx_line(JET_DUMMY_X+x,JET_DUMMY_Y,
JET_DUMMY_X+x,JET_DUMMY_Y+height ,black);
grx_line(JET_DUMMY_X+x,JET_DUMMY_Y+height,
JET_DUMMY_X+x,JET_DUMMY_Y+JET_DUMMY_HEIGHT,white);
grx_line(JET_DUMMY_X+(x+1)%JET_DUMMY_WIDTH,JET_DUMMY_Y,
JET_DUMMY_X+(x+1)%JET_DUMMY_WIDTH,JET_DUMMY_Y+JET_DUMMY_HEIGHT,255);
 
x = (x+1)%JET_DUMMY_WIDTH;
 
task_endcycle();
}
}
 
void init_jetcontrol(void)
{
SOFT_TASK_MODEL m4;
 
PID p4;
 
/* useful colors ... */
white = rgb16(255,255,255);
black = rgb16(0,0,0);
red = rgb16(255,0,0);
lightgray = rgb16(128,128,128);
 
/* scenario */
grx_text("System load",
JET_DUMMY_X+8, JET_DUMMY_Y-10, lightgray, black);
grx_rect(JET_DUMMY_X-1, JET_DUMMY_Y-1,
JET_DUMMY_X+JET_DUMMY_WIDTH, JET_DUMMY_Y+JET_DUMMY_HEIGHT+1, lightgray);
 
grx_text("100%", JET_DUMMY_X-40, JET_DUMMY_Y, lightgray, black);
grx_text(" 0%", JET_DUMMY_X-40, JET_DUMMY_Y+JET_DUMMY_HEIGHT-8, lightgray, black);
 
grx_line(JET_DUMMY_X-1, JET_DUMMY_Y, JET_DUMMY_X-5, JET_DUMMY_Y, lightgray);
grx_line(JET_DUMMY_X-1, JET_DUMMY_Y+JET_DUMMY_HEIGHT, JET_DUMMY_X-5, JET_DUMMY_Y+JET_DUMMY_HEIGHT, lightgray);
 
/* jetdummy task */
soft_task_default_model(m4);
soft_task_def_period(m4, PERIOD_JETDUMMY);
soft_task_def_met(m4, WCET_JETDUMMY);
soft_task_def_usemath(m4);
p4 = task_create("jdmy", jetdummy_task, &m4, NULL);
if (p4 == -1) {
grx_close();
perror("Could not create task <jetdummy>");
sys_end();
}
task_activate(p4);
}
 
/advdemos/branches/advdemos/mpeg2/config.h
0,0 → 1,45
/* config.h, configuration defines */
 
/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
 
/*
* Disclaimer of Warranty
*
* These software programs are available to the user without any license fee or
* royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
* any and all warranties, whether express, implied, or statuary, including any
* implied warranties or merchantability or of fitness for a particular
* purpose. In no event shall the copyright-holder be liable for any
* incidental, punitive, or consequential damages of any kind whatsoever
* arising from the use of these programs.
*
* This disclaimer of warranty extends to the user of these programs and user's
* customers, employees, agents, transferees, successors, and assigns.
*
* The MPEG Software Simulation Group does not represent or warrant that the
* programs furnished hereunder are free of infringement of any third-party
* patents.
*
* Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
* are subject to royalty fees to patent holders. Many of these patents are
* general enough such that they are unavoidable regardless of implementation
* design.
*
*/
 
/* define NON_ANSI_COMPILER for compilers without function prototyping */
/* #define NON_ANSI_COMPILER */
 
#ifdef NON_ANSI_COMPILER
#define _ANSI_ARGS_(x) ()
#else
#define _ANSI_ARGS_(x) x
#endif
 
#define RB "rb"
#define WB "wb"
 
#ifndef O_BINARY
#define O_BINARY 0
 
#endif
/advdemos/branches/advdemos/mpeg2/getpic.c
0,0 → 1,1225
/* getpic.c, picture decoding */
 
/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
 
/*
* Disclaimer of Warranty
*
* These software programs are available to the user without any license fee or
* royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
* any and all warranties, whether express, implied, or statuary, including any
* implied warranties or merchantability or of fitness for a particular
* purpose. In no event shall the copyright-holder be liable for any
* incidental, punitive, or consequential damages of any kind whatsoever
* arising from the use of these programs.
*
* This disclaimer of warranty extends to the user of these programs and user's
* customers, employees, agents, transferees, successors, and assigns.
*
* The MPEG Software Simulation Group does not represent or warrant that the
* programs furnished hereunder are free of infringement of any third-party
* patents.
*
* Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
* are subject to royalty fees to patent holders. Many of these patents are
* general enough such that they are unavoidable regardless of implementation
* design.
*
*/
 
#include <stdio.h>
 
#include "config.h"
#include "global.h"
 
/* private prototypes*/
static void picture_data _ANSI_ARGS_((int framenum));
static void macroblock_modes _ANSI_ARGS_((int *pmacroblock_type, int *pstwtype,
int *pstwclass, int *pmotion_type, int *pmotion_vector_count, int *pmv_format, int *pdmv,
int *pmvscale, int *pdct_type));
static void Clear_Block _ANSI_ARGS_((int comp));
static void Sum_Block _ANSI_ARGS_((int comp));
static void Saturate _ANSI_ARGS_((short *bp));
static void Add_Block _ANSI_ARGS_((int comp, int bx, int by,
int dct_type, int addflag));
static void Update_Picture_Buffers _ANSI_ARGS_((void));
static void frame_reorder _ANSI_ARGS_((int bitstream_framenum,
int sequence_framenum));
static void Decode_SNR_Macroblock _ANSI_ARGS_((int *SNRMBA, int *SNRMBAinc,
int MBA, int MBAmax, int *dct_type));
 
static void motion_compensation _ANSI_ARGS_((int MBA, int macroblock_type,
int motion_type, int PMV[2][2][2], int motion_vertical_field_select[2][2],
int dmvector[2], int stwtype, int dct_type));
 
static void skipped_macroblock _ANSI_ARGS_((int dc_dct_pred[3],
int PMV[2][2][2], int *motion_type, int motion_vertical_field_select[2][2],
int *stwtype, int *macroblock_type));
 
static int slice _ANSI_ARGS_((int framenum, int MBAmax));
 
static int start_of_slice _ANSI_ARGS_ ((int MBAmax, int *MBA,
int *MBAinc, int dc_dct_pred[3], int PMV[2][2][2]));
 
static int decode_macroblock _ANSI_ARGS_((int *macroblock_type,
int *stwtype, int *stwclass, int *motion_type, int *dct_type,
int PMV[2][2][2], int dc_dct_pred[3],
int motion_vertical_field_select[2][2], int dmvector[2]));
 
 
/* decode one frame or field picture */
void Decode_Picture(bitstream_framenum, sequence_framenum)
int bitstream_framenum, sequence_framenum;
{
 
if (picture_structure==FRAME_PICTURE && Second_Field)
{
/* recover from illegal number of field pictures */
printf("odd number of field pictures\n");
Second_Field = 0;
}
 
/* IMPLEMENTATION: update picture buffer pointers */
Update_Picture_Buffers();
 
#ifdef VERIFY
Check_Headers(bitstream_framenum, sequence_framenum);
#endif /* VERIFY */
 
/* ISO/IEC 13818-4 section 2.4.5.4 "frame buffer intercept method" */
/* (section number based on November 1995 (Dallas) draft of the
conformance document) */
if(Ersatz_Flag)
Substitute_Frame_Buffer(bitstream_framenum, sequence_framenum);
 
/* form spatial scalable picture */
/* form spatial scalable picture */
/* ISO/IEC 13818-2 section 7.7: Spatial scalability */
if (base.pict_scal && !Second_Field)
{
Spatial_Prediction();
}
 
/* decode picture data ISO/IEC 13818-2 section 6.2.3.7 */
picture_data(bitstream_framenum);
 
/* write or display current or previously decoded reference frame */
/* ISO/IEC 13818-2 section 6.1.1.11: Frame reordering */
frame_reorder(bitstream_framenum, sequence_framenum);
 
if (picture_structure!=FRAME_PICTURE)
Second_Field = !Second_Field;
}
 
 
/* decode all macroblocks of the current picture */
/* stages described in ISO/IEC 13818-2 section 7 */
static void picture_data(framenum)
int framenum;
{
int MBAmax;
int ret;
 
/* number of macroblocks per picture */
MBAmax = mb_width*mb_height;
 
if (picture_structure!=FRAME_PICTURE)
MBAmax>>=1; /* field picture has half as mnay macroblocks as frame */
 
for(;;)
{
if((ret=slice(framenum, MBAmax))<0)
return;
}
 
}
 
 
 
/* decode all macroblocks of the current picture */
/* ISO/IEC 13818-2 section 6.3.16 */
static int slice(framenum, MBAmax)
int framenum, MBAmax;
{
int MBA;
int MBAinc, macroblock_type, motion_type, dct_type;
int dc_dct_pred[3];
int PMV[2][2][2], motion_vertical_field_select[2][2];
int dmvector[2];
int stwtype, stwclass;
int SNRMBA, SNRMBAinc;
int ret;
 
MBA = 0; /* macroblock address */
MBAinc = 0;
 
if((ret=start_of_slice(MBAmax, &MBA, &MBAinc, dc_dct_pred, PMV))!=1)
return(ret);
 
if (Two_Streams && enhan.scalable_mode==SC_SNR)
{
SNRMBA=0;
SNRMBAinc=0;
}
 
Fault_Flag=0;
 
for (;;)
{
 
/* this is how we properly exit out of picture */
if (MBA>=MBAmax)
return(-1); /* all macroblocks decoded */
 
#ifdef TRACE
if (Trace_Flag)
printf("frame %d, MB %d\n",framenum,MBA);
#endif /* TRACE */
 
#ifdef DISPLAY
if (!progressive_frame && picture_structure==FRAME_PICTURE
&& MBA==(MBAmax>>1) && framenum!=0 && Output_Type==T_X11
&& !Display_Progressive_Flag)
{
Display_Second_Field();
}
#endif
 
ld = &base;
 
if (MBAinc==0)
{
if (base.scalable_mode==SC_DP && base.priority_breakpoint==1)
ld = &enhan;
 
if (!Show_Bits(23) || Fault_Flag) /* next_start_code or fault */
{
resync: /* if Fault_Flag: resynchronize to next next_start_code */
Fault_Flag = 0;
return(0); /* trigger: go to next slice */
}
else /* neither next_start_code nor Fault_Flag */
{
if (base.scalable_mode==SC_DP && base.priority_breakpoint==1)
ld = &enhan;
 
/* decode macroblock address increment */
MBAinc = Get_macroblock_address_increment();
 
if (Fault_Flag) goto resync;
}
}
 
if (MBA>=MBAmax)
{
/* MBAinc points beyond picture dimensions */
if (!Quiet_Flag)
printf("Too many macroblocks in picture\n");
return(-1);
}
 
if (MBAinc==1) /* not skipped */
{
ret = decode_macroblock(&macroblock_type, &stwtype, &stwclass,
&motion_type, &dct_type, PMV, dc_dct_pred,
motion_vertical_field_select, dmvector);
 
if(ret==-1)
return(-1);
if(ret==0)
goto resync;
 
}
else /* MBAinc!=1: skipped macroblock */
{
/* ISO/IEC 13818-2 section 7.6.6 */
skipped_macroblock(dc_dct_pred, PMV, &motion_type,
motion_vertical_field_select, &stwtype, &macroblock_type);
}
 
/* SCALABILITY: SNR */
/* ISO/IEC 13818-2 section 7.8 */
/* NOTE: we currently ignore faults encountered in this routine */
if (Two_Streams && enhan.scalable_mode==SC_SNR)
Decode_SNR_Macroblock(&SNRMBA, &SNRMBAinc, MBA, MBAmax, &dct_type);
 
/* ISO/IEC 13818-2 section 7.6 */
motion_compensation(MBA, macroblock_type, motion_type, PMV,
motion_vertical_field_select, dmvector, stwtype, dct_type);
 
 
/* advance to next macroblock */
MBA++;
MBAinc--;
/* SCALABILITY: SNR */
if (Two_Streams && enhan.scalable_mode==SC_SNR)
{
SNRMBA++;
SNRMBAinc--;
}
 
if (MBA>=MBAmax)
return(-1); /* all macroblocks decoded */
}
}
 
/* ISO/IEC 13818-2 section 6.3.17.1: Macroblock modes */
static void macroblock_modes(pmacroblock_type,pstwtype,pstwclass,
pmotion_type,pmotion_vector_count,pmv_format,pdmv,pmvscale,pdct_type)
int *pmacroblock_type, *pstwtype, *pstwclass;
int *pmotion_type, *pmotion_vector_count, *pmv_format, *pdmv, *pmvscale;
int *pdct_type;
{
int macroblock_type;
int stwtype, stwcode, stwclass;
int motion_type = 0;