Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 510 → Rev 511

/shark/trunk/kernel/modules/intdrive.c
0,0 → 1,344
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Giacomo Guidi <giacomo@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,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
*
*/
 
/* Interrupt Driver Module */
 
#include <modules/intdrive.h>
#include <kernel/model.h>
#include <kernel/descr.h>
#include <kernel/var.h>
#include <kernel/func.h>
 
#include <ll/i386/64bit.h>
 
/*+ Status used in the level +*/
#define INTDRIVE_READY MODULE_STATUS_BASE /*+ - Ready status +*/
#define INTDRIVE_WCET_VIOLATED MODULE_STATUS_BASE+2 /*+ when wcet is finished +*/
#define INTDRIVE_IDLE MODULE_STATUS_BASE+3 /*+ to wait the replenish +*/
#define INTDRIVE_WAIT MODULE_STATUS_BASE+4 /*+ to wait the activation */
 
//#define INTDRIVE_DEBUG
 
/*+ the level redefinition for the IntDrive +*/
typedef struct {
level_des l; /*+ the standard level descriptor +*/
 
TIME replenish_period;
TIME next_time;
TIME capacity;
 
int avail;
 
int replenish_timer;
int wcet_timer;
 
int act_number; /*+ the activation number +*/
 
int flags; /*+ the init flags... +*/
 
bandwidth_t U; /*+ the used bandwidth +*/
 
} INTDRIVE_level_des;
 
PID INTDRIVE_task = NIL;
 
/* Replenish the capacity */
static void INTDRIVE_timer(void *arg)
{
 
INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(arg);
 
lev->replenish_timer = NIL;
 
#ifdef INTDRIVE_DEBUG
kern_printf("(INTD:TIMER)");
#endif
 
if (INTDRIVE_task == NIL) return;
 
lev->avail = lev->capacity;
 
switch (proc_table[INTDRIVE_task].status) {
 
case INTDRIVE_IDLE:
if (lev->act_number) {
proc_table[INTDRIVE_task].status = INTDRIVE_READY;
event_need_reschedule();
} else {
proc_table[INTDRIVE_task].status = INTDRIVE_WAIT;
}
break;
 
}
 
}
 
 
static void INTDRIVE_wcet_timer(void *arg)
{
 
INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(arg);
 
lev->wcet_timer = NIL;
kern_raise(XWCET_VIOLATION,INTDRIVE_task);
 
}
 
static PID INTDRIVE_public_scheduler(LEVEL l)
{
if (proc_table[INTDRIVE_task].status == INTDRIVE_READY ||
proc_table[INTDRIVE_task].status == EXE)
return INTDRIVE_task;
else
return NIL;
 
}
 
static int INTDRIVE_public_create(LEVEL l, PID p, TASK_MODEL *m)
{
 
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->periodicity != INTDRIVE) return -1;
 
if (INTDRIVE_task != NIL) return -1;
 
INTDRIVE_task = p;
 
proc_table[INTDRIVE_task].wcet = h->wcet;
proc_table[INTDRIVE_task].status = INTDRIVE_WAIT;
proc_table[INTDRIVE_task].control &= ~CONTROL_CAP;
return 0;
 
}
 
static void INTDRIVE_public_dispatch(LEVEL l, PID p, int nostop)
{
 
INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
struct timespec time;
kern_gettime(&time);
ADDUSEC2TIMESPEC(proc_table[INTDRIVE_task].wcet,&time);
lev->wcet_timer = kern_event_post(&time,INTDRIVE_wcet_timer,(void *)lev);
 
}
 
static void INTDRIVE_public_epilogue(LEVEL l, PID p)
{
 
struct timespec time;
int temp;
 
INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
 
if (lev->wcet_timer != NIL)
kern_event_delete(lev->wcet_timer);
 
SUBTIMESPEC(&schedule_time, &cap_lasttime, &time);
temp = TIMESPEC2USEC(&time);
lev->avail -= temp;
 
}
 
static void INTDRIVE_public_activate(LEVEL l, PID p)
{
 
struct timespec time;
INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
 
if (proc_table[INTDRIVE_task].status == INTDRIVE_WAIT) {
proc_table[INTDRIVE_task].status = INTDRIVE_READY;
} else {
 
if (proc_table[INTDRIVE_task].status == INTDRIVE_IDLE ||
proc_table[INTDRIVE_task].status == INTDRIVE_READY) {
 
#ifdef INTDRIVE_DEBUG
kern_printf("(INTD:WAIT_REC)");
#endif
lev->act_number++;
 
}
 
}
 
if (lev->replenish_timer == NIL) {
kern_gettime(&time);
ADDUSEC2TIMESPEC(lev->next_time,&time);
 
lev->replenish_timer = kern_event_post(&time,INTDRIVE_timer,(void *)lev);
}
}
 
