Subversion Repositories shark

Rev

Rev 1033 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
961 pj 1
/*
2
 * Project: S.Ha.R.K.
3
 *
4
 * Coordinators:
5
 *   Giorgio Buttazzo    <giorgio@sssup.it>
6
 *   Paolo Gai           <pj@gandalf.sssup.it>
7
 *
8
 * Authors     :
9
 *   Giacomo Guidi       <giacomo@gandalf.sssup.it>
10
 *   (see the web pages for full authors list)
11
 *
12
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
13
 *
14
 * http://www.sssup.it
15
 * http://retis.sssup.it
16
 * http://shark.sssup.it
17
 */
18
 
19
/*
20
 * Copyright (C) 2000,2002 Paolo Gai
21
 *
22
 * This program is free software; you can redistribute it and/or modify
23
 * it under the terms of the GNU General Public License as published by
24
 * the Free Software Foundation; either version 2 of the License, or
25
 * (at your option) any later version.
26
 *
27
 * This program is distributed in the hope that it will be useful,
28
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30
 * GNU General Public License for more details.
31
 *
32
 * You should have received a copy of the GNU General Public License
33
 * along with this program; if not, write to the Free Software
34
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
35
 *
36
 */
37
 
38
/* Interrupt Driver Module */
39
 
40
#include <intdrive/intdrive/intdrive.h>
1018 mauro 41
#include <intdrive/intdrive/inttask.h>
961 pj 42
#include <kernel/model.h>
43
#include <kernel/descr.h>
44
#include <kernel/var.h>
45
#include <kernel/func.h>
46
#include <tracer.h>
47
 
48
#include <ll/i386/64bit.h>
49
 
50
/*+ Status used in the level +*/
51
#define INTDRIVE_READY         MODULE_STATUS_BASE    /*+ - Ready status        +*/
52
#define INTDRIVE_WCET_VIOLATED MODULE_STATUS_BASE+2  /*+ when wcet is finished +*/
53
#define INTDRIVE_IDLE          MODULE_STATUS_BASE+3  /*+ to wait the replenish +*/
54
#define INTDRIVE_WAIT          MODULE_STATUS_BASE+4  /*+ to wait the activation */
55
 
56
//#define INTDRIVE_DEBUG
57
 
58
/*+ the level redefinition for the IntDrive +*/
59
typedef struct {
1021 mauro 60
        level_des l;     /*+ the standard level descriptor          +*/
961 pj 61
 
1021 mauro 62
        TIME replenish_period;
63
        TIME capacity;
64
        TIME q_theta;
961 pj 65
 
1021 mauro 66
        struct timespec act_time;
961 pj 67
 
1021 mauro 68
        int avail;
69
        int replenish_timer;
961 pj 70
 
1021 mauro 71
        //struct timespec replenish_expires;
72
        //int wcet_timer;
961 pj 73
 
1021 mauro 74
        int act_number;   /*+ the activation number                  +*/
961 pj 75
 
1021 mauro 76
        int flags;        /*+ the init flags...                      +*/
961 pj 77
 
1021 mauro 78
        bandwidth_t U;    /*+ the used bandwidth                     +*/
961 pj 79
 
80
} INTDRIVE_level_des;
81
 
82
PID INTDRIVE_task = NIL;
83
 
84
/* Replenish the capacity */
85
static void INTDRIVE_timer(void *arg)
86
{
1021 mauro 87
        INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(arg);
961 pj 88
 
1021 mauro 89
        lev->replenish_timer = NIL;
961 pj 90
 
1021 mauro 91
#ifdef INTDRIVE_DEBUG
92
        kern_printf("(INTD:TIMER)");
93
#endif
961 pj 94
 
1021 mauro 95
        if (INTDRIVE_task == NIL) return;
961 pj 96
 
1021 mauro 97
        lev->avail = lev->q_theta;
1033 tullio 98
 
99
#ifdef INTDRIVE_DEBUG
1021 mauro 100
        TRACER_LOGEVENT(FTrace_EVT_user_event_0, 0, lev->avail + INT_MAX);
1033 tullio 101
#endif
961 pj 102
 
1021 mauro 103
        switch (proc_table[INTDRIVE_task].status) {
104
                case INTDRIVE_IDLE:
105
                        if (lev->act_number) {
106
                                proc_table[INTDRIVE_task].status = INTDRIVE_READY;
107
                                event_need_reschedule();
108
                        } else {
109
                                proc_table[INTDRIVE_task].status = INTDRIVE_WAIT;
110
                        }
111
                        break;
112
        }
961 pj 113
}
114
 
