Subversion Repositories shark

Rev

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

Rev Author Line No. Line
671 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
 *      Mauro Marinoni
11
 *      Anton Cervin
12
 *
13
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
14
 *
15
 * http://www.sssup.it
16
 * http://retis.sssup.it
17
 * http://shark.sssup.it
18
 */
19
 
20
/*
21
 * This program is free software; you can redistribute it and/or modify
22
 * it under the terms of the GNU General Public License as published by
23
 * the Free Software Foundation; either version 2 of the License, or
24
 * (at your option) any later version.
25
 *
26
 * This program is distributed in the hope that it will be useful,
27
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29
 * GNU General Public License for more details.
30
 *
31
 * You should have received a copy of the GNU General Public License
32
 * along with this program; if not, write to the Free Software
33
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
34
 *
35
 */
36
 
37
#include <kernel/model.h>
38
#include <kernel/descr.h>
39
#include <kernel/var.h>
40
#include <kernel/func.h>
41
 
42
#include <stdlib.h>
43
 
44
#include <modules/elastic.h>
45
 
46
#include <tracer.h>
47
 
673 giacomo 48
#define ELASTIC_EMPTY_SLOT    0
49
#define ELASTIC_PRESENT       1
671 giacomo 50
 
683 giacomo 51
#define ELASTIC_IDLE          APER_STATUS_BASE
52
 
691 anton 53
//#define ELASTIC_DEBUG
676 giacomo 54
 
671 giacomo 55
typedef struct {
56
 
57
  struct timespec dline;
58
 
691 anton 59
  TIME Tmin;
671 giacomo 60
  TIME Tmax;
691 anton 61
  TIME C;
62
  int  E;
63
  int  beta;
671 giacomo 64
 
691 anton 65
  TIME T;
673 giacomo 66
 
671 giacomo 67
  int  flags;
68
 
69
} ELASTIC_task_descr;
70
 
71
typedef struct {
72
  level_des l;     /*+ the standard level descriptor          +*/
73
 
691 anton 74
  bandwidth_t U;   /*+ the bandwidth reserved for elastic tasks  +*/
671 giacomo 75
 
683 giacomo 76
  ELASTIC_task_descr *elist;//[MAX_PROC];
671 giacomo 77
 
78
  LEVEL scheduling_level;
79
 
80
  LEVEL current_level;
81
 
82
  int flags;
83
 
84
} ELASTIC_level_des;
85
 
676 giacomo 86
static int ELASTIC_recompute(ELASTIC_level_des *lev) {
673 giacomo 87
 
676 giacomo 88
  PID i;
89
 
90
  for (i=0; i<MAX_PROC; i++) {
691 anton 91
    if (lev->elist[i].flags & ELASTIC_PRESENT) {
92
      lev->elist[i].T = lev->elist[i].Tmax;
93
    }
676 giacomo 94
  }
95
 
673 giacomo 96
  return 0;
97
 
98
}
99
 
691 anton 100
static int ELASTIC_check_guarantee(ELASTIC_level_des *lev) {
673 giacomo 101
 
691 anton 102
  PID i;
103
 
104
  for (i=0; i<MAX_PROC; i++) {
105
    if (lev->elist[i].flags & ELASTIC_PRESENT) {
106
 
107
      lev->elist[i].T = lev->elist[i].Tmax;
108
    }
109
  }
110
 
111
 
673 giacomo 112
  return 0;
113
 
114
}
115
 
671 giacomo 116
static void ELASTIC_activation(ELASTIC_level_des *lev,
117
                               PID p,
118
                               struct timespec *acttime)
119
{
120
  JOB_TASK_MODEL job;
674 giacomo 121
 
122
  /* Job deadline */
123
  TIMESPEC_ASSIGN(&(lev->elist[p].dline),acttime);
691 anton 124
  ADDUSEC2TIMESPEC(lev->elist[p].T,&(lev->elist[p].dline));
674 giacomo 125
 
691 anton 126
  proc_table[p].avail_time = lev->elist[p].C;
127
  proc_table[p].wcet = lev->elist[p].C;
683 giacomo 128
 
674 giacomo 129
  /* Job insertion */
130
  job_task_default_model(job, lev->elist[p].dline);
671 giacomo 131
  level_table[ lev->scheduling_level ]->
132
    private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
133
 
674 giacomo 134
}
671 giacomo 135
 
674 giacomo 136
static void ELASTIC_timer_act(void *arg) {
137
 
138
  PID p = (PID)(arg);
139
  ELASTIC_level_des *lev;
140
  struct timespec acttime;
683 giacomo 141
 
142
  #ifdef ELASTIC_DEBUG
143
    printk("(ELASTIC:Timer:%d)",p);
144
  #endif
145
 
674 giacomo 146
  kern_gettime(&acttime);
147
 
148
  lev = (ELASTIC_level_des *)level_table[proc_table[p].task_level];
149
 
150
  ELASTIC_activation(lev, p, &acttime);                                                                                                                            
683 giacomo 151
  event_need_reschedule();
152
 
153
  /* Next activation */
154
  kern_event_post(&(lev->elist[p].dline), ELASTIC_timer_act, (void *)(p));
155
 
671 giacomo 156
}
157
 
