Subversion Repositories shark

Rev

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

Rev Author Line No. Line
221 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
 *   Paolo Gai           <pj@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) 2001 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
#include "edfstar.h"
39
#include <ll/stdio.h>
40
#include <ll/string.h>
41
#include <kernel/model.h>
42
#include <kernel/descr.h>
43
#include <kernel/var.h>
44
#include <kernel/func.h>
45
#include <kernel/trace.h>
46
 
47
 
48
#define EDFSTAR_CHANGE_LEVEL 1
49
 
50
/* for iqueues */
51
/* #include "iqueue.h" Now iqueues are the only queue type available
52
   into the kernel */
53
#include <kernel/iqueue.h>
54
 
55
/* for BUDGET_TASK_MODEL */
241 giacomo 56
#include "fsf_server.h"
221 giacomo 57
 
58
/*
59
 * DEBUG stuffs begin
60
 */
61
 
224 giacomo 62
//#define EDFSTAR_DEBUG
221 giacomo 63
 
64
#ifdef EDFSTAR_DEBUG
65
 
66
static __inline__ fake_printf(char *fmt, ...) {}
67
 
68
//#define edfstar_printf fake_printf
69
//#define edfstar_printf2 fake_printf
70
//#define edfstar_printf3 fake_printf
71
 
72
#define edfstar_printf kern_printf
73
#define edfstar_printf2 kern_printf
74
#define edfstar_printf3 kern_printf
75
#endif
76
 
77
/*
78
 * DEBUG stuffs end
79
 */
80
 
81
/* Status used in the level */
82
#define EDFSTAR_READY         MODULE_STATUS_BASE    /* - Ready status        */
83
#define EDFSTAR_IDLE          MODULE_STATUS_BASE+4  /* to wait the deadline  */
84
 
85
/* flags */
86
#define EDFSTAR_FLAG_NORAISEEXC  2
348 trimarchi 87
#define EDFSTAR_FLAG_SPORADIC    1
221 giacomo 88
 
348 trimarchi 89
 
221 giacomo 90
/* the level redefinition for the Earliest Deadline First level */
91
typedef struct {
92
  level_des l;     /* the standard level descriptor          */
93
 
94
  TIME period[MAX_PROC]; /* The task periods; the deadlines are
95
                       stored in the priority field           */
96
  int deadline_timer[MAX_PROC];
97
                   /* The task deadline timers               */
98
 
99
  struct timespec deadline_timespec[MAX_PROC];
100
 
101
  int dline_miss[MAX_PROC]; /* Deadline miss counter */
102
  int wcet_miss[MAX_PROC];  /* Wcet miss counter */
103
 
104
  int nact[MAX_PROC];       /* Wcet miss counter */
105
 
106
  int flag[MAX_PROC];
107
                   /* used to manage the JOB_TASK_MODEL and the
108
                       periodicity                            */
109
 
110
  IQUEUE ready;     /* the ready queue                        */
111
 
112
  PID activated;   /* the task that has been inserted into the
113
                       master module */
114
 
115
  int budget[MAX_PROC];
116
 
117
  int scheduling_level;
118
 
296 trimarchi 119
  int cap_lev;
120
  struct timespec cap_lasttime;
121
 
122
 
221 giacomo 123
} EDFSTAR_level_des;
124
 
296 trimarchi 125
 
126
 
127
static void capacity_handler(void *l)
128
{
129
  EDFSTAR_level_des *lev = l;
130
  lev->cap_lev = NIL;
131
  //kern_printf("(/)");
132
  event_need_reschedule();
133
}
134
 