115
/*static void INTDRIVE_wcet_timer(void *arg)
116
{
1021 mauro 117
        INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(arg);
961 pj 118
 
1021 mauro 119
        lev->wcet_timer = NIL;
961 pj 120
 
1021 mauro 121
        kern_raise(XWCET_VIOLATION,INTDRIVE_task);
961 pj 122
}*/
123
 
124
static PID INTDRIVE_public_scheduler(LEVEL l)
125
{
1021 mauro 126
        if (INTDRIVE_task == NIL) return NIL;
961 pj 127
 
1021 mauro 128
        if (proc_table[INTDRIVE_task].status == INTDRIVE_READY ||
129
            proc_table[INTDRIVE_task].status == EXE)
130
                return INTDRIVE_task;
131
        else
132
                return NIL;
961 pj 133
}
134
 
135
static int INTDRIVE_public_create(LEVEL l, PID p, TASK_MODEL *m)
136
{
1023 mauro 137
        INTERRUPT_TASK_MODEL *h;
961 pj 138
 
1023 mauro 139
        if (m->pclass != INTERRUPT_PCLASS) return -1;
140
        if (m->level != l) return -1;
141
        h = (INTERRUPT_TASK_MODEL *)m;
142
        if (!h->wcet) return -1;
961 pj 143
 
1021 mauro 144
        if (INTDRIVE_task != NIL) return -1;
961 pj 145
 
1021 mauro 146
        INTDRIVE_task = p;
961 pj 147
 
1021 mauro 148
        proc_table[INTDRIVE_task].wcet = h->wcet;
149
        proc_table[INTDRIVE_task].avail_time = h->wcet;
150
        proc_table[INTDRIVE_task].status = INTDRIVE_WAIT;
151
        proc_table[INTDRIVE_task].control &= ~CONTROL_CAP;
961 pj 152
 
1021 mauro 153
        return 0;
961 pj 154
}
155
 
156
static void INTDRIVE_public_dispatch(LEVEL l, PID p, int nostop)
157
{
1021 mauro 158
        INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
159
        //struct timespec time;
961 pj 160
 
1021 mauro 161
        kern_gettime(&(lev->act_time));
961 pj 162
 
1021 mauro 163
        /*TIMESPEC_ASSIGN(&time,&(lev->act_time));
164
        ADDUSEC2TIMESPEC(proc_table[INTDRIVE_task].wcet,&time);
961 pj 165
 
1021 mauro 166
        if (lev->flags == INTDRIVE_CHECK_WCET)
167
                lev->wcet_timer = kern_event_post(&time,INTDRIVE_wcet_timer,(void *)lev);*/  
961 pj 168
}
169
 
170
static void INTDRIVE_public_epilogue(LEVEL l, PID p)
171
{
1021 mauro 172
        struct timespec time;
961 pj 173
 
1021 mauro 174
        INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
961 pj 175
 
1021 mauro 176
        /*if (lev->wcet_timer != NIL)
177
                kern_event_delete(lev->wcet_timer);*/
961 pj 178
 
1021 mauro 179
        SUBTIMESPEC(&schedule_time, &(lev->act_time), &time);
180
        lev->avail -= TIMESPEC2USEC(&time);
1033 tullio 181
 
182
#ifdef INTDRIVE_DEBUG
1021 mauro 183
        TRACER_LOGEVENT(FTrace_EVT_user_event_0, 0, lev->avail + INT_MAX);
1033 tullio 184
#endif
1021 mauro 185
 
186
        if (proc_table[INTDRIVE_task].wcet < TIMESPEC2USEC(&time)) {
187
                kern_raise(XWCET_VIOLATION,INTDRIVE_task);    
188
        }
961 pj 189
}
190
 
191
static void INTDRIVE_public_activate(LEVEL l, PID p, struct timespec *t)
192
{
1021 mauro 193
        struct timespec acttime;
194
        TIME time, delta_capacity;
961 pj 195
 
1021 mauro 196
        INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
961 pj 197
 
1021 mauro 198
        if (proc_table[INTDRIVE_task].status == INTDRIVE_WAIT) {
199
                proc_table[INTDRIVE_task].status = INTDRIVE_READY;
200
                lev->act_number++;     
201
        } else {
202
                if (proc_table[INTDRIVE_task].status == INTDRIVE_IDLE ||
203
                    proc_table[INTDRIVE_task].status == INTDRIVE_READY ||
204
                    proc_table[INTDRIVE_task].status == EXE) {
205
#ifdef INTDRIVE_DEBUG
206
                        kern_printf("(INTD:WAIT_REC)");
207
#endif
208
                        lev->act_number++;
209
                }
210
        }
961 pj 211
 
1021 mauro 212
        if (lev->replenish_timer == NIL) {
213
                delta_capacity = lev->q_theta - lev->avail;
214
                mul32div32to32(delta_capacity, MAX_BANDWIDTH, lev->U, time);
215
                kern_gettime(&acttime);
216
                ADDUSEC2TIMESPEC(time,&acttime);
217
                lev->replenish_timer = kern_event_post(&acttime,INTDRIVE_timer,(void *)lev);
961 pj 218
 
1021 mauro 219
                /*kern_gettime(&(lev->replenish_expires));
220
                ADDUSEC2TIMESPEC(lev->replenish_period,&(lev->replenish_expires));
221
                lev->replenish_timer = kern_event_post(&(lev->replenish_expires),INTDRIVE_timer,(void *)lev);*/
222
        }
961 pj 223
}
224
 
