Subversion Repositories shark

Rev

Rev 697 | 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
 
697 anton 57
  /* Task parameters (set/changed by the user) */
58
 
59
  TIME Tmin;   /* The nominal (minimum) period */
60
  TIME Tmax;   /* The maximum tolerable period */
61
  TIME C;      /* The declared worst-case execution time */
62
  int  E;      /* The elasticity coefficient */
63
  int  beta;   /* PERIOD_SCALING or WCET_SCALING */
64
 
65
  /* Task variables (changed by the module) */
66
 
67
  struct timespec dline;  /* The current absolute deadline */
671 giacomo 68
 
700 anton 69
  ext_bandwidth_t Umax;       /* The maximum utilization, Umax = C/Tmin  */
70
  ext_bandwidth_t Umin;       /* The minimum utilization, Umin = C/Tmax  */
671 giacomo 71
 
700 anton 72
  ext_bandwidth_t U;          /* The current utilization       */
697 anton 73
  TIME T;                 /* The current period, T = C/U   */
673 giacomo 74
 
671 giacomo 75
  int  flags;
76
 
77
} ELASTIC_task_descr;
78
 
79
typedef struct {
80
  level_des l;     /*+ the standard level descriptor          +*/
81
 
700 anton 82
  ext_bandwidth_t U;   /*+ the bandwidth reserved for elastic tasks  +*/
671 giacomo 83
 
697 anton 84
  ELASTIC_task_descr elist[MAX_PROC];
671 giacomo 85
 
86
  LEVEL scheduling_level;
87
 
88
  LEVEL current_level;
89
 
90
  int flags;
91
 
92
} ELASTIC_level_des;
93
 
673 giacomo 94
 
697 anton 95
/* Checks feasability and computes new utilizations for the task set */
96
 
97
static int ELASTIC_compress(ELASTIC_level_des *lev) {
98
 
676 giacomo 99
  PID i;
697 anton 100
  ELASTIC_task_descr *t;
101
  int ok;
102
 
103
  ext_bandwidth_t Umin;  // minimum utilization
104
  ext_bandwidth_t Umax;  // nominal (maximum) utilization of compressable tasks
676 giacomo 105
 
697 anton 106
  ext_bandwidth_t Uf;    // amount of non-compressable utilization
107
  int Ev;                // sum of elasticity among compressable tasks
108
 
109
  Umin = 0;
110
  Umax = 0;
111
 
676 giacomo 112
  for (i=0; i<MAX_PROC; i++) {
697 anton 113
    t = &lev->elist[i];
114
    if (t->flags & ELASTIC_PRESENT) {
115
      if (t->E == 0) {
116
        Umin += t->U;
700 anton 117
        Umax += t->U;
697 anton 118
      } else {
119
        Umin += t->Umin;
700 anton 120
        Umax += t->Umax;
697 anton 121
        t->U = t->Umax;   // reset previous saturations
700 anton 122
        t->T = ((long long)t->C * (long long)MAX_BANDWIDTH) / t->U;
697 anton 123
      }
691 anton 124
    }
676 giacomo 125
  }
697 anton 126
 
700 anton 127
  if (Umin > lev->U) return -1;  // NOT FEASIBLE
676 giacomo 128
 
700 anton 129
  if (Umax <= lev->U) return 0;  // FEASIBLE WITH MAXIMUM UTILIZATIONS
130
 
697 anton 131
  do {
132
    Uf = 0;
133
    Ev = 0;
134
    Umax = 0;
673 giacomo 135
 
697 anton 136
    for (i=0; i<MAX_PROC; i++) {
137
      t = &lev->elist[i];
138
      if (t->flags & ELASTIC_PRESENT) {
139
        if (t->E == 0 || t->U == t->Umin) {
140
          Uf += t->U;
141
        } else {
142
          Ev += t->E;
143
          Umax += t->Umax;
144
        }
145
      }
146
    }
147
 
148
    ok = 1;
149
 
150
    for (i=0; i<MAX_PROC; i++) {
151
      t = &lev->elist[i];
152
      if (t->flags & ELASTIC_PRESENT) {
153
        if (t->E > 0 && t->U > t->Umin) {
154
          t->U = t->Umax - (Umax - lev->U + Uf) * t->E / Ev;
155
          if (t->U < t->Umin) {
156
            t->U = t->Umin;
157
            ok = 0;
158
          }
159
          t->T = ((long long)t->C * (long long)MAX_BANDWIDTH) / t->U;
160
        }
161
      }
162
    }
673 giacomo 163
 
697 anton 164
  } while (ok == 0);
673 giacomo 165
 
697 anton 166
  cprintf("New periods: ");
691 anton 167
  for (i=0; i<MAX_PROC; i++) {
697 anton 168
    t = &lev->elist[i];
169
    if (t->flags & ELASTIC_PRESENT) {
170
      cprintf("%s:%d ", proc_table[i].name, t->T);
691 anton 171
    }
172
  }
697 anton 173
  cprintf("\n");
691 anton 174
 
697 anton 175
  return 0; // FEASIBLE
691 anton 176
 
673 giacomo 177
}
178
 