221 giacomo 135
static void EDFSTAR_check_preemption(EDFSTAR_level_des *lev)
136
{
137
  PID first;
138
 
139
#ifdef EDFSTAR_DEBUG
140
  edfstar_printf("(E:chk)");
141
#endif
142
 
143
  if ((first = iq_query_first(&lev->ready)) != lev->activated) {
144
    if (lev->activated != NIL)
145
      level_table[ lev->scheduling_level ]->
146
        private_extract(lev->scheduling_level, lev->activated);
147
 
148
    lev->activated = first;
149
 
150
    if (first != NIL) {
151
      BUDGET_TASK_MODEL b;
152
      budget_task_default_model(b, lev->budget[first]);
153
 
154
      level_table[ lev->scheduling_level ]->
155
        private_insert(lev->scheduling_level, first, (TASK_MODEL *)&b);
156
    }
157
  }
158
}
159
 
160
static void EDFSTAR_timer_deadline(void *par);
161
 
162
static void EDFSTAR_internal_activate(EDFSTAR_level_des *lev, PID p,
163
                                      struct timespec *t)
164
{
165
#ifdef EDFSTAR_DEBUG
166
  edfstar_printf("(E:iact)");
167
#endif
168
 
169
  ADDUSEC2TIMESPEC(lev->period[p], t);
170
 
171
  *iq_query_timespec(p, &lev->ready) = *t;
172
  lev->deadline_timespec[p] = *t;
173
 
174
  /* Insert task in the correct position */
175
  proc_table[p].status = EDFSTAR_READY;
176
  iq_timespec_insert(p,&lev->ready);
296 trimarchi 177
  proc_table[p].control &= ~CONTROL_CAP;
221 giacomo 178
 
179
  /* needed because when there is a wcet miss I disable CONTROL_CAP */
296 trimarchi 180
  //proc_table[p].control |= CONTROL_CAP;
221 giacomo 181
 
182
  /* check for preemption */
183
  EDFSTAR_check_preemption(lev);
184
}
185
 
186
static void EDFSTAR_timer_deadline(void *par)
187
{
188
  PID p = (PID) par;
189
  EDFSTAR_level_des *lev;
190
 
191
#ifdef EDFSTAR_DEBUG
192
//  edfstar_printf("(E:tdl ");
193
#endif
194
 
195
  lev = (EDFSTAR_level_des *)level_table[proc_table[p].task_level];
196
 
197
  switch (proc_table[p].status) {
198
    case EDFSTAR_IDLE:
199
#ifdef EDFSTAR_DEBUG
200
//      edfstar_printf2("I%d",p);
201
#endif
202
      /* set the request time */
350 giacomo 203
      if (!(lev->flag[p] & EDFSTAR_FLAG_SPORADIC))
204
        EDFSTAR_internal_activate(lev,p,iq_query_timespec(p, &lev->ready));
221 giacomo 205
 
206
      event_need_reschedule();
207
      break;
208
 
209
    default:
224 giacomo 210
  #ifdef EDFSTAR_DEBUG
221 giacomo 211
      kern_printf("(E:Dl:%d)",p);
224 giacomo 212
  #endif
221 giacomo 213
      /* else, a deadline miss occurred!!! */
214
      lev->dline_miss[p]++;
215
 
216
      /* the task is into another state */
217
      lev->nact[p]++;
218
 
219
      /* Set the deadline timer */
220
      ADDUSEC2TIMESPEC(lev->period[p], &lev->deadline_timespec[p]);
221
  }
222
 
223
  /* Set the deadline timer */
350 giacomo 224
  if (!(lev->flag[p] & EDFSTAR_FLAG_SPORADIC))
225
    lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
226
                                             EDFSTAR_timer_deadline,
227
                                             (void *)p);
221 giacomo 228
 
229
#ifdef EDFSTAR_DEBUG
230
//  edfstar_printf(")");
231
#endif
232
}
233
 
234
static void EDFSTAR_timer_guest_deadline(void *par)
235
{
236
  PID p = (PID) par;
237
 
238
#ifdef EDFSTAR_DEBUG
239
  edfstar_printf("(E:gdl)");
240
#endif
241
 
242
  kern_raise(XDEADLINE_MISS,p);
243
}
244
 
