Subversion Repositories shark

Rev

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