158
/* The on-line guarantee is enabled only if the appropriate flag is set... */
159
static int ELASTIC_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
160
{
161
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
162
 
691 anton 163
  if (*freebandwidth >= lev->U) {
164
    *freebandwidth -= lev->U;
165
    return 1;
166
  } else {
167
    return 0;
168
  }
671 giacomo 169
}
170
 
691 anton 171
 
671 giacomo 172
static int ELASTIC_public_create(LEVEL l, PID p, TASK_MODEL *m)
173
{
174
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
691 anton 175
  ELASTIC_TASK_MODEL *elastic = (ELASTIC_TASK_MODEL *)m;
176
  ext_bandwidth_t Umin = 0;
671 giacomo 177
 
178
  if (m->pclass != ELASTIC_PCLASS) return -1;
179
  if (m->level != 0 && m->level != l) return -1;
180
 
691 anton 181
  if (elastic->C == 0) return -1;
673 giacomo 182
  if (elastic->Tmin > elastic->Tmax) return -1;
183
  if (elastic->Tmax == 0) return -1;
184
 
185
  lev->elist[p].flags |= ELASTIC_PRESENT;
186
 
187
  NULL_TIMESPEC(&(lev->elist[p].dline));
188
  lev->elist[p].Tmin = elastic->Tmin;
189
  lev->elist[p].Tmax = elastic->Tmax;
691 anton 190
  lev->elist[p].C = elastic->C;
191
  lev->elist[p].E = elastic->E;
673 giacomo 192
  lev->elist[p].beta = elastic->beta;
193
 
691 anton 194
  lev->elist[p].T = elastic->Tmin;
673 giacomo 195
 
691 anton 196
  /* check if new task can be admitted:              */
197
  /* compute minimum consumed bandwidth of all tasks */
198
  Umin = 0;
199
  for (i=0; i<MAX_PROC; i++) {
200
    if (lev->elist[i].flags & ELASTIC_PRESENT) {
201
      if (lev->elist[i].E == 0) {
202
        /* The task is not elastic. Use current period T */
203
        Umin += (MAX_BANDWIDTH / lev->elist[i].T) * lev->elist[i].C;
204
      } else {
205
        /* The task is elastic. Use maximum period Tmax */
206
        Umin += (MAX_BANDWIDTH / lev->elist[i].Tmax) * lev->elist[i].C;
207
      }
208
    }
209
  }
210
  if (Umin > lev->U) {
211
    /* failed to add task */
212
    lev->elist[p].flags = ELASTIC_EMPTY_SLOT;
213
    return -1;
214
  }
215
 
676 giacomo 216
  ELASTIC_recompute(lev);
673 giacomo 217
 
691 anton 218
  proc_table[p].avail_time = elastic->C;
219
  proc_table[p].wcet       = elastic->C;
674 giacomo 220
  proc_table[p].control    |= CONTROL_CAP;
673 giacomo 221
 
671 giacomo 222
  return 0; /* OK, also if the task cannot be guaranteed... */
223
 
224
}
225
 
226
static void ELASTIC_public_detach(LEVEL l, PID p)
227
{
228
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
229
 
230
}
231
 
232
static int ELASTIC_public_eligible(LEVEL l, PID p)
233
{
234
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
235
 
236
  return 0;
237
 
238
}
239
 
240
static void ELASTIC_public_dispatch(LEVEL l, PID p, int nostop)
241
{
242
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
674 giacomo 243
 
683 giacomo 244
  #ifdef ELASTIC_DEBUG
245
    printk("(ELASTIC:Dsp:%d)",p);
246
  #endif
247
 
671 giacomo 248
  level_table[ lev->scheduling_level ]->
249
    private_dispatch(lev->scheduling_level,p,nostop);
674 giacomo 250
 
671 giacomo 251
}
252
 
253
static void ELASTIC_public_epilogue(LEVEL l, PID p)
254
{
255
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
256
 
683 giacomo 257
  #ifdef ELASTIC_DEBUG
258
    printk("(ELASTIC:Epi:%d)",p);
259
  #endif
260
 
674 giacomo 261
  /* check if the wcet is finished... */
262
  if (proc_table[p].avail_time <= 0) {
263
 
264
    TRACER_LOGEVENT(FTrace_EVT_task_wcet_violation,(unsigned short int)proc_table[p].context,0);
265
    kern_raise(XWCET_VIOLATION,p);
266
 
267
  }
691 anton 268
 
674 giacomo 269
  level_table[ lev->scheduling_level ]->
270
      private_epilogue(lev->scheduling_level,p);
271
 
671 giacomo 272
}
273
 
274
static void ELASTIC_public_activate(LEVEL l, PID p, struct timespec *t)
275
{
276
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
277
 
674 giacomo 278
  #ifdef ELASTIC_DEBUG
279
    printk("(ELASTIC:Act:%d)", p);
280
  #endif
281
 
282
  /* check if we are not in the SLEEP state */
283
  if (proc_table[p].status != SLEEP) {
284
 
285
    return;
286
 
287
  }
288
 
289
  ELASTIC_activation(lev,p,t);
290
 
291
  /* Next activation */
292
  kern_event_post(&(lev->elist[p].dline), ELASTIC_timer_act, (void *)(p));
293
 
671 giacomo 294
}
295
 