245
static int EDFSTAR_public_create(LEVEL l, PID p, TASK_MODEL *m)
246
{
247
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
248
 
249
  /* if the EDFSTAR_task_create is called, then the pclass must be a
250
     valid pclass. */
251
  HARD_TASK_MODEL *h;
252
 
253
  if (m->pclass != HARD_PCLASS) return -1;
254
  if (m->level != 0 && m->level != l) return -1;
255
  h = (HARD_TASK_MODEL *)m;
348 trimarchi 256
  if (!h->wcet || !h->mit /* || h->periodicity != PERIODIC */) return -1;
221 giacomo 257
  /* now we know that m is a valid model */
258
 
259
 
260
#ifdef EDFSTAR_DEBUG
261
  edfstar_printf("(E:tcr)");
262
#endif
263
 
264
  lev->period[p] = h->mit;
265
 
266
  lev->flag[p] = 0;
348 trimarchi 267
 
268
  if (h->periodicity == APERIODIC)
269
       lev->flag[p] |= EDFSTAR_FLAG_SPORADIC;
270
 
221 giacomo 271
  lev->deadline_timer[p] = -1;
272
  lev->dline_miss[p]     = 0;
273
  lev->wcet_miss[p]      = 0;
274
  lev->nact[p]           = 0;
275
 
276
  /* Enable wcet check */
277
  proc_table[p].avail_time = h->wcet;
278
  proc_table[p].wcet       = h->wcet;
296 trimarchi 279
  //proc_table[p].control |= CONTROL_CAP;
221 giacomo 280
 
281
  return 0; /* OK, also if the task cannot be guaranteed... */
282
}
283
 
296 trimarchi 284
 
285
static void EDFSTAR_account_capacity(EDFSTAR_level_des *lev, PID p)
286
{
287
  struct timespec ty;
288
  TIME tx;
289
 
290
  SUBTIMESPEC(&schedule_time, &lev->cap_lasttime, &ty);
291
  tx = TIMESPEC2USEC(&ty);
292
 
293
  proc_table[p].avail_time -= tx;
294
  //kern_printf("avail time pid %d , %d", p, proc_table[p].avail_time);
295
 
296
}
221 giacomo 297
static int EDFSTAR_public_eligible(LEVEL l, PID p)
298
{
299
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
300
 
301
#ifdef EDFSTAR_DEBUG
302
  edfstar_printf2("(E:eli)");
303
#endif
304
 
305
  return level_table[ lev->scheduling_level ]->
306
    private_eligible(lev->scheduling_level,p);
307
}
308
 
309
static void EDFSTAR_public_dispatch(LEVEL l, PID p, int nostop)
310
{
311
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
296 trimarchi 312
  struct timespec ty;
221 giacomo 313
 
314
#ifdef EDFSTAR_DEBUG
315
  edfstar_printf("(E:dis)");
316
 
317
  edfstar_printf3("(%d %d)",
318
                  iq_query_timespec(p, &lev->ready)->tv_nsec/1000000,
319
                  schedule_time.tv_nsec/1000000);
320
#endif
296 trimarchi 321
  if (!nostop || proc_table[exec].task_level==l) {
322
      TIMESPEC_ASSIGN(&ty, &schedule_time);
323
      TIMESPEC_ASSIGN(&lev->cap_lasttime, &schedule_time);
221 giacomo 324
 
296 trimarchi 325
      /* ...and finally, we have to post a capacity event on exec task because the shadow_task consume
326
       *      *        capacity on exe task always */
327
      ADDUSEC2TIMESPEC(proc_table[exec].avail_time ,&ty);
328
      lev->cap_lev = kern_event_post(&ty,capacity_handler, lev);
329
      level_table[lev->scheduling_level]->private_dispatch(lev->scheduling_level, p, nostop);
330
  }
331
  else
332
      level_table[proc_table[exec].task_level]->public_dispatch(proc_table[exec].task_level, p, nostop);
333
 
221 giacomo 334
}
335
 
