Subversion Repositories shark

Rev

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

Rev Author Line No. Line
1089 pj 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
 ------------
1100 pj 21
 CVS :        $Id: rmstar.c,v 1.2 2002-10-28 08:16:09 pj Exp $
1089 pj 22
 
23
 File:        $File$
1100 pj 24
 Revision:    $Revision: 1.2 $
25
 Last update: $Date: 2002-10-28 08:16:09 $
1089 pj 26
 ------------
27
**/
28
 
29
/*
30
 * Copyright (C) 2001 Paolo Gai
31
 *
32
 * This program is free software; you can redistribute it and/or modify
33
 * it under the terms of the GNU General Public License as published by
34
 * the Free Software Foundation; either version 2 of the License, or
35
 * (at your option) any later version.
36
 *
37
 * This program is distributed in the hope that it will be useful,
38
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40
 * GNU General Public License for more details.
41
 *
42
 * You should have received a copy of the GNU General Public License
43
 * along with this program; if not, write to the Free Software
44
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
45
 *
46
 */
47
 
48
#include "rmstar.h"
49
#include <ll/stdio.h>
50
#include <ll/string.h>
51
#include <kernel/model.h>
52
#include <kernel/descr.h>
53
#include <kernel/var.h>
54
#include <kernel/func.h>
55
#include <kernel/trace.h>
56
 
57
/* for iqueues */
58
#include "iqueue.h"
59
 
60
/* for BUDGET_TASK_MODEL */
61
#include "cbsstar.h"
62
 
63
/*
64
 * DEBUG stuffs begin
65
 */
66
 
67
//#define RMSTAR_DEBUG
68
 
69
#ifdef RMSTAR_DEBUF
70
 
71
static __inline__ fake_printf(char *fmt, ...) {}
72
 
73
#define rmstar_printf fake_printf
74
#define rmstar_printf2 fake_printf
75
#define rmstar_printf3 fake_printf
76
 
77
//#define rmstar_printf kern_printf
78
//#define rmstar_printf2 kern_printf
79
//#define rmstar_printf3 kern_printf
80
#endif
81
 
82
/*
83
 * DEBUG stuffs end
84
 */
85
 
86
/* Status used in the level */
87
#define RMSTAR_READY         MODULE_STATUS_BASE    /* - Ready status        */
88
#define RMSTAR_IDLE          MODULE_STATUS_BASE+4  /* to wait the deadline  */
89
 
90
/* flags */
91
#define RMSTAR_FLAG_NORAISEEXC  2
92
 
93
/* the level redefinition for the Earliest Deadline First level */
94
typedef struct {
95
  level_des l;     /* the standard level descriptor          */
96
 
97
  TIME period[MAX_PROC]; /* The task periods; the deadlines are
98
                       stored in the priority field           */
99
  int deadline_timer[MAX_PROC];
100
                   /* The task deadline timers               */
101
 
102
  struct timespec deadline_timespec[MAX_PROC];
103
 
104
  int dline_miss[MAX_PROC]; /* Deadline miss counter */
105
  int wcet_miss[MAX_PROC];  /* Wcet miss counter */
106
 
107
  int nact[MAX_PROC];       /* Wcet miss counter */
108
 
109
  int flag[MAX_PROC];
110
                   /* used to manage the JOB_TASK_MODEL and the
111
                       periodicity                            */
112
 
113
  IQUEUE ready;     /* the ready queue                        */
114
 
115
  PID activated;   /* the task that has been inserted into the
116
                       master module */
117
 
118
  int budget;
119
 
120
  int scheduling_level;
121
} RMSTAR_level_des;
122
 
123
static void RMSTAR_check_preemption(RMSTAR_level_des *lev)
124
{
125
  PID first;
126
 
127
#ifdef RMSTAR_DEBUG
128
  rmstar_printf("(E:chk)");
129
#endif
130
 
131
  if ((first = iq_queryfirst(&lev->ready)) != lev->activated) {
132
    if (lev->activated != NIL)
133
      level_table[ lev->scheduling_level ]->
134
        guest_end(lev->scheduling_level, lev->activated);
135
 
136
    lev->activated = first;
137
 
138
    if (first != NIL) {
139
      BUDGET_TASK_MODEL b;
140
      budget_task_default_model(b, lev->budget);
141
 
142
      level_table[ lev->scheduling_level ]->
143
        guest_create(lev->scheduling_level, first, (TASK_MODEL *)&b);
144
    }
145
  }
146
}
147
 