225
static void INTDRIVE_public_unblock(LEVEL l, PID p)
226
{
1021 mauro 227
        /* Insert task in the correct position */
228
        proc_table[INTDRIVE_task].status = INTDRIVE_READY;
961 pj 229
}
230
 
231
static void INTDRIVE_public_block(LEVEL l, PID p)
232
{
233
 
234
}
235
 
236
static int INTDRIVE_public_message(LEVEL l, PID p, void *m)
237
{
1021 mauro 238
        INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
239
        struct timespec time, acttime;
240
        //int delta_time;
241
        TIME delta_capacity, delta_time;
961 pj 242
 
1021 mauro 243
        lev->act_number--;
961 pj 244
 
1021 mauro 245
        /*if (lev->wcet_timer != NIL)
246
        kern_event_delete(lev->wcet_timer);*/
961 pj 247
 
1021 mauro 248
        kern_gettime(&acttime);
249
        SUBTIMESPEC(&acttime, &(lev->act_time), &time);
250
        delta_time = TIMESPEC2USEC(&time);
251
        mul32div32to32(delta_time, (MAX_BANDWIDTH-lev->U), MAX_BANDWIDTH, delta_capacity);
252
        lev->avail -= delta_capacity;
1018 mauro 253
 
1021 mauro 254
        //lev->avail -= TIMESPEC2USEC(&time);
961 pj 255
 
1033 tullio 256
#ifdef INTDRIVE_DEBUG
1021 mauro 257
        TRACER_LOGEVENT(FTrace_EVT_user_event_0, 0, lev->avail + INT_MAX);
1033 tullio 258
#endif
961 pj 259
 
1021 mauro 260
#ifdef INTDRIVE_DEBUG
261
        kern_printf("(INTD:AV:%d)",(int)(lev->avail));
262
#endif
961 pj 263
 
1021 mauro 264
        if (lev->avail < 0) {
265
                proc_table[INTDRIVE_task].status = INTDRIVE_IDLE;
961 pj 266
 
1021 mauro 267
                if (lev->replenish_timer != NIL)
268
                        kern_event_delete(lev->replenish_timer);
961 pj 269
 
1021 mauro 270
                delta_capacity = lev->q_theta - lev->avail;
271
                mul32div32to32(delta_capacity, MAX_BANDWIDTH, lev->U, delta_time);
272
                kern_gettime(&acttime);
273
                ADDUSEC2TIMESPEC(delta_time,&acttime);
274
                lev->replenish_timer = kern_event_post(&acttime,INTDRIVE_timer,(void *)lev);
961 pj 275
 
1021 mauro 276
                /*temp = -lev->avail;
277
                mul32div32to32(temp,lev->replenish_period,lev->capacity,delta_time)
278
                ADDUSEC2TIMESPEC(delta_time,&(lev->replenish_expires));
279
                lev->replenish_timer = kern_event_post(&(lev->replenish_expires),INTDRIVE_timer,(void *)lev);*/
961 pj 280
 
1021 mauro 281
#ifdef INTDRIVE_DEBUG
282
                kern_printf("(INTD:IDLE:%d)",delta_time);
283
#endif
284
        } else {
285
                if (lev->act_number) {
286
                        proc_table[INTDRIVE_task].status = INTDRIVE_READY;
287
#ifdef INTDRIVE_DEBUG
288
                        kern_printf("(INTD:NEXT_ACT)");
289
#endif
290
                } else {
291
#ifdef INTDRIVE_DEBUG
292
                        kern_printf("(INTD:WAIT_ACT)");
293
#endif
294
                        proc_table[INTDRIVE_task].status = INTDRIVE_WAIT;
295
                }
296
        }
961 pj 297
 
1021 mauro 298
        TRACER_LOGEVENT(FTrace_EVT_task_end_cycle, (unsigned short int)proc_table[INTDRIVE_task].context,(unsigned int)l);
961 pj 299
 
1021 mauro 300
        return 0;
961 pj 301
}
302
 
