Subversion Repositories shark

Rev

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