Subversion Repositories shark

Rev

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