Subversion Repositories shark

Rev

Rev 776 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
511 giacomo 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 <modules/intdrive.h>
41
#include <kernel/model.h>
42
#include <kernel/descr.h>
43
#include <kernel/var.h>
44
#include <kernel/func.h>
903 mauro 45
#include <tracer.h>
511 giacomo 46
 
47
#include <ll/i386/64bit.h>
48
 
49
/*+ Status used in the level +*/
50
#define INTDRIVE_READY         MODULE_STATUS_BASE    /*+ - Ready status        +*/
51
#define INTDRIVE_WCET_VIOLATED MODULE_STATUS_BASE+2  /*+ when wcet is finished +*/
52
#define INTDRIVE_IDLE          MODULE_STATUS_BASE+3  /*+ to wait the replenish +*/
53
#define INTDRIVE_WAIT          MODULE_STATUS_BASE+4  /*+ to wait the activation */
54
 
55
//#define INTDRIVE_DEBUG
56
 
57
/*+ the level redefinition for the IntDrive +*/
58
typedef struct {
59
  level_des l;     /*+ the standard level descriptor          +*/
60
 
61
  TIME replenish_period;
62
  TIME capacity;
903 mauro 63
  TIME q_theta;
511 giacomo 64
 
522 mauro 65
  struct timespec act_time;
66
 
511 giacomo 67
  int avail;
68
  int replenish_timer;
69
 
903 mauro 70
  //struct timespec replenish_expires;
71
  //int wcet_timer;
72
 
511 giacomo 73
  int act_number;   /*+ the activation number                  +*/
74
 
75
  int flags;        /*+ the init flags...                      +*/
76
 
77
  bandwidth_t U;    /*+ the used bandwidth                     +*/
78
 
79
} INTDRIVE_level_des;
80
 
81
PID INTDRIVE_task = NIL;
82
 
83
/* Replenish the capacity */
84
static void INTDRIVE_timer(void *arg)
85
{
903 mauro 86
  //TRACER_LOGEVENT(FTrace_EVT_user_event_3, 0, 0);
511 giacomo 87
 
88
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(arg);
89
 
90
  lev->replenish_timer = NIL;
91
 
92
  #ifdef INTDRIVE_DEBUG
93
    kern_printf("(INTD:TIMER)");
94
  #endif
95
 
96
  if (INTDRIVE_task == NIL) return;
97
 
903 mauro 98
  lev->avail = lev->q_theta;
99
 
100
  TRACER_LOGEVENT(FTrace_EVT_user_event_0, 0, lev->avail + INT_MAX);
511 giacomo 101
 
102
  switch (proc_table[INTDRIVE_task].status) {
103
 
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
  }
903 mauro 113
  //TRACER_LOGEVENT(FTrace_EVT_user_event_4, 1, 0);
511 giacomo 114
}
115
 
903 mauro 116
/*static void INTDRIVE_wcet_timer(void *arg)
511 giacomo 117
{
118
 
119
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(arg);
120
 
121
  lev->wcet_timer = NIL;
122
 
123
  kern_raise(XWCET_VIOLATION,INTDRIVE_task);
124
 
903 mauro 125
}*/
511 giacomo 126
 
127
static PID INTDRIVE_public_scheduler(LEVEL l)
128
{
754 giacomo 129
 
130
  if (INTDRIVE_task == NIL) return NIL;
511 giacomo 131
 
132
  if (proc_table[INTDRIVE_task].status == INTDRIVE_READY ||
133
        proc_table[INTDRIVE_task].status == EXE)
134
    return INTDRIVE_task;
135
  else
136
    return NIL;
137
 
138
}
139
 
140
static int INTDRIVE_public_create(LEVEL l, PID p, TASK_MODEL *m)
141
{
142
 
143
  HARD_TASK_MODEL *h;
144
 
145
  if (m->pclass != HARD_PCLASS) return -1;
146
  if (m->level != 0 && m->level != l) return -1;
147
  h = (HARD_TASK_MODEL *)m;
148
  if (!h->wcet && h->periodicity != INTDRIVE) return -1;
149
 
150
  if (INTDRIVE_task != NIL) return -1;
151
 
152
  INTDRIVE_task = p;
153
 
154
  proc_table[INTDRIVE_task].wcet = h->wcet;
755 giacomo 155
  proc_table[INTDRIVE_task].avail_time = h->wcet;
511 giacomo 156
  proc_table[INTDRIVE_task].status = INTDRIVE_WAIT;
157
  proc_table[INTDRIVE_task].control &= ~CONTROL_CAP;
158
 
159
  return 0;
160
 
161
}
162
 