697 anton 179
 
671 giacomo 180
static void ELASTIC_activation(ELASTIC_level_des *lev,
181
                               PID p,
182
                               struct timespec *acttime)
183
{
184
  JOB_TASK_MODEL job;
674 giacomo 185
 
186
  /* Job deadline */
187
  TIMESPEC_ASSIGN(&(lev->elist[p].dline),acttime);
691 anton 188
  ADDUSEC2TIMESPEC(lev->elist[p].T,&(lev->elist[p].dline));
674 giacomo 189
 
691 anton 190
  proc_table[p].avail_time = lev->elist[p].C;
191
  proc_table[p].wcet = lev->elist[p].C;
683 giacomo 192
 
674 giacomo 193
  /* Job insertion */
194
  job_task_default_model(job, lev->elist[p].dline);
671 giacomo 195
  level_table[ lev->scheduling_level ]->
196
    private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
197
 
674 giacomo 198
}
671 giacomo 199
 
674 giacomo 200
static void ELASTIC_timer_act(void *arg) {
697 anton 201
 
674 giacomo 202
  PID p = (PID)(arg);
203
  ELASTIC_level_des *lev;
204
  struct timespec acttime;
683 giacomo 205
 
206
  #ifdef ELASTIC_DEBUG
207
    printk("(ELASTIC:Timer:%d)",p);
208
  #endif
697 anton 209
 
674 giacomo 210
  kern_gettime(&acttime);
697 anton 211
 
674 giacomo 212
  lev = (ELASTIC_level_des *)level_table[proc_table[p].task_level];
697 anton 213
 
214
  ELASTIC_activation(lev, p, &acttime);
215
 
683 giacomo 216
  event_need_reschedule();
217
 
218
  /* Next activation */
219
  kern_event_post(&(lev->elist[p].dline), ELASTIC_timer_act, (void *)(p));
220
 
671 giacomo 221
}
222
 
223
/* The on-line guarantee is enabled only if the appropriate flag is set... */
224
static int ELASTIC_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
225
{
226
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
227
 
700 anton 228
  return 1;
229
 
691 anton 230
  if (*freebandwidth >= lev->U) {
700 anton 231
    *freebandwidth -= (unsigned int)lev->U;
691 anton 232
    return 1;
233
  } else {
234
    return 0;
235
  }
671 giacomo 236
}
237
 
691 anton 238
 
