Subversion Repositories shark

Rev

Rev 522 | Go to most recent revision | Details | 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
 
48
/*+ Status used in the level +*/
49
#define INTDRIVE_READY         MODULE_STATUS_BASE    /*+ - Ready status        +*/
50
#define INTDRIVE_WCET_VIOLATED MODULE_STATUS_BASE+2  /*+ when wcet is finished +*/
51
#define INTDRIVE_IDLE          MODULE_STATUS_BASE+3  /*+ to wait the replenish +*/
52
#define INTDRIVE_WAIT          MODULE_STATUS_BASE+4  /*+ to wait the activation */
53
 
54
//#define INTDRIVE_DEBUG
55
 
56
/*+ the level redefinition for the IntDrive +*/
57
typedef struct {
58
  level_des l;     /*+ the standard level descriptor          +*/
59
 
60
  TIME replenish_period;
61
  TIME next_time;
62
  TIME capacity;
63
 
64
  int avail;
65
 
66
  int replenish_timer;
67
  int wcet_timer;
68
 
69
  int act_number;   /*+ the activation number                  +*/
70
 
71
  int flags;        /*+ the init flags...                      +*/
72
 
73
  bandwidth_t U;    /*+ the used bandwidth                     +*/
74
 
75
} INTDRIVE_level_des;
76
 
77
PID INTDRIVE_task = NIL;
78
 
79
/* Replenish the capacity */
80
static void INTDRIVE_timer(void *arg)
81
{
82
 
83
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(arg);
84
 
85
  lev->replenish_timer = NIL;
86
 
87
  #ifdef INTDRIVE_DEBUG
88
    kern_printf("(INTD:TIMER)");
89
  #endif
90
 
91
  if (INTDRIVE_task == NIL) return;
92
 
93
  lev->avail = lev->capacity;
94
 
95
  switch (proc_table[INTDRIVE_task].status) {
96
 
97
    case INTDRIVE_IDLE:
98
      if (lev->act_number) {
99
        proc_table[INTDRIVE_task].status = INTDRIVE_READY;
100
        event_need_reschedule();
101
      } else {
102
        proc_table[INTDRIVE_task].status = INTDRIVE_WAIT;
103
      }
104
      break;
105
 
106
  }
107
 
108
}
109
 
110
 
111
static void INTDRIVE_wcet_timer(void *arg)
112
{
113
 
114
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(arg);
115
 
116
  lev->wcet_timer = NIL;
117
 
118
  kern_raise(XWCET_VIOLATION,INTDRIVE_task);
119
 
120
}
121
 
122
static PID INTDRIVE_public_scheduler(LEVEL l)
123
{
124
 
125
  if (proc_table[INTDRIVE_task].status == INTDRIVE_READY ||
126
        proc_table[INTDRIVE_task].status == EXE)
127
    return INTDRIVE_task;
128
  else
129
    return NIL;
130
 
131
}
132
 
133
static int INTDRIVE_public_create(LEVEL l, PID p, TASK_MODEL *m)
134
{
135
 
136
  HARD_TASK_MODEL *h;
137
 
138
  if (m->pclass != HARD_PCLASS) return -1;
139
  if (m->level != 0 && m->level != l) return -1;
140
  h = (HARD_TASK_MODEL *)m;
141
  if (!h->wcet && h->periodicity != INTDRIVE) return -1;
142
 
143
  if (INTDRIVE_task != NIL) return -1;
144
 
145
  INTDRIVE_task = p;
146
 
147
  proc_table[INTDRIVE_task].wcet = h->wcet;
148
  proc_table[INTDRIVE_task].status = INTDRIVE_WAIT;
149
  proc_table[INTDRIVE_task].control &= ~CONTROL_CAP;
150
 
151
  return 0;
152
 
153
}
154
 
155
static void INTDRIVE_public_dispatch(LEVEL l, PID p, int nostop)
156
{
157
 
158
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
159
  struct timespec time;
160
 
161
  kern_gettime(&time);
162
  ADDUSEC2TIMESPEC(proc_table[INTDRIVE_task].wcet,&time);
163
 
164
  lev->wcet_timer = kern_event_post(&time,INTDRIVE_wcet_timer,(void *)lev);  
165
 
166
}
167
 
168
static void INTDRIVE_public_epilogue(LEVEL l, PID p)
169
{
170
 
171
  struct timespec time;
172
  int temp;
173
 
174
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
175
 
176
  if (lev->wcet_timer != NIL)
177
    kern_event_delete(lev->wcet_timer);
178
 
179
  SUBTIMESPEC(&schedule_time, &cap_lasttime, &time);
180
  temp = TIMESPEC2USEC(&time);
181
 
182
  lev->avail -= temp;
183
 
184
}
185
 
186
static void INTDRIVE_public_activate(LEVEL l, PID p)
187
{
188
 
189
  struct timespec time;
190
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
191
 
192
  if (proc_table[INTDRIVE_task].status == INTDRIVE_WAIT) {
193
    proc_table[INTDRIVE_task].status = INTDRIVE_READY;
194
  } else {
195
 
196
    if (proc_table[INTDRIVE_task].status == INTDRIVE_IDLE ||
197
        proc_table[INTDRIVE_task].status == INTDRIVE_READY) {
198
 
199
        #ifdef INTDRIVE_DEBUG
200
          kern_printf("(INTD:WAIT_REC)");
201
        #endif
202
 
203
        lev->act_number++;
204
 
205
    }
206
 
207
  }
208
 
209
  if (lev->replenish_timer == NIL) {
210
    kern_gettime(&time);
211
    ADDUSEC2TIMESPEC(lev->next_time,&time);
212
 
213
    lev->replenish_timer = kern_event_post(&time,INTDRIVE_timer,(void *)lev);
214
  }
215
 
216
}
217
 