163
static void INTDRIVE_public_dispatch(LEVEL l, PID p, int nostop)
164
{
165
 
166
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
903 mauro 167
  //struct timespec time;
522 mauro 168
 
169
  kern_gettime(&(lev->act_time));
903 mauro 170
 
171
  /*TIMESPEC_ASSIGN(&time,&(lev->act_time));
511 giacomo 172
  ADDUSEC2TIMESPEC(proc_table[INTDRIVE_task].wcet,&time);
173
 
699 giacomo 174
  if (lev->flags == INTDRIVE_CHECK_WCET)
903 mauro 175
    lev->wcet_timer = kern_event_post(&time,INTDRIVE_wcet_timer,(void *)lev);*/  
511 giacomo 176
}
177
 
178
static void INTDRIVE_public_epilogue(LEVEL l, PID p)
179
{
180
 
699 giacomo 181
  struct timespec time;
511 giacomo 182
 
183
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
184
 
903 mauro 185
  /*if (lev->wcet_timer != NIL)
186
    kern_event_delete(lev->wcet_timer);*/
187
 
699 giacomo 188
  SUBTIMESPEC(&schedule_time, &(lev->act_time), &time);
528 giacomo 189
  lev->avail -= TIMESPEC2USEC(&time);
903 mauro 190
  TRACER_LOGEVENT(FTrace_EVT_user_event_0, 0, lev->avail + INT_MAX);
191
 
192
  if (proc_table[INTDRIVE_task].wcet < TIMESPEC2USEC(&time)) {
193
    kern_raise(XWCET_VIOLATION,INTDRIVE_task);    
194
  }                                                                                                                      
511 giacomo 195
}
196
 
657 anton 197
static void INTDRIVE_public_activate(LEVEL l, PID p, struct timespec *t)
511 giacomo 198
{
903 mauro 199
  struct timespec acttime;
200
  TIME time, delta_capacity;
511 giacomo 201
 
202
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
203
 
204
  if (proc_table[INTDRIVE_task].status == INTDRIVE_WAIT) {
543 giacomo 205
 
511 giacomo 206
    proc_table[INTDRIVE_task].status = INTDRIVE_READY;
543 giacomo 207
 
208
    lev->act_number++; 
209
 
511 giacomo 210
  } else {
211
 
212
    if (proc_table[INTDRIVE_task].status == INTDRIVE_IDLE ||
543 giacomo 213
        proc_table[INTDRIVE_task].status == INTDRIVE_READY ||
214
        proc_table[INTDRIVE_task].status == EXE) {
511 giacomo 215
 
216
        #ifdef INTDRIVE_DEBUG
217
          kern_printf("(INTD:WAIT_REC)");
218
        #endif
219
 
220
        lev->act_number++;
221
 
222
    }
223
 
224
  }
225
 
226
  if (lev->replenish_timer == NIL) {
524 giacomo 227
 
903 mauro 228
    delta_capacity = lev->q_theta - lev->avail;
229
    mul32div32to32(delta_capacity, MAX_BANDWIDTH, lev->U, time);
230
    kern_gettime(&acttime);
231
    ADDUSEC2TIMESPEC(time,&acttime);
232
    lev->replenish_timer = kern_event_post(&acttime,INTDRIVE_timer,(void *)lev);
233
 
234
    /*kern_gettime(&(lev->replenish_expires));
528 giacomo 235
    ADDUSEC2TIMESPEC(lev->replenish_period,&(lev->replenish_expires));
903 mauro 236
    lev->replenish_timer = kern_event_post(&(lev->replenish_expires),INTDRIVE_timer,(void *)lev);*/
511 giacomo 237
  }
238
 
239
}
240
 
241
static void INTDRIVE_public_unblock(LEVEL l, PID p)
242
{
243
  /* Insert task in the correct position */
244
  proc_table[INTDRIVE_task].status = INTDRIVE_READY;
245
 
246
}
247
 
248
static void INTDRIVE_public_block(LEVEL l, PID p)
249
{
250
 
251
}
252
 