671 giacomo 239
static int ELASTIC_public_create(LEVEL l, PID p, TASK_MODEL *m)
240
{
241
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
691 anton 242
  ELASTIC_TASK_MODEL *elastic = (ELASTIC_TASK_MODEL *)m;
671 giacomo 243
 
244
  if (m->pclass != ELASTIC_PCLASS) return -1;
245
  if (m->level != 0 && m->level != l) return -1;
246
 
691 anton 247
  if (elastic->C == 0) return -1;
673 giacomo 248
  if (elastic->Tmin > elastic->Tmax) return -1;
249
  if (elastic->Tmax == 0) return -1;
250
 
251
  lev->elist[p].flags |= ELASTIC_PRESENT;
252
 
253
  NULL_TIMESPEC(&(lev->elist[p].dline));
254
  lev->elist[p].Tmin = elastic->Tmin;
255
  lev->elist[p].Tmax = elastic->Tmax;
691 anton 256
  lev->elist[p].C = elastic->C;
257
  lev->elist[p].E = elastic->E;
673 giacomo 258
  lev->elist[p].beta = elastic->beta;
259
 
697 anton 260
  lev->elist[p].Umax = ((long long)MAX_BANDWIDTH * (long long)elastic->C)
261
                        / elastic->Tmin;
262
  lev->elist[p].Umin = ((long long)MAX_BANDWIDTH * (long long)elastic->C)
263
                        / elastic->Tmax;
673 giacomo 264
 
697 anton 265
  lev->elist[p].U = lev->elist[p].Umax;
266
  lev->elist[p].T = lev->elist[p].Tmin;
267
 
268
  if (ELASTIC_compress(lev) == -1) {
691 anton 269
    lev->elist[p].flags = ELASTIC_EMPTY_SLOT;
270
    return -1;
271
  }
272
 
273
  proc_table[p].avail_time = elastic->C;
274
  proc_table[p].wcet       = elastic->C;
674 giacomo 275
  proc_table[p].control    |= CONTROL_CAP;
673 giacomo 276
 
697 anton 277
  return 0;
671 giacomo 278
}
279
 
697 anton 280
 
671 giacomo 281
static void ELASTIC_public_detach(LEVEL l, PID p)
282
{
283
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
284
 
285
}
286
 
287
static int ELASTIC_public_eligible(LEVEL l, PID p)
288
{
289
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
290
 
291
  return 0;
292
 
293
}
294
 
295
static void ELASTIC_public_dispatch(LEVEL l, PID p, int nostop)
296
{
297
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
674 giacomo 298
 
683 giacomo 299
  #ifdef ELASTIC_DEBUG
300
    printk("(ELASTIC:Dsp:%d)",p);
301
  #endif
302
 
671 giacomo 303
  level_table[ lev->scheduling_level ]->
304
    private_dispatch(lev->scheduling_level,p,nostop);
674 giacomo 305
 
671 giacomo 306
}
307
 
308
static void ELASTIC_public_epilogue(LEVEL l, PID p)
309
{
310
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
311
 
683 giacomo 312
  #ifdef ELASTIC_DEBUG
313
    printk("(ELASTIC:Epi:%d)",p);
314
  #endif
315
 
674 giacomo 316
  /* check if the wcet is finished... */
317
  if (proc_table[p].avail_time <= 0) {
318
 
319
    TRACER_LOGEVENT(FTrace_EVT_task_wcet_violation,(unsigned short int)proc_table[p].context,0);
320
    kern_raise(XWCET_VIOLATION,p);
321
 
322
  }
691 anton 323
 
674 giacomo 324
  level_table[ lev->scheduling_level ]->
325
      private_epilogue(lev->scheduling_level,p);
326
 
671 giacomo 327
}
328
 
329
static void ELASTIC_public_activate(LEVEL l, PID p, struct timespec *t)
330
{
331
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
332
 
674 giacomo 333
  #ifdef ELASTIC_DEBUG
334
    printk("(ELASTIC:Act:%d)", p);
335
  #endif
336
 
337
  /* check if we are not in the SLEEP state */
338
  if (proc_table[p].status != SLEEP) {
339
 
340
    return;
341
 
342
  }
343
 
344
  ELASTIC_activation(lev,p,t);
345
 
346
  /* Next activation */
347
  kern_event_post(&(lev->elist[p].dline), ELASTIC_timer_act, (void *)(p));
348
 
671 giacomo 349
}
350
 
351
static void ELASTIC_public_unblock(LEVEL l, PID p)
352
{
353
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
354
  struct timespec acttime;
355
 
356
  kern_gettime(&acttime);
357
 
358
  ELASTIC_activation(lev,p,&acttime);
359
 
360
}
361
 
362
static void ELASTIC_public_block(LEVEL l, PID p)
363
{
364
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
365
 
366
  level_table[ lev->scheduling_level ]->
367
    private_extract(lev->scheduling_level,p);
368
 
369
}
370
 