296
static void ELASTIC_public_unblock(LEVEL l, PID p)
297
{
298
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
299
  struct timespec acttime;
300
 
301
  kern_gettime(&acttime);
302
 
303
  ELASTIC_activation(lev,p,&acttime);
304
 
305
}
306
 
307
static void ELASTIC_public_block(LEVEL l, PID p)
308
{
309
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
310
 
311
  level_table[ lev->scheduling_level ]->
312
    private_extract(lev->scheduling_level,p);
313
 
314
}
315
 
316
static int ELASTIC_public_message(LEVEL l, PID p, void *m)
317
{
318
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
676 giacomo 319
  struct timespec acttime;
671 giacomo 320
 
321
  switch((long)(m)) {
322
 
323
    case (long)(NULL):
324
 
683 giacomo 325
      #ifdef ELASTIC_DEBUG
326
        printk("(ELASTIC:EndCyc:%d)",p);
327
      #endif
328
 
676 giacomo 329
      level_table[ lev->scheduling_level ]->
330
        private_extract(lev->scheduling_level,p);
331
 
683 giacomo 332
      proc_table[p].status = ELASTIC_IDLE;
676 giacomo 333
 
671 giacomo 334
      jet_update_endcycle(); /* Update the Jet data... */
335
      TRACER_LOGEVENT(FTrace_EVT_task_end_cycle,(unsigned short int)proc_table[p].context,(unsigned int)l);
336
 
337
      break;
338
 
339
    case 1:
340
 
683 giacomo 341
      #ifdef ELASTIC_DEBUG
342
        printk("(ELASTIC:Disable:%d)",p);
343
      #endif
344
 
676 giacomo 345
      level_table[ lev->scheduling_level ]->
346
        private_extract(lev->scheduling_level,p);
347
 
348
      proc_table[p].status = SLEEP;
349
 
671 giacomo 350
      TRACER_LOGEVENT(FTrace_EVT_task_disable,(unsigned short int)proc_table[p].context,(unsigned int)l);
351
 
352
      break;
353
 
354
  }
355
 
356
  return 0;
357
 
358
}
359
 
360
static void ELASTIC_public_end(LEVEL l, PID p)
361
{
362
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
363
 
364
  level_table[ lev->scheduling_level ]->
365
    private_extract(lev->scheduling_level,p);
366
 
367
}
368
 
369
/*+ Registration function +*/
691 anton 370
LEVEL ELASTIC_register_level(int flags, LEVEL master, bandwidth_t U)
671 giacomo 371
{
372
  LEVEL l;            /* the level that we register */
373
  ELASTIC_level_des *lev;  /* for readableness only */
374
  PID i;
375
 
376
  printk("ELASTIC_register_level\n");
377
 
378
  /* request an entry in the level_table */
379
  l = level_alloc_descriptor(sizeof(ELASTIC_level_des));
380
 
381
  lev = (ELASTIC_level_des *)level_table[l];
382
 
383
  /* fill the standard descriptor */
384
  if (flags & ELASTIC_ENABLE_GUARANTEE)
385
    lev->l.public_guarantee = ELASTIC_public_guarantee;
386
  else
387
    lev->l.public_guarantee = NULL;
388
  lev->l.public_create    = ELASTIC_public_create;
389
  lev->l.public_detach    = ELASTIC_public_detach;
390
  lev->l.public_end       = ELASTIC_public_end;
391
  lev->l.public_eligible  = ELASTIC_public_eligible;
392
  lev->l.public_dispatch  = ELASTIC_public_dispatch;
393
  lev->l.public_epilogue  = ELASTIC_public_epilogue;
394
  lev->l.public_activate  = ELASTIC_public_activate;
395
  lev->l.public_unblock   = ELASTIC_public_unblock;
396
  lev->l.public_block     = ELASTIC_public_block;
397
  lev->l.public_message   = ELASTIC_public_message;
398
 
683 giacomo 399
  lev->elist = kern_alloc(MAX_PROC * sizeof(ELASTIC_task_descr));
671 giacomo 400
 
676 giacomo 401
  /* fill the ELASTIC task descriptor part */
671 giacomo 402
  for (i=0; i<MAX_PROC; i++) {
403
     NULL_TIMESPEC(&(lev->elist[i].dline));
404
     lev->elist[i].Tmin = 0;
405
     lev->elist[i].Tmax = 0;
691 anton 406
     lev->elist[i].T = 0;
407
     lev->elist[i].C = 0;
408
     lev->elist[i].E = 0;
671 giacomo 409
     lev->elist[i].beta = 0;
410
     lev->elist[i].flags = ELASTIC_EMPTY_SLOT;
411
  }
412
 
691 anton 413
  lev->U = U;
671 giacomo 414
 
415
  lev->scheduling_level = master;
416
 
417
  lev->current_level = l;
418
 
419
  lev->flags = flags;
420
 
421
  return l;
422
}
423