253
static int INTDRIVE_public_message(LEVEL l, PID p, void *m)
254
{
255
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
698 giacomo 256
  struct timespec time, acttime;
903 mauro 257
  //int delta_time;
258
  TIME delta_capacity, delta_time;
259
 
543 giacomo 260
  lev->act_number--;
261
 
903 mauro 262
  /*if (lev->wcet_timer != NIL)
263
    kern_event_delete(lev->wcet_timer);*/
511 giacomo 264
 
698 giacomo 265
  kern_gettime(&acttime);
266
  SUBTIMESPEC(&acttime, &(lev->act_time), &time);
903 mauro 267
  delta_time = TIMESPEC2USEC(&time);
268
  mul32div32to32(delta_time, (1-lev->U), MAX_BANDWIDTH, delta_capacity);
269
  lev->avail -= delta_capacity;
270
 
271
  //lev->avail -= TIMESPEC2USEC(&time);
272
 
273
  TRACER_LOGEVENT(FTrace_EVT_user_event_0, 0, lev->avail + INT_MAX);
511 giacomo 274
 
275
  #ifdef INTDRIVE_DEBUG
276
    kern_printf("(INTD:AV:%d)",(int)(lev->avail));
277
  #endif
278
 
279
  if (lev->avail < 0) {
280
    proc_table[INTDRIVE_task].status = INTDRIVE_IDLE;
903 mauro 281
 
511 giacomo 282
    if (lev->replenish_timer != NIL)
283
      kern_event_delete(lev->replenish_timer);
284
 
903 mauro 285
    delta_capacity = lev->q_theta - lev->avail;
286
    mul32div32to32(delta_capacity, MAX_BANDWIDTH, lev->U, delta_time);
287
    kern_gettime(&acttime);
288
    ADDUSEC2TIMESPEC(delta_time,&acttime);
289
    lev->replenish_timer = kern_event_post(&acttime,INTDRIVE_timer,(void *)lev);
290
 
291
    /*temp = -lev->avail;
292
    mul32div32to32(temp,lev->replenish_period,lev->capacity,delta_time)
293
    ADDUSEC2TIMESPEC(delta_time,&(lev->replenish_expires));
294
    lev->replenish_timer = kern_event_post(&(lev->replenish_expires),INTDRIVE_timer,(void *)lev);*/
511 giacomo 295
 
296
    #ifdef INTDRIVE_DEBUG
528 giacomo 297
      kern_printf("(INTD:IDLE:%d)",delta_time);
511 giacomo 298
    #endif
299
 
300
  } else {
301
    if (lev->act_number) {
302
      proc_table[INTDRIVE_task].status = INTDRIVE_READY;
303
 
304
      #ifdef INTDRIVE_DEBUG
305
        kern_printf("(INTD:NEXT_ACT)");
306
      #endif
307
 
308
    } else {
309
 
310
      #ifdef INTDRIVE_DEBUG
311
        kern_printf("(INTD:WAIT_ACT)");
312
      #endif
313
 
314
      proc_table[INTDRIVE_task].status = INTDRIVE_WAIT;
315
 
316
    }
317
  }
318
 
319
  return 0;
522 mauro 320
 
511 giacomo 321
}
322
 
323
static void INTDRIVE_public_end(LEVEL l, PID p)
324
{
325
 
326
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
327
 
328
  if (lev->replenish_timer != NIL)
329
    kern_event_delete(lev->replenish_timer);
330
 
903 mauro 331
  /*if (lev->wcet_timer != NIL)
332
    kern_event_delete(lev->wcet_timer);*/
524 giacomo 333
 
511 giacomo 334
  proc_table[INTDRIVE_task].status = INTDRIVE_IDLE;
335
 
336
}
337
 
338
/* Registration functions */
339
 
340
/*+ Registration function: +*/
341
LEVEL INTDRIVE_register_level(TIME capacity, TIME replenish_period, int flags)
342
{
343
  LEVEL l;            /* the level that we register */
344
  INTDRIVE_level_des *lev;
345
 
346
  printk("INTDRIVE_register_level\n");
347
 
348
  /* request an entry in the level_table */
349
  l = level_alloc_descriptor(sizeof(INTDRIVE_level_des));
350
 
351
  lev = (INTDRIVE_level_des *)level_table[l];
352
 
353
  lev->l.public_scheduler = INTDRIVE_public_scheduler;
354
  lev->l.public_guarantee = NULL;
355
  lev->l.public_create    = INTDRIVE_public_create;
356
  lev->l.public_end       = INTDRIVE_public_end;
357
  lev->l.public_dispatch  = INTDRIVE_public_dispatch;
358
  lev->l.public_epilogue  = INTDRIVE_public_epilogue;
359
  lev->l.public_activate  = INTDRIVE_public_activate;
360
  lev->l.public_unblock   = INTDRIVE_public_unblock;
361
  lev->l.public_block     = INTDRIVE_public_block;
362
  lev->l.public_message   = INTDRIVE_public_message;
363
 
522 mauro 364
  NULL_TIMESPEC(&(lev->act_time));
365
 
511 giacomo 366
  lev->capacity = capacity;
903 mauro 367
  //lev->replenish_period = replenish_period;
511 giacomo 368
  lev->replenish_timer = NIL;
903 mauro 369
  //lev->wcet_timer = NIL;
511 giacomo 370
  lev->flags = flags;
371
  lev->act_number = 0;
903 mauro 372
  lev->avail = 0;
373
  lev->q_theta = capacity;
374
  mul32div32to32(MAX_BANDWIDTH,lev->capacity,replenish_period,lev->U);
511 giacomo 375
 
376
  return l;
377
}
378
 
379
bandwidth_t INTDRIVE_usedbandwidth(LEVEL l)
380
{
381
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
382
 
383
  return lev->U;
384
}
385
 
903 mauro 386
TIME INTDRIVE_set_q_theta(LEVEL l, TIME new_q_theta)
387
{
388
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
389
 
390
  lev->q_theta = new_q_theta;
391
  if (lev->q_theta < 0) lev->q_theta = 0;
392
  if (lev->q_theta > lev->capacity) lev->q_theta = lev->capacity;
393
 
394
  return lev->q_theta;
395
}