static void INTDRIVE_public_unblock(LEVEL l, PID p)
{
/* Insert task in the correct position */
proc_table[INTDRIVE_task].status = INTDRIVE_READY;
}
 
static void INTDRIVE_public_block(LEVEL l, PID p)
{
 
}
 
static int INTDRIVE_public_message(LEVEL l, PID p, void *m)
{
INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
struct timespec time;
int temp;
 
if (lev->wcet_timer != NIL)
kern_event_delete(lev->wcet_timer);
 
SUBTIMESPEC(&schedule_time, &cap_lasttime, &time);
temp = TIMESPEC2USEC(&time);
lev->avail -= temp;
#ifdef INTDRIVE_DEBUG
kern_printf("(INTD:AV:%d)",(int)(lev->avail));
#endif
 
if (lev->avail < 0) {
proc_table[INTDRIVE_task].status = INTDRIVE_IDLE;
temp = lev->capacity - lev->avail;
mul32div32to32(temp,lev->replenish_period,lev->capacity,lev->next_time);
 
if (lev->replenish_timer != NIL)
kern_event_delete(lev->replenish_timer);
 
kern_gettime(&time);
ADDUSEC2TIMESPEC(lev->next_time,&time);
lev->replenish_timer = kern_event_post(&time,INTDRIVE_timer,(void *)lev);
 
#ifdef INTDRIVE_DEBUG
kern_printf("(INTD:IDLE)");
#endif
 
} else {
if (lev->act_number) {
lev->act_number--;
proc_table[INTDRIVE_task].status = INTDRIVE_READY;
 
#ifdef INTDRIVE_DEBUG
kern_printf("(INTD:NEXT_ACT)");
#endif
 
} else {
 
#ifdef INTDRIVE_DEBUG
kern_printf("(INTD:WAIT_ACT)");
#endif
 
proc_table[INTDRIVE_task].status = INTDRIVE_WAIT;
 
}
}
 
jet_update_endcycle(); /* Update the Jet data... */
return 0;
}
 
static void INTDRIVE_public_end(LEVEL l, PID p)
{
 
INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
 
if (lev->replenish_timer != NIL)
kern_event_delete(lev->replenish_timer);
 
proc_table[INTDRIVE_task].status = INTDRIVE_IDLE;
 
}
 
/* Registration functions */
 
/*+ Registration function: +*/
LEVEL INTDRIVE_register_level(TIME capacity, TIME replenish_period, int flags)
{
LEVEL l; /* the level that we register */
INTDRIVE_level_des *lev;
 
printk("INTDRIVE_register_level\n");
 
/* request an entry in the level_table */
l = level_alloc_descriptor(sizeof(INTDRIVE_level_des));
 
lev = (INTDRIVE_level_des *)level_table[l];
 
lev->l.public_scheduler = INTDRIVE_public_scheduler;
lev->l.public_guarantee = NULL;
lev->l.public_create = INTDRIVE_public_create;
lev->l.public_end = INTDRIVE_public_end;
lev->l.public_dispatch = INTDRIVE_public_dispatch;
lev->l.public_epilogue = INTDRIVE_public_epilogue;
lev->l.public_activate = INTDRIVE_public_activate;
lev->l.public_unblock = INTDRIVE_public_unblock;
lev->l.public_block = INTDRIVE_public_block;
lev->l.public_message = INTDRIVE_public_message;
 
lev->capacity = capacity;
lev->replenish_period = replenish_period;
lev->next_time = replenish_period;
lev->replenish_timer = NIL;
lev->wcet_timer = NIL;
lev->flags = flags;
lev->act_number = 0;
mul32div32to32(MAX_BANDWIDTH,lev->capacity,lev->replenish_period,lev->U);
 
return l;
}
 
bandwidth_t INTDRIVE_usedbandwidth(LEVEL l)
{
INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
 
return lev->U;
}
 
/shark/trunk/kernel/modules/makefile
15,13 → 15,14
# Object files
#
 
SCHED_OBJ = rr.o \
rr2.o \
edf.o \
rm.o \
posix.o \
dummy.o \
rrsoft.o
SCHED_OBJ = rr.o \
rr2.o \
edf.o \
rm.o \
posix.o \
dummy.o \
rrsoft.o \
intdrive.o
 
APER_OBJ = tbs.o \
cbs.o \