336
static void EDFSTAR_public_epilogue(LEVEL l, PID p)
337
{
338
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
339
 
340
#ifdef EDFSTAR_DEBUG
341
  edfstar_printf("(E:epi ");
342
#endif
343
 
296 trimarchi 344
  if (lev->cap_lev!=NIL) {
345
       kern_event_delete(lev->cap_lev);
346
       lev->cap_lev=NIL;
347
  }
348
 
349
 
350
  if ( proc_table[exec].task_level==l ) {
351
 
352
     EDFSTAR_account_capacity(lev,exec);
353
 
354
     /* check if the wcet is finished... */
355
     if (proc_table[exec].avail_time <= 0) {
356
        /* wcet finished: disable wcet event and count wcet miss */
221 giacomo 357
#ifdef EDFSTAR_DEBUG
358
    edfstar_printf2("W%d",p);
359
#endif
296 trimarchi 360
        //proc_table[p].control &= ~CONTROL_CAP;
361
        lev->wcet_miss[exec]++;
362
     }
221 giacomo 363
#ifdef EDFSTAR_DEBUG
364
  edfstar_printf(")");
365
#endif
366
 
367
  level_table[ lev->scheduling_level ]->
368
    private_epilogue(lev->scheduling_level,p);
369
 
296 trimarchi 370
  proc_table[exec].status = EDFSTAR_READY;
371
    } else
372
        level_table[proc_table[exec].task_level]->public_epilogue(proc_table[exec].task_level,p);
373
 
221 giacomo 374
}
375
 
376
static void EDFSTAR_public_activate(LEVEL l, PID p)
377
{
378
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
379
  struct timespec t;
380
 
381
  #ifdef EDFSTAR_DEBUG
382
    edfstar_printf("(E:act:%d)",p);
383
  #endif
384
 
385
  /* Test if we are trying to activate a non sleeping task    */
386
  /* save activation (only if needed... */
387
  if (proc_table[p].status != SLEEP) {
388
    /* a periodic task cannot be activated when it is already active */
348 trimarchi 389
    /* but aperiodic task can be reactivate before */
390
    if (lev->flag[p] & EDFSTAR_FLAG_SPORADIC)
391
       lev->nact[p]++;
392
    else
393
       kern_raise(XACTIVATION,p);
394
 
350 giacomo 395
    if (proc_table[p].status != EDFSTAR_IDLE) return;
396
 
221 giacomo 397
  }
398
 
399
  kern_gettime(&t);
400
 
401
  EDFSTAR_internal_activate(lev,p, &t);
402
 
403
  /* Set the deadline timer */
404
  lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
405
                                           EDFSTAR_timer_deadline,
406
                                           (void *)p);
407
 
408
}
409
 
410
static void EDFSTAR_public_unblock(LEVEL l, PID p)
411
{
412
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
413
 
414
#ifdef EDFSTAR_DEBUG
348 trimarchi 415
edfstar_printf("(E:ins)");
221 giacomo 416
#endif
417
 
348 trimarchi 418
/* Insert task in the correct position */
419
proc_table[p].status = EDFSTAR_READY;
420
iq_timespec_insert(p,&lev->ready);
221 giacomo 421
 
348 trimarchi 422
/* and check for preemption! */
423
EDFSTAR_check_preemption(lev);
221 giacomo 424
}
425
 
426
static void EDFSTAR_public_block(LEVEL l, PID p)
427
{
348 trimarchi 428
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
221 giacomo 429
 
430
#ifdef EDFSTAR_DEBUG
348 trimarchi 431
edfstar_printf("(E:ext)");
221 giacomo 432
#endif
433
 
348 trimarchi 434
/* the task is blocked on a synchronization primitive. we have to
435
remove it from the master module -and- from the local queue! */
436
iq_extract(p,&lev->ready);
221 giacomo 437
 
348 trimarchi 438
/* and finally, a preemption check! (it will also call guest_end) */
439
EDFSTAR_check_preemption(lev);
221 giacomo 440
}
441
 