303
static void INTDRIVE_public_end(LEVEL l, PID p)
304
{
1021 mauro 305
        INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
961 pj 306
 
1021 mauro 307
        if (lev->replenish_timer != NIL)
308
                kern_event_delete(lev->replenish_timer);
961 pj 309
 
1021 mauro 310
        /*if (lev->wcet_timer != NIL)
311
                kern_event_delete(lev->wcet_timer);*/
961 pj 312
 
1021 mauro 313
        proc_table[INTDRIVE_task].status = INTDRIVE_IDLE;
961 pj 314
}
315
 
316
/* Registration functions */
317
 
1046 tullio 318
PID intr_server = NIL;
319
extern TASK Interrupt_Server(void *arg);
320
extern TASK Interrupt_Server_Prot(void *arg);
321
 
322
static void intdrive_create(void *l)
323
{
324
        INTERRUPT_TASK_MODEL ht;
325
        int level;
326
        int wcet = 10000;   // TODO: should be a parameter
327
 
328
        level = (LEVEL)l;
329
 
330
        interrupt_task_default_model(ht);
331
        interrupt_task_def_wcet(ht, wcet);
332
        interrupt_task_def_system(ht);
333
        interrupt_task_def_nokill(ht);
334
 
335
        if (level > 0)
336
                intr_server = task_create("Interrupt Server (Protected)",Interrupt_Server_Prot,&ht,NULL);
337
        else
338
                intr_server = task_create("Interrupt Server",Interrupt_Server,&ht,NULL);
339
 
340
        if (intr_server == NIL)
341
    printk("\nPanic!!! Can't create IntDrive task...\n");
342
}
343
 
961 pj 344
/*+ Registration function: +*/
1004 mauro 345
LEVEL INTDRIVE_register_level(TIME capacity, TIME q_theta, int U, int flags)
961 pj 346
{
1021 mauro 347
        LEVEL l;            /* the level that we register */
348
        INTDRIVE_level_des *lev;
961 pj 349
 
1021 mauro 350
        printk("INTDRIVE_register_level\n");
961 pj 351
 
1021 mauro 352
        /* request an entry in the level_table */
353
        l = level_alloc_descriptor(sizeof(INTDRIVE_level_des));
961 pj 354
 
1021 mauro 355
        lev = (INTDRIVE_level_des *)level_table[l];
961 pj 356
 
1021 mauro 357
        lev->l.public_scheduler = INTDRIVE_public_scheduler;
358
        lev->l.public_guarantee = NULL;
359
        lev->l.public_create    = INTDRIVE_public_create;
360
        lev->l.public_end       = INTDRIVE_public_end;
361
        lev->l.public_dispatch  = INTDRIVE_public_dispatch;
362
        lev->l.public_epilogue  = INTDRIVE_public_epilogue;
363
        lev->l.public_activate  = INTDRIVE_public_activate;
364
        lev->l.public_unblock   = INTDRIVE_public_unblock;
365
        lev->l.public_block     = INTDRIVE_public_block;
366
        lev->l.public_message   = INTDRIVE_public_message;
961 pj 367
 
1021 mauro 368
        NULL_TIMESPEC(&(lev->act_time));
961 pj 369
 
1021 mauro 370
        lev->capacity = capacity;
371
        lev->replenish_timer = NIL;
372
        lev->flags = flags;
373
        lev->act_number = 0;
374
        lev->avail = 0;
375
        lev->q_theta = q_theta;
376
        lev->U = U;
377
        //mul32div32to32(MAX_BANDWIDTH,U,10000,lev->U);
378
#ifdef INTDRIVE_DEBUG
379
        printk("INTDRIVE Init: %d %d %d\n", lev->capacity, lev->q_theta, lev->U);
380
#endif
1018 mauro 381
 
1046 tullio 382
        sys_atrunlevel(intdrive_create, (void *) l, RUNLEVEL_INIT);
961 pj 383
 
1021 mauro 384
        return l;
961 pj 385
}
386
 
387
bandwidth_t INTDRIVE_usedbandwidth(LEVEL l)
388
{
1021 mauro 389
        INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
961 pj 390
 
1021 mauro 391
        return lev->U;
961 pj 392
}
393
 
394
TIME INTDRIVE_set_q_theta(LEVEL l, TIME new_q_theta)
395
{
1021 mauro 396
        INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
961 pj 397
 
1021 mauro 398
        lev->q_theta = new_q_theta;
399
        if (lev->q_theta < 0) lev->q_theta = 0;
400
        if (lev->q_theta > lev->capacity) lev->q_theta = lev->capacity;
401
 
402
        return lev->q_theta;
961 pj 403
}