148
static void RMSTAR_timer_deadline(void *par);
149
 
150
static void RMSTAR_internal_activate(RMSTAR_level_des *lev, PID p)
151
{
152
  struct timespec temp;
153
 
154
#ifdef RMSTAR_DEBUG
155
  rmstar_printf("(E:iact)");
156
#endif
157
 
158
  TIMESPEC_ASSIGN(&temp, &proc_table[p].request_time);
159
  ADDUSEC2TIMESPEC(lev->period[p], &temp);
160
 
161
  *iq_query_timespec(p, &lev->ready) = temp;
162
  lev->deadline_timespec[p] = temp;
163
 
164
  /* Insert task in the correct position */
165
  proc_table[p].status = RMSTAR_READY;
166
  iq_priority_insert(p,&lev->ready);
167
 
168
  /* needed because when there is a wcet miss I disable CONTROL_CAP */
169
  proc_table[p].control |= CONTROL_CAP;
170
 
171
  /* check for preemption */
172
  RMSTAR_check_preemption(lev);
173
}
174
 
175
static char *RMSTAR_status_to_a(WORD status)
176
{
177
  if (status < MODULE_STATUS_BASE)
178
    return status_to_a(status);
179
 
180
  switch (status) {
181
    case RMSTAR_READY    : return "RMSTAR_Ready";
182
    case RMSTAR_IDLE     : return "RMSTAR_Idle";
183
    default               : return "RMSTAR_Unknown";
184
  }
185
}
186
 
187
static void RMSTAR_timer_deadline(void *par)
188
{
189
  PID p = (PID) par;
190
  RMSTAR_level_des *lev;
191
 
192
#ifdef RMSTAR_DEBUG
193
//  rmstar_printf("(E:tdl ");
194
#endif
195
 
196
  lev = (RMSTAR_level_des *)level_table[proc_table[p].task_level];
197
 
198
  switch (proc_table[p].status) {
199
    case RMSTAR_IDLE:
200
#ifdef RMSTAR_DEBUG
201
//      rmstar_printf2("I%d",p);
202
#endif
203
      /* set the request time */
204
      proc_table[p].request_time = *iq_query_timespec(p, &lev->ready);
205
 
206
      RMSTAR_internal_activate(lev,p);
207
 
208
      event_need_reschedule();
209
      break;
210
 
211
    default:
212
#ifdef RMSTAR_DEBUG
213
//      rmstar_printf2("D%d",p);
214
#endif
215
      /* else, a deadline miss occurred!!! */
216
      lev->dline_miss[p]++;
217
 
218
      /* the task is into another state */
219
      lev->nact[p]++;
220
 
221
      /* Set the deadline timer */
222
      ADDUSEC2TIMESPEC(lev->period[p], &lev->deadline_timespec[p]);
223
  }
224
 
225
  /* Set the deadline timer */
226
  lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
227
                                           RMSTAR_timer_deadline,
228
                                           (void *)p);
229
 
230
#ifdef RMSTAR_DEBUG
231
//  rmstar_printf(")");
232
#endif
233
}
234
 
235
static void RMSTAR_timer_guest_deadline(void *par)
236
{
237
  PID p = (PID) par;
238
 
239
#ifdef RMSTAR_DEBUG
240
  rmstar_printf("(E:gdl)");
241
#endif
242
 
243
  kern_raise(XDEADLINE_MISS,p);
244
}
245
 
246
static int RMSTAR_level_accept_task_model(LEVEL l, TASK_MODEL *m)
247
{
248
#ifdef RMSTAR_DEBUG
249
  rmstar_printf("(E:lacct)");
250
#endif
251
 
252
  if (m->pclass == HARD_PCLASS || m->pclass == (HARD_PCLASS | l)) {
253
    HARD_TASK_MODEL *h = (HARD_TASK_MODEL *)m;
254
 
255
    if (h->wcet && h->mit && h->periodicity == PERIODIC)
256
      return 0;
257
  }
258
 
259
  return -1;
260
}
261
 
262
static int RMSTAR_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
263
{
264
#ifdef RMSTAR_DEBUG
265
  rmstar_printf("(E:laccg)");
266
#endif
267
 
268
  if (m->pclass == JOB_PCLASS || m->pclass == (JOB_PCLASS | l))
269
    return 0;
270
  else
271
    return -1;
272
}
273
 
274
 