442
static int EDFSTAR_public_message(LEVEL l, PID p, void *m)
443
{
348 trimarchi 444
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
445
struct timespec temp;
221 giacomo 446
 
447
#ifdef EDFSTAR_DEBUG
348 trimarchi 448
edfstar_printf("(E:ecy ");
221 giacomo 449
#endif
450
 
348 trimarchi 451
switch ((long)(m)) {
221 giacomo 452
 
348 trimarchi 453
/* Task EndCycle */
454
case (long)(NULL):
221 giacomo 455
 
348 trimarchi 456
/* we call guest_end directly here because the same task may
457
be reinserted in the queue before calling the preemption check! */
458
level_table[ lev->scheduling_level ]->
459
private_extract(lev->scheduling_level,p);
460
lev->activated = NIL;
461
 
462
iq_extract(p,&lev->ready);
463
 
464
/* we reset the capacity counters... */
465
proc_table[p].avail_time = proc_table[p].wcet;
466
 
467
if (lev->nact[p] > 0) {
221 giacomo 468
 
469
      #ifdef EDFSTAR_DEBUG
470
        edfstar_printf2("E%d",p);
471
      #endif
472
 
473
      /* Pending activation: reactivate the thread!!! */
474
      lev->nact[p]--;
475
 
476
      /* see also EDFSTAR_timer_deadline */
477
      kern_gettime(&temp);
478
 
479
      EDFSTAR_internal_activate(lev,p, &temp);
480
 
481
      /* check if the deadline has already expired */
482
      temp = *iq_query_timespec(p, &lev->ready);
483
      if (TIMESPEC_A_LT_B(&temp, &schedule_time)) {
484
          /* count the deadline miss */
485
          lev->dline_miss[p]++;
486
          kern_event_delete(lev->deadline_timer[p]);
487
      }
488
 
489
    } else {
490
 
491
      #ifdef EDFSTAR_DEBUG
492
        edfstar_printf("e%d",p);
493
      #endif
494
 
495
      /* the task has terminated his job before it consume the wcet. All OK! */
496
      proc_table[p].status = EDFSTAR_IDLE;
497
 
498
      /* and finally, a preemption check! */
499
      EDFSTAR_check_preemption(lev);
500
 
501
      /* when the deadline timer fire, it recognize the situation and set
502
         correctly all the stuffs (like reactivation, etc... ) */
503
    }
504
#ifdef EDFSTAR_DEBUG
505
    edfstar_printf(")");
506
#endif
507
 
508
    jet_update_endcycle(); /* Update the Jet data... */
509
    trc_logevent(TRC_ENDCYCLE,&exec_shadow); /* tracer stuff */
510
    break;
511
 
512
  default:
513
 
241 giacomo 514
    break;
221 giacomo 515
 
516
  }
517
  return 0;
518
}
519
 
520
static void EDFSTAR_public_end(LEVEL l, PID p)
521
{
522
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
523
 
524
#ifdef EDFSTAR_DEBUG
525
  edfstar_printf("(E:end)");
526
#endif
527
 
528
  iq_extract(p,&lev->ready);
529
 
530
  /* we finally put the task in the ready queue */
531
  proc_table[p].status = FREE;
532
 
533
  iq_insertfirst(p,&freedesc);
348 trimarchi 534
  lev->activated=NIL;
221 giacomo 535
 
536
  if (lev->deadline_timer[p] != -1) {
537
    kern_event_delete(lev->deadline_timer[p]);
538
  }
539
 
540
  /* and finally, a preemption check! (it will also call guest_end) */
541
  EDFSTAR_check_preemption(lev);
542
}
543
 