218
static void INTDRIVE_public_unblock(LEVEL l, PID p)
219
{
220
  /* Insert task in the correct position */
221
  proc_table[INTDRIVE_task].status = INTDRIVE_READY;
222
 
223
}
224
 
225
static void INTDRIVE_public_block(LEVEL l, PID p)
226
{
227
 
228
}
229
 
230
static int INTDRIVE_public_message(LEVEL l, PID p, void *m)
231
{
232
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
233
  struct timespec time;
234
  int temp;
235
 
236
  if (lev->wcet_timer != NIL)
237
    kern_event_delete(lev->wcet_timer);
238
 
239
  SUBTIMESPEC(&schedule_time, &cap_lasttime, &time);
240
  temp = TIMESPEC2USEC(&time);
241
 
242
  lev->avail -= temp;
243
  #ifdef INTDRIVE_DEBUG
244
    kern_printf("(INTD:AV:%d)",(int)(lev->avail));
245
  #endif
246
 
247
  if (lev->avail < 0) {
248
    proc_table[INTDRIVE_task].status = INTDRIVE_IDLE;
249
    temp = lev->capacity - lev->avail;
250
    mul32div32to32(temp,lev->replenish_period,lev->capacity,lev->next_time);
251
 
252
    if (lev->replenish_timer != NIL)
253
      kern_event_delete(lev->replenish_timer);
254
 
255
    kern_gettime(&time);
256
    ADDUSEC2TIMESPEC(lev->next_time,&time);                                                                              
257
    lev->replenish_timer = kern_event_post(&time,INTDRIVE_timer,(void *)lev);
258
 
259
    #ifdef INTDRIVE_DEBUG
260
      kern_printf("(INTD:IDLE)");
261
    #endif
262
 
263
  } else {
264
    if (lev->act_number) {
265
      lev->act_number--;
266
      proc_table[INTDRIVE_task].status = INTDRIVE_READY;
267
 
268
      #ifdef INTDRIVE_DEBUG
269
        kern_printf("(INTD:NEXT_ACT)");
270
      #endif
271
 
272
    } else {
273
 
274
      #ifdef INTDRIVE_DEBUG
275
        kern_printf("(INTD:WAIT_ACT)");
276
      #endif
277
 
278
      proc_table[INTDRIVE_task].status = INTDRIVE_WAIT;
279
 
280
    }
281
  }
282
 
283
  jet_update_endcycle(); /* Update the Jet data... */
284
 
285
  return 0;
286
}
287
 
288
static void INTDRIVE_public_end(LEVEL l, PID p)
289
{
290
 
291
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
292
 
293
  if (lev->replenish_timer != NIL)
294
    kern_event_delete(lev->replenish_timer);
295
 
296
  proc_table[INTDRIVE_task].status = INTDRIVE_IDLE;
297
 
298
}
299
 
300
/* Registration functions */
301
 
302
/*+ Registration function: +*/
303
LEVEL INTDRIVE_register_level(TIME capacity, TIME replenish_period, int flags)
304
{
305
  LEVEL l;            /* the level that we register */
306
  INTDRIVE_level_des *lev;
307
 
308
  printk("INTDRIVE_register_level\n");
309
 
310
  /* request an entry in the level_table */
311
  l = level_alloc_descriptor(sizeof(INTDRIVE_level_des));
312
 
313
  lev = (INTDRIVE_level_des *)level_table[l];
314
 
315
  lev->l.public_scheduler = INTDRIVE_public_scheduler;
316
  lev->l.public_guarantee = NULL;
317
  lev->l.public_create    = INTDRIVE_public_create;
318
  lev->l.public_end       = INTDRIVE_public_end;
319
  lev->l.public_dispatch  = INTDRIVE_public_dispatch;
320
  lev->l.public_epilogue  = INTDRIVE_public_epilogue;
321
  lev->l.public_activate  = INTDRIVE_public_activate;
322
  lev->l.public_unblock   = INTDRIVE_public_unblock;
323
  lev->l.public_block     = INTDRIVE_public_block;
324
  lev->l.public_message   = INTDRIVE_public_message;
325
 
326
  lev->capacity = capacity;
327
  lev->replenish_period = replenish_period;
328
  lev->next_time = replenish_period;
329
  lev->replenish_timer = NIL;
330
  lev->wcet_timer = NIL;
331
  lev->flags = flags;
332
  lev->act_number = 0;
333
  mul32div32to32(MAX_BANDWIDTH,lev->capacity,lev->replenish_period,lev->U);
334
 
335
  return l;
336
}
337
 
338
bandwidth_t INTDRIVE_usedbandwidth(LEVEL l)
339
{
340
  INTDRIVE_level_des *lev = (INTDRIVE_level_des *)(level_table[l]);
341
 
342
  return lev->U;
343
}
344