371
static int ELASTIC_public_message(LEVEL l, PID p, void *m)
372
{
373
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
676 giacomo 374
  struct timespec acttime;
671 giacomo 375
 
376
  switch((long)(m)) {
377
 
378
    case (long)(NULL):
379
 
683 giacomo 380
      #ifdef ELASTIC_DEBUG
381
        printk("(ELASTIC:EndCyc:%d)",p);
382
      #endif
383
 
676 giacomo 384
      level_table[ lev->scheduling_level ]->
385
        private_extract(lev->scheduling_level,p);
386
 
683 giacomo 387
      proc_table[p].status = ELASTIC_IDLE;
676 giacomo 388
 
671 giacomo 389
      jet_update_endcycle(); /* Update the Jet data... */
390
      TRACER_LOGEVENT(FTrace_EVT_task_end_cycle,(unsigned short int)proc_table[p].context,(unsigned int)l);
391
 
392
      break;
393
 
394
    case 1:
395
 
683 giacomo 396
      #ifdef ELASTIC_DEBUG
397
        printk("(ELASTIC:Disable:%d)",p);
398
      #endif
399
 
676 giacomo 400
      level_table[ lev->scheduling_level ]->
401
        private_extract(lev->scheduling_level,p);
402
 
403
      proc_table[p].status = SLEEP;
404
 
671 giacomo 405
      TRACER_LOGEVENT(FTrace_EVT_task_disable,(unsigned short int)proc_table[p].context,(unsigned int)l);
406
 
407
      break;
408
 
409
  }
410
 
411
  return 0;
412
 
413
}
414
 
415
static void ELASTIC_public_end(LEVEL l, PID p)
416
{
417
  ELASTIC_level_des *lev = (ELASTIC_level_des *)(level_table[l]);
418
 
419
  level_table[ lev->scheduling_level ]->
420
    private_extract(lev->scheduling_level,p);
421
 
422
}
423
 
424
/*+ Registration function +*/
700 anton 425
LEVEL ELASTIC_register_level(int flags, LEVEL master, ext_bandwidth_t U)
671 giacomo 426
{
427
  LEVEL l;            /* the level that we register */
428
  ELASTIC_level_des *lev;  /* for readableness only */
429
  PID i;
430
 
431
  printk("ELASTIC_register_level\n");
432
 
433
  /* request an entry in the level_table */
434
  l = level_alloc_descriptor(sizeof(ELASTIC_level_des));
435
 
436
  lev = (ELASTIC_level_des *)level_table[l];
437
 
438
  /* fill the standard descriptor */
439
  if (flags & ELASTIC_ENABLE_GUARANTEE)
440
    lev->l.public_guarantee = ELASTIC_public_guarantee;
441
  else
442
    lev->l.public_guarantee = NULL;
443
  lev->l.public_create    = ELASTIC_public_create;
444
  lev->l.public_detach    = ELASTIC_public_detach;
445
  lev->l.public_end       = ELASTIC_public_end;
446
  lev->l.public_eligible  = ELASTIC_public_eligible;
447
  lev->l.public_dispatch  = ELASTIC_public_dispatch;
448
  lev->l.public_epilogue  = ELASTIC_public_epilogue;
449
  lev->l.public_activate  = ELASTIC_public_activate;
450
  lev->l.public_unblock   = ELASTIC_public_unblock;
451
  lev->l.public_block     = ELASTIC_public_block;
452
  lev->l.public_message   = ELASTIC_public_message;
453
 
676 giacomo 454
  /* fill the ELASTIC task descriptor part */
671 giacomo 455
  for (i=0; i<MAX_PROC; i++) {
456
     NULL_TIMESPEC(&(lev->elist[i].dline));
457
     lev->elist[i].Tmin = 0;
458
     lev->elist[i].Tmax = 0;
691 anton 459
     lev->elist[i].T = 0;
697 anton 460
     lev->elist[i].U = 0;
691 anton 461
     lev->elist[i].C = 0;
462
     lev->elist[i].E = 0;
671 giacomo 463
     lev->elist[i].beta = 0;
464
     lev->elist[i].flags = ELASTIC_EMPTY_SLOT;
465
  }
466
 
691 anton 467
  lev->U = U;
671 giacomo 468
 
469
  lev->scheduling_level = master;
470
 
471
  lev->current_level = l;
472
 
473
  lev->flags = flags;
474
 
475
  return l;
476
}
477