275
static char *onoff(int i)
276
{
277
  if (i)
278
    return "On ";
279
  else
280
    return "Off";
281
}
282
 
283
static void RMSTAR_level_status(LEVEL l)
284
{
285
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
286
  PID p = iq_queryfirst(&lev->ready);
287
  struct timespec temp;
288
 
289
  kern_printf("Budget number     : %u\n", lev->budget);
290
  kern_printf("Master level      : %u\n", lev->scheduling_level);
291
  kern_printf("Active PID        : %u\n", lev->activated);
292
 
293
  while (p != NIL) {
294
    if ((proc_table[p].pclass) == JOB_PCLASS)
295
      kern_printf("Pid: %2d (GUEST)\n", p);
296
    else {
297
      temp = *iq_query_timespec(p, &lev->ready);
298
 
299
      kern_printf("Pid: %2d Name: %10s %s: %9ld Dline: %9ld.%6ld Stat: %s\n",
300
                  p,
301
                  proc_table[p].name,
302
                  "Period  ",
303
                  lev->period[p],
304
                  temp.tv_sec,
305
                  temp.tv_nsec/1000,
306
                  RMSTAR_status_to_a(proc_table[p].status));
307
      p = proc_table[p].next;
308
    }
309
  }
310
 
311
  for (p=0; p<MAX_PROC; p++)
312
    if (proc_table[p].task_level == l
313
        && proc_table[p].status != RMSTAR_READY
314
        && proc_table[p].status != FREE ) {
315
      temp = *iq_query_timespec(p, &lev->ready);
316
 
317
      kern_printf("Pid: %2d Name: %10s %s: %9ld Dline: %9ld.%6ld Stat: %s\n",
318
                  p,
319
                  proc_table[p].name,
320
                  "Period  ",
321
                  lev->period[p],
322
                  temp.tv_sec,
323
                  temp.tv_nsec/1000,
324
                  RMSTAR_status_to_a(proc_table[p].status));
325
    }
326
}
327
 
328
/* The scheduler only gets the first task in the queue */
329
static PID RMSTAR_level_scheduler(LEVEL l)
330
{
331
  //RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
332
 
333
  return NIL;
334
}
335
 
336
static int RMSTAR_task_create(LEVEL l, PID p, TASK_MODEL *m)
337
{
338
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
339
 
340
  /* if the RMSTAR_task_create is called, then the pclass must be a
341
     valid pclass. */
342
  HARD_TASK_MODEL *h = (HARD_TASK_MODEL *)m;
343
 
344
#ifdef RMSTAR_DEBUG
345
  rmstar_printf("(E:tcr)");
346
#endif
347
 
348
  lev->period[p] = h->mit;
349
  *iq_query_priority(p, &lev->ready) = h->mit;
350
 
351
  lev->flag[p] = 0;
352
  lev->deadline_timer[p] = -1;
353
  lev->dline_miss[p]     = 0;
354
  lev->wcet_miss[p]      = 0;
355
  lev->nact[p]           = 0;
356
 
357
  /* Enable wcet check */
358
  proc_table[p].avail_time = h->wcet;
359
  proc_table[p].wcet       = h->wcet;
360
  proc_table[p].control |= CONTROL_CAP;
361
 
362
  return 0; /* OK, also if the task cannot be guaranteed... */
363
}
364
 
365
static void RMSTAR_task_detach(LEVEL l, PID p)
366
{
367
#ifdef RMSTAR_DEBUG
368
  rmstar_printf2("(E:tdt)");
369
#endif
370
}
371
 
372
static int RMSTAR_task_eligible(LEVEL l, PID p)
373
{
374
#ifdef RMSTAR_DEBUG
375
  rmstar_printf2("(E:eli)");
376
#endif
377
 
378
  return 0; /* if the task p is chosen, it is always eligible */
379
}
380
 
381
static void RMSTAR_task_dispatch(LEVEL l, PID p, int nostop)
382
{
383
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
384
 
385
#ifdef RMSTAR_DEBUG
386
  rmstar_printf("(E:dis)");
387
 
388
  rmstar_printf3("(%d %d)",
389
                  iq_query_timespec(p, &lev->ready)->tv_nsec/1000000,
390
                  schedule_time.tv_nsec/1000000);
391
#endif
392
 
393
  level_table[ lev->scheduling_level ]->
394
    guest_dispatch(lev->scheduling_level,p,nostop);
395
}
396
 