544
/* Guest Functions
545
   These functions manages a JOB_TASK_MODEL, that is used to put
546
   a guest task in the EDFSTAR ready queue. */
547
 
548
static void EDFSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
549
{
550
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
551
  JOB_TASK_MODEL *job;
552
 
553
  if (m->pclass != JOB_PCLASS || (m->level != 0 && m->level != l) ) {
554
    kern_raise(XINVALID_TASK, p);
555
    return;
556
  }
557
 
558
  job = (JOB_TASK_MODEL *)m;
559
 
560
  /* if the EDFSTAR_guest_create is called, then the pclass must be a
561
     valid pclass. */
562
 
563
  *iq_query_timespec(p, &lev->ready) = job->deadline;
564
 
565
  lev->deadline_timer[p] = -1;
566
  lev->dline_miss[p]     = 0;
567
  lev->wcet_miss[p]      = 0;
568
  lev->nact[p]           = 0;
569
 
570
  if (job->noraiseexc)
571
    lev->flag[p] |= EDFSTAR_FLAG_NORAISEEXC;
572
  else {
573
    lev->flag[p] &= ~EDFSTAR_FLAG_NORAISEEXC;
574
    lev->deadline_timer[p] = kern_event_post(iq_query_timespec(p, &lev->ready),
575
                                             EDFSTAR_timer_guest_deadline,
576
                                             (void *)p);
577
  }
578
 
579
  lev->period[p] = job->period;
580
 
581
  /* Insert task in the correct position */
582
  iq_timespec_insert(p,&lev->ready);
583
  proc_table[p].status = EDFSTAR_READY;
584
 
585
  /* check for preemption */
586
  EDFSTAR_check_preemption(lev);
587
 
588
  /* there is no bandwidth guarantee at this level, it is performed
589
     by the level that inserts guest tasks... */
590
}
591
 
592
static void EDFSTAR_private_dispatch(LEVEL l, PID p, int nostop)
593
{
594
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
595
 
596
  level_table[ lev->scheduling_level ]->
597
    private_dispatch(lev->scheduling_level,p,nostop);
598
}
599
 
600
static void EDFSTAR_private_epilogue(LEVEL l, PID p)
601
{
602
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
603
 
604
  /* the task has been preempted. it returns into the ready queue... */
605
  level_table[ lev->scheduling_level ]->
606
    private_epilogue(lev->scheduling_level,p);
607
 
608
  proc_table[p].status = EDFSTAR_READY;
609
}
610
 
611
static void EDFSTAR_private_extract(LEVEL l, PID p)
612
{
613
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
614
 
615
#ifdef EDFSTAR_DEBUG
616
  //kern_printf("EDFSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
617
#endif
618
 
619
  iq_extract(p, &lev->ready);
620
 
621
  /* we remove the deadline timer, because the slice is finished */
622
  if (lev->deadline_timer[p] != NIL) {
623
#ifdef EDFSTAR_DEBUG
624
//    kern_printf("EDFSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
625
#endif
626
    kern_event_delete(lev->deadline_timer[p]);
627
    lev->deadline_timer[p] = NIL;
628
  }
629
 
630
  /* and finally, a preemption check! (it will also call guest_end() */
631
  EDFSTAR_check_preemption(lev);
632
}
633
 
634
/* Registration functions */
635
 
636
/* Registration function:
637
    int flags                 the init flags ... see EDFSTAR.h */
638
 