397
static void RMSTAR_task_epilogue(LEVEL l, PID p)
398
{
399
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
400
 
401
#ifdef RMSTAR_DEBUG
402
  rmstar_printf("(E:epi ");
403
#endif
404
 
405
  /* check if the wcet is finished... */
406
  if (proc_table[p].avail_time <= 0 && proc_table[p].control&CONTROL_CAP) {
407
    /* wcet finished: disable wcet event and count wcet miss */
408
#ifdef RMSTAR_DEBUG
409
    rmstar_printf2("W%d",p);
410
#endif
411
    proc_table[p].control &= ~CONTROL_CAP;
412
    lev->wcet_miss[p]++;
413
  }
414
#ifdef RMSTAR_DEBUG
415
  rmstar_printf(")");
416
#endif
417
 
418
  level_table[ lev->scheduling_level ]->
419
    guest_epilogue(lev->scheduling_level,p);
420
 
421
  proc_table[p].status = RMSTAR_READY;
422
}
423
 
424
static void RMSTAR_task_activate(LEVEL l, PID p)
425
{
426
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
427
 
428
#ifdef RMSTAR_DEBUG
429
  rmstar_printf("(E:act)");
430
#endif
431
 
432
  /* Test if we are trying to activate a non sleeping task    */
433
  /* save activation (only if needed... */
434
  if (proc_table[p].status != SLEEP) {
435
    /* a periodic task cannot be activated when it is already active */
436
    kern_raise(XACTIVATION,p);
437
    return;
438
  }
439
 
440
  ll_gettime(TIME_EXACT, &proc_table[p].request_time);
441
 
442
  RMSTAR_internal_activate(lev,p);
443
 
444
  /* Set the deadline timer */
445
  lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
446
                                           RMSTAR_timer_deadline,
447
                                           (void *)p);
448
 
449
}
450
 
451
static void RMSTAR_task_insert(LEVEL l, PID p)
452
{
453
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
454
 
455
#ifdef RMSTAR_DEBUG
456
  rmstar_printf("(E:ins)");
457
#endif
458
 
459
  /* Insert task in the correct position */
460
  proc_table[p].status = RMSTAR_READY;
461
  iq_priority_insert(p,&lev->ready);
462
 
463
  /* and check for preemption! */
464
  RMSTAR_check_preemption(lev);
465
}
466
 
467
static void RMSTAR_task_extract(LEVEL l, PID p)
468
{
469
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
470
 
471
#ifdef RMSTAR_DEBUG
472
  rmstar_printf("(E:ext)");
473
#endif
474
 
475
  /* the task is blocked on a synchronization primitive. we have to
476
     remove it from the master module -and- from the local queue! */
477
  iq_extract(p,&lev->ready);
478
 
479
  /* and finally, a preemption check! (it will also call guest_end) */
480
  RMSTAR_check_preemption(lev);
481
}
482
 
483
static void RMSTAR_task_endcycle(LEVEL l, PID p)
484
{
485
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
486
  struct timespec temp;
487
 
488
#ifdef RMSTAR_DEBUG
489
  rmstar_printf("(E:ecy ");
490
#endif
491
 
492
  /* we call guest_end directly here because the same task may
493
     be reinserted in the queue before calling the preemption check! */
494
  level_table[ lev->scheduling_level ]->
495
    guest_end(lev->scheduling_level,p);
496
  lev->activated = NIL;
497
 
498
  iq_extract(p,&lev->ready);
499
 
500
  /* we reset the capacity counters... */
501
  proc_table[p].avail_time = proc_table[p].wcet;
502
 
503
  if (lev->nact[p] > 0) {
504
#ifdef RMSTAR_DEBUG
505
    rmstar_printf2("E%d",p);
506
#endif
507
 
508
    /* Pending activation: reactivate the thread!!! */
509
    lev->nact[p]--;
510
 
511
    /* see also RMSTAR_timer_deadline */
512
    ll_gettime(TIME_EXACT, &proc_table[p].request_time);
513
 
514
    RMSTAR_internal_activate(lev,p);
515
 
516
    /* check if the deadline has already expired */
517
    temp = *iq_query_timespec(p, &lev->ready);
518
    if (TIMESPEC_A_LT_B(&temp, &schedule_time)) {
519
      /* count the deadline miss */
520
      lev->dline_miss[p]++;
521
      event_delete(lev->deadline_timer[p]);
522
    }
523
 
524
  }
525
  else {
526
#ifdef RMSTAR_DEBUG
527
    rmstar_printf("e%d",p);
528
#endif
529
 
530
    /* the task has terminated his job before it consume the wcet. All OK! */
531
    proc_table[p].status = RMSTAR_IDLE;
532
 
533
    /* and finally, a preemption check! */
534
    RMSTAR_check_preemption(lev);
535
 
536
    /* when the deadline timer fire, it recognize the situation and set
537
       correctly all the stuffs (like reactivation, request_time, etc... ) */
538
  }
539
#ifdef RMSTAR_DEBUG
540
  rmstar_printf(")");
541
#endif
542
}
543
 
544
static void RMSTAR_task_end(LEVEL l, PID p)
545
{
546
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
547
 
548
#ifdef RMSTAR_DEBUG
549
  rmstar_printf("(E:end)");
550
#endif
551
 
552
  iq_extract(p,&lev->ready);
553
 
554
  /* we finally put the task in the ready queue */
555
  proc_table[p].status = FREE;
556
 
557
  q_insertfirst(p,&freedesc);
558
 
559
  if (lev->deadline_timer[p] != -1) {
560
    event_delete(lev->deadline_timer[p]);
561
  }
562
 
563
  /* and finally, a preemption check! (it will also call guest_end) */
564
  RMSTAR_check_preemption(lev);
565
}
566
 
567
static void RMSTAR_task_sleep(LEVEL l, PID p)
1100 pj 568
{ kern_raise(XINVALID_TASK,exec_shadow); }
1089 pj 569
 
570
static void RMSTAR_task_delay(LEVEL l, PID p, TIME usdelay)
1100 pj 571
{ kern_raise(XINVALID_TASK,exec_shadow); }
1089 pj 572
 
573
/* Guest Functions
574
   These functions manages a JOB_TASK_MODEL, that is used to put
575
   a guest task in the RMSTAR ready queue. */
576
 
577
static int RMSTAR_guest_create(LEVEL l, PID p, TASK_MODEL *m)
578
{
579
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
580
  JOB_TASK_MODEL *job = (JOB_TASK_MODEL *)m;
581
 
582
  /* if the RMSTAR_guest_create is called, then the pclass must be a
583
     valid pclass. */
584
 
585
  *iq_query_timespec(p, &lev->ready) = job->deadline;
586
 
587
  lev->deadline_timer[p] = -1;
588
  lev->dline_miss[p]     = 0;
589
  lev->wcet_miss[p]      = 0;
590
  lev->nact[p]           = 0;
591
 
592
  if (job->noraiseexc)
593
    lev->flag[p] = RMSTAR_FLAG_NORAISEEXC;
594
  else
595
    lev->flag[p] = 0;
596
 
597
  lev->period[p] = job->period;
598
  *iq_query_priority(p, &lev->ready) = job->period;
599
 
600
  /* there is no bandwidth guarantee at this level, it is performed
601
     by the level that inserts guest tasks... */
602
 
603
  return 0; /* OK, also if the task cannot be guaranteed... */
604
}
605
 
606
static void RMSTAR_guest_detach(LEVEL l, PID p)
607
{
608
  /* the RMSTAR level doesn't introduce any dinamic allocated new field.
609
     No guarantee is performed on guest tasks... so we don't have to reset
610
     the NO_GUARANTEE FIELD */
611
}
612
 
613
static void RMSTAR_guest_dispatch(LEVEL l, PID p, int nostop)
614
{
615
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
616
 
617
  level_table[ lev->scheduling_level ]->
618
    guest_dispatch(lev->scheduling_level,p,nostop);
619
}
620
 
621
static void RMSTAR_guest_epilogue(LEVEL l, PID p)
622
{
623
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
624
 
625
  /* the task has been preempted. it returns into the ready queue... */
626
  level_table[ lev->scheduling_level ]->
627
    guest_epilogue(lev->scheduling_level,p);
628
 
629
  proc_table[p].status = RMSTAR_READY;
630
}
631
 
632
static void RMSTAR_guest_activate(LEVEL l, PID p)
633
{
634
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
635
 
636
  /* Insert task in the correct position */
637
  iq_priority_insert(p,&lev->ready);
638
  proc_table[p].status = RMSTAR_READY;
639
 
640
  /* check for preemption */
641
  RMSTAR_check_preemption(lev);
642
 
643
  /* Set the deadline timer */
644
  if (!(lev->flag[p] & RMSTAR_FLAG_NORAISEEXC))
645
    lev->deadline_timer[p] = kern_event_post(iq_query_timespec(p, &lev->ready),
646
                                             RMSTAR_timer_guest_deadline,
647
                                             (void *)p);
648
 
649
}
650
 