639
LEVEL EDFSTAR_register_level(int master)
640
{
641
  LEVEL l;            /* the level that we register */
642
  EDFSTAR_level_des *lev;  /* for readableness only */
643
  PID i;              /* a counter */
644
 
645
#ifdef EDFSTAR_DEBUG
646
  printk("EDFSTAR_register_level\n");
647
#endif
648
 
649
  /* request an entry in the level_table */
650
  l = level_alloc_descriptor(sizeof(EDFSTAR_level_des));
651
 
652
  lev = (EDFSTAR_level_des *)level_table[l];
653
 
654
  printk("    lev=%d\n",(int)lev);
655
 
656
  /* fill the standard descriptor */
657
  lev->l.private_insert   = EDFSTAR_private_insert;
658
  lev->l.private_extract  = EDFSTAR_private_extract;
659
  lev->l.private_dispatch = EDFSTAR_private_dispatch;
660
  lev->l.private_epilogue = EDFSTAR_private_epilogue;
661
 
662
  lev->l.public_guarantee = NULL;
663
  lev->l.public_eligible  = EDFSTAR_public_eligible;
664
  lev->l.public_create    = EDFSTAR_public_create;
665
  lev->l.public_end       = EDFSTAR_public_end;
666
  lev->l.public_dispatch  = EDFSTAR_public_dispatch;
667
  lev->l.public_epilogue  = EDFSTAR_public_epilogue;
668
  lev->l.public_activate  = EDFSTAR_public_activate;
669
  lev->l.public_unblock   = EDFSTAR_public_unblock;
670
  lev->l.public_block     = EDFSTAR_public_block;
671
  lev->l.public_message   = EDFSTAR_public_message;
672
 
673
  /* fill the EDFSTAR descriptor part */
674
  for(i=0; i<MAX_PROC; i++) {
675
    lev->period[i]         = 0;
676
    lev->deadline_timer[i] = -1;
677
    lev->flag[i]           = 0;
678
    lev->dline_miss[i]     = 0;
679
    lev->wcet_miss[i]      = 0;
680
    lev->nact[i]           = 0;
681
    lev->budget[i]         = NIL;
682
  }
683
 
684
  iq_init(&lev->ready, NULL, IQUEUE_NO_PRIORITY);
685
  lev->activated = NIL;
686
 
687
  lev->scheduling_level = master;
298 giacomo 688
  lev->cap_lev = NIL;
296 trimarchi 689
  NULL_TIMESPEC(&lev->cap_lasttime);
221 giacomo 690
 
691
  return l;
692
}
693
 
694
int EDFSTAR_get_dline_miss(PID p)
695
{
696
  LEVEL l = proc_table[p].task_level;
697
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
698
 
699
  return lev->dline_miss[p];
700
}
701
 
702
int EDFSTAR_get_wcet_miss(PID p)
703
{
704
  LEVEL l = proc_table[p].task_level;
705
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
706
 
707
  return lev->wcet_miss[p];
708
}
709
 
710
int EDFSTAR_get_nact(PID p)
711
{
712
  LEVEL l = proc_table[p].task_level;
713
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
714
 
715
  return lev->nact[p];
716
}
717
 
718
int EDFSTAR_reset_dline_miss(PID p)
719
{
720
  LEVEL l = proc_table[p].task_level;
721
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
722
 
723
  lev->dline_miss[p] = 0;
724
  return 0;
725
}
726
 
727
int EDFSTAR_reset_wcet_miss(PID p)
728
{
729
  LEVEL l = proc_table[p].task_level;
730
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
731
 
732
  lev->wcet_miss[p] = 0;
733
  return 0;
734
}
735
 
736
int EDFSTAR_setbudget(LEVEL l, PID p, int budget)
737
{
738
 
739
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
740
 
741
  lev->budget[p] = budget;
742
 
743
  return 0;
744
 
745
}
746
 
747
int EDFSTAR_getbudget(LEVEL l, PID p)
748
{
749
 
750
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
751
 
752
  return lev->budget[p];
753
 
754
}
236 giacomo 755
 
756
int EDFSTAR_budget_has_thread(LEVEL l, int budget)
757
{
758
 
759
  EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
760
  int i;
761
 
762
  for(i = 0; i< MAX_PROC; i++)
763
    if (lev->budget[i] == budget) return 1;
764
 
765
  return 0;
766
 
767
}