651
static void RMSTAR_guest_insert(LEVEL l, PID p)
652
{
653
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
654
 
655
  /* Insert task in the correct position */
656
  iq_priority_insert(p,&lev->ready);
657
  proc_table[p].status = RMSTAR_READY;
658
 
659
  /* and check for preemption! */
660
  RMSTAR_check_preemption(lev);
661
}
662
 
663
static void RMSTAR_guest_extract(LEVEL l, PID p)
664
{
665
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
666
 
667
  /* the task is blocked on a synchronization primitive. we have to
668
     remove it from the master module -and- from the local queue! */
669
  iq_extract(p,&lev->ready);
670
 
671
  /* and finally, a preemption check! (it will also call guest_end() */
672
  RMSTAR_check_preemption(lev);
673
}
674
 
675
static void RMSTAR_guest_end(LEVEL l, PID p)
676
{
677
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
678
 
679
#ifdef RMSTAR_DEBUG
680
  //kern_printf("RMSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
681
#endif
682
 
683
  iq_extract(p, &lev->ready);
684
 
685
  /* we remove the deadline timer, because the slice is finished */
686
  if (lev->deadline_timer[p] != NIL) {
687
#ifdef RMSTAR_DEBUG
688
//    kern_printf("RMSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
689
#endif
690
    event_delete(lev->deadline_timer[p]);
691
    lev->deadline_timer[p] = NIL;
692
  }
693
 
694
  /* and finally, a preemption check! (it will also call guest_end() */
695
  RMSTAR_check_preemption(lev);
696
}
697
 
698
static void RMSTAR_guest_endcycle(LEVEL l, PID p)
1100 pj 699
{ kern_raise(XINVALID_GUEST,exec_shadow); }
1089 pj 700
 
701
static void RMSTAR_guest_sleep(LEVEL l, PID p)
1100 pj 702
{ kern_raise(XINVALID_GUEST,exec_shadow); }
1089 pj 703
 
704
static void RMSTAR_guest_delay(LEVEL l, PID p, TIME usdelay)
1100 pj 705
{ kern_raise(XINVALID_GUEST,exec_shadow); }
1089 pj 706
 
707
/* Registration functions */
708
 
709
/* Registration function:
710
    int flags                 the init flags ... see RMSTAR.h */
711
LEVEL RMSTAR_register_level(int budget, int master)
712
{
713
  LEVEL l;            /* the level that we register */
714
  RMSTAR_level_des *lev;  /* for readableness only */
715
  PID i;              /* a counter */
716
 
717
#ifdef RMSTAR_DEBUG
718
  printk("RMSTAR_register_level\n");
719
#endif
720
 
721
  /* request an entry in the level_table */
722
  l = level_alloc_descriptor();
723
 
724
#ifdef RMSTAR_DEBUG
725
  printk("    alloco descrittore %d %d\n",l,(int)sizeof(RMSTAR_level_des));
726
#endif
727
 
728
  /* alloc the space needed for the RMSTAR_level_des */
729
  lev = (RMSTAR_level_des *)kern_alloc(sizeof(RMSTAR_level_des));
730
 
731
#ifdef RMSTAR_DEBUG
732
  printk("    lev=%d\n",(int)lev);
733
#endif
734
 
735
  /* update the level_table with the new entry */
736
  level_table[l] = (level_des *)lev;
737
 
738
  /* fill the standard descriptor */
739
  strncpy(lev->l.level_name,  RMSTAR_LEVELNAME, MAX_LEVELNAME);
740
  lev->l.level_code               = RMSTAR_LEVEL_CODE;
741
  lev->l.level_version            = RMSTAR_LEVEL_VERSION;
742
 
743
  lev->l.level_accept_task_model  = RMSTAR_level_accept_task_model;
744
  lev->l.level_accept_guest_model = RMSTAR_level_accept_guest_model;
745
  lev->l.level_status             = RMSTAR_level_status;
746
  lev->l.level_scheduler          = RMSTAR_level_scheduler;
747
  lev->l.level_guarantee          = NULL;
748
  lev->l.task_create              = RMSTAR_task_create;
749
  lev->l.task_detach              = RMSTAR_task_detach;
750
  lev->l.task_eligible            = RMSTAR_task_eligible;
751
  lev->l.task_dispatch            = RMSTAR_task_dispatch;
752
  lev->l.task_epilogue            = RMSTAR_task_epilogue;
753
  lev->l.task_activate            = RMSTAR_task_activate;
754
  lev->l.task_insert              = RMSTAR_task_insert;
755
  lev->l.task_extract             = RMSTAR_task_extract;
756
  lev->l.task_endcycle            = RMSTAR_task_endcycle;
757
  lev->l.task_end                 = RMSTAR_task_end;
758
  lev->l.task_sleep               = RMSTAR_task_sleep;
759
  lev->l.task_delay               = RMSTAR_task_delay;
760
 
761
  lev->l.guest_create             = RMSTAR_guest_create;
762
  lev->l.guest_detach             = RMSTAR_guest_detach;
763
  lev->l.guest_dispatch           = RMSTAR_guest_dispatch;
764
  lev->l.guest_epilogue           = RMSTAR_guest_epilogue;
765
  lev->l.guest_activate           = RMSTAR_guest_activate;
766
  lev->l.guest_insert             = RMSTAR_guest_insert;
767
  lev->l.guest_extract            = RMSTAR_guest_extract;
768
  lev->l.guest_endcycle           = RMSTAR_guest_endcycle;
769
  lev->l.guest_end                = RMSTAR_guest_end;
770
  lev->l.guest_sleep              = RMSTAR_guest_sleep;
771
  lev->l.guest_delay              = RMSTAR_guest_delay;
772
 
773
  /* fill the RMSTAR descriptor part */
774
  for(i=0; i<MAX_PROC; i++) {
775
    lev->period[i]         = 0;
776
    lev->deadline_timer[i] = -1;
777
    lev->flag[i]           = 0;
778
    lev->dline_miss[i]     = 0;
779
    lev->wcet_miss[i]      = 0;
780
    lev->nact[i]           = 0;
781
  }
782
 
783
  iq_init(&lev->ready, NULL, 0);
784
  lev->activated = NIL;
785
 
786
  lev->budget = budget;
787
  lev->scheduling_level = master;
788
 
789
  return l;
790
}
791
 
792
int RMSTAR_get_dline_miss(PID p)
793
{
794
  LEVEL l = proc_table[p].task_level;
795
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
796
  if (lev->l.level_code    == RMSTAR_LEVEL_CODE &&
797
      lev->l.level_version == RMSTAR_LEVEL_VERSION)
798
    return lev->dline_miss[p];
799
  else
800
    return -1;
801
}
802
 
803
int RMSTAR_get_wcet_miss(PID p)
804
{
805
  LEVEL l = proc_table[p].task_level;
806
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
807
  if (lev->l.level_code    == RMSTAR_LEVEL_CODE &&
808
      lev->l.level_version == RMSTAR_LEVEL_VERSION)
809
    return lev->wcet_miss[p];
810
  else
811
    return -1;
812
}
813
 
814
int RMSTAR_get_nact(PID p)
815
{
816
  LEVEL l = proc_table[p].task_level;
817
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
818
  if (lev->l.level_code    == RMSTAR_LEVEL_CODE &&
819
      lev->l.level_version == RMSTAR_LEVEL_VERSION)
820
    return lev->nact[p];
821
  else
822
    return -1;
823
}
824
 
825
int RMSTAR_reset_dline_miss(PID p)
826
{
827
  LEVEL l = proc_table[p].task_level;
828
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
829
  if (lev->l.level_code    == RMSTAR_LEVEL_CODE &&
830
      lev->l.level_version == RMSTAR_LEVEL_VERSION)
831
  {
832
    lev->dline_miss[p] = 0;
833
    return 0;
834
  }
835
  else
836
    return -1;
837
}
838
 
839
int RMSTAR_reset_wcet_miss(PID p)
840
{
841
  LEVEL l = proc_table[p].task_level;
842
  RMSTAR_level_des *lev = (RMSTAR_level_des *)(level_table[l]);
843
  if (lev->l.level_code    == RMSTAR_LEVEL_CODE &&
844
      lev->l.level_version == RMSTAR_LEVEL_VERSION)
845
  {
846
    lev->wcet_miss[p] = 0;
847
    return 0;
848
  }
849
  else
850
    return -1;
851
}
852