Subversion Repositories shark

Rev

Rev 14 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 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
 *   Massimiliano Giorgi <massy@gandalf.sssup.it>
11
 *   Luca Abeni          <luca@gandalf.sssup.it>
12
 *   (see the web pages for full authors list)
13
 *
14
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
15
 *
16
 * http://www.sssup.it
17
 * http://retis.sssup.it
18
 * http://shark.sssup.it
19
 */
20
 
21
/**
22
 ------------
29 pj 23
 CVS :        $Id: ps.c,v 1.3 2002-11-11 08:32:06 pj Exp $
2 pj 24
 
25
 File:        $File$
29 pj 26
 Revision:    $Revision: 1.3 $
27
 Last update: $Date: 2002-11-11 08:32:06 $
2 pj 28
 ------------
29
 
30
 This file contains the aperiodic server PS (Polling Server)
31
 
32
 when scheduling in background  the flags field has the PS_BACKGROUND bit set
33
 
34
 when scheduling a task because it is pointed by another task via shadows,
35
 the task have to be extracted from the wait queue or the master level. To
36
 check this we have to look at the activated field; it is != NIL if a task
37
 is inserted into the master level. Only a task at a time can be inserted
38
 into the master level.
39
 
40
 The capacity of the server must be updated
41
 - when scheduling a task normally
42
 - when scheduling a task because it is pointed by a shadow
43
 but not when scheduling in background.
44
 
45
 When a task is extracted from the system no scheduling has to be done
46
 until the task reenter into the system. to implement this, when a task
47
 is extracted we block the background scheduling (the scheduling with the
48
 master level is already blocked because the activated field is not
49
 reset to NIL) using the PS_BACKGROUNDBLOCK bit.
50
 
51
 nact[p] is -1 if the task set the activations to SKIP, >= 0 otherwise
52
 
53
 Note that if the period event fires and there aren't any task to schedule,
54
 the server capacity is set to 0. This is correct, but there is a subtle
55
 variant: the server capacity may be set to 0 later because if at the
56
 period end the running task have priority > than the server, the capacity
57
 may be set to zero the first time the server become the highest priority
58
 running task and there aren't task to serve. The second implementation
59
 is more efficient but more complicated, because normally we don't know the
60
 priority of the running task.
61
 
62
 An implementation can be done in this way: when there are not task to
63
 schedule, we does not set the lev->activated field to nil, but to a "dummy"
64
 task that is inserted into the master level queue.
65
 When the master level scheduler try to schedule the "dummy" task (this is
66
 the situation in witch there are not task to schedule and the PS is the
67
 task with greater priority), it calls the PS_task_eligible, that set the
68
 server capacity to 0, remove the dummy task from the queue with a guest_end
69
 and ask to reschedule.
70
 
71
 Because this implementation is more complex than the first, I don't
72
 implement it... see (*), near line 169, 497 and 524
73
 
74
 
75
 Read PS.h for further details.
76
 
77
**/
78
 
79
/*
80
 * Copyright (C) 2000 Paolo Gai
81
 *
82
 * This program is free software; you can redistribute it and/or modify
83
 * it under the terms of the GNU General Public License as published by
84
 * the Free Software Foundation; either version 2 of the License, or
85
 * (at your option) any later version.
86
 *
87
 * This program is distributed in the hope that it will be useful,
88
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
89
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
90
 * GNU General Public License for more details.
91
 *
92
 * You should have received a copy of the GNU General Public License
93
 * along with this program; if not, write to the Free Software
94
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
95
 *
96
 */
97
 
98
 
99
#include <modules/ps.h>
100
#include <ll/stdio.h>
101
#include <ll/string.h>
102
#include <kernel/model.h>
103
#include <kernel/descr.h>
104
#include <kernel/var.h>
105
#include <kernel/func.h>
106
 
107
/*+ Status used in the level +*/
108
#define PS_WAIT          APER_STATUS_BASE    /*+ waiting the service   +*/
109
 
110
/*+ the level redefinition for the Total Bandwidth Server level +*/
111
typedef struct {
112
  level_des l;     /*+ the standard level descriptor          +*/
113
 
114
  /* The wcet are stored in the task descriptor's priority
115
     field, so no other fields are needed                      */
116
 
117
  int nact[MAX_PROC]; /*+ number of pending activations       +*/
118
 
119
  struct timespec lastdline; /*+ the last deadline assigned to
120
                                 a PS task                    +*/
121
 
122
  int Cs;          /*+ server capacity                        +*/
123
  int availCs;     /*+ server avail time                      +*/
124
 
29 pj 125
  IQUEUE wait;      /*+ the wait queue of the PS              +*/
2 pj 126
  PID activated;   /*+ the task inserted in another queue     +*/
127
 
128
  int flags;       /*+ the init flags...                      +*/
129
 
130
  bandwidth_t U;   /*+ the used bandwidth by the server       +*/
131
  int period;
132
 
133
  LEVEL scheduling_level;
134
 
135
} PS_level_des;
136
 
137
/* This static function activates the task pointed by lev->activated) */
138
static __inline__ void PS_activation(PS_level_des *lev)
139
{
140
    PID p;                     /* for readableness    */
141
    JOB_TASK_MODEL j;          /* the guest model     */
142
    LEVEL m;                   /* the master level... only for readableness*/
143
 
144
    p = lev->activated;
145
    m = lev->scheduling_level;
146
    job_task_default_model(j,lev->lastdline);
147
    job_task_def_period(j,lev->period);
148
    level_table[m]->guest_create(m,p,(TASK_MODEL *)&j);
149
    level_table[m]->guest_activate(m,p);
150
//    kern_printf("(%d %d)",lev->lastdline.tv_sec,lev->lastdline.tv_nsec);
151
}
152
 
153
static void PS_deadline_timer(void *a)
154
{
155
  PS_level_des *lev = (PS_level_des *)(level_table[(LEVEL)a]);
156
 
157
  ADDUSEC2TIMESPEC(lev->period, &lev->lastdline);
158
 
159
//  kern_printf("(%d:%d %d)",lev->lastdline.tv_sec,lev->lastdline.tv_nsec, lev->period);
160
  if (lev->availCs >= 0)
161
    lev->availCs = lev->Cs;
162
  else
163
    lev->availCs += lev->Cs;
164
 
165
  /* availCs may be <0 because a task executed via a shadow fo many time
166
     lev->activated == NIL only if the prec task was finished and there
167
     was not any other task to be put in the ready queue
168
     ... we are now activating the next task */
169
  if (lev->availCs > 0 && lev->activated == NIL) {
29 pj 170
      if (iq_query_first(&lev->wait) != NIL) {
171
        lev->activated = iq_getfirst(&lev->wait);
2 pj 172
        PS_activation(lev);
173
        event_need_reschedule();
174
      }
175
      else
176
        lev->availCs = 0; /* see note (*) at the begin of the file */
177
  }
178
 
179
  kern_event_post(&lev->lastdline, PS_deadline_timer, a);
180
//  kern_printf("!");
181
}
182
 
183
static char *PS_status_to_a(WORD status)
184
{
185
  if (status < MODULE_STATUS_BASE)
186
    return status_to_a(status);
187
 
188
  switch (status) {
189
    case PS_WAIT         : return "PS_Wait";
190
    default              : return "PS_Unknown";
191
  }
192
}
193
 
194
 
195
static int PS_level_accept_task_model(LEVEL l, TASK_MODEL *m)
196
{
197
  if (m->pclass == SOFT_PCLASS || m->pclass == (SOFT_PCLASS | l) ) {
198
    SOFT_TASK_MODEL *s = (SOFT_TASK_MODEL *)m;
199
 
200
    if (s->periodicity == APERIODIC)
201
      return 0;
202
  }
203
  return -1;
204
}
205
 
206
static int PS_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
207
{
208
  return -1;
209
}
210
 
211
static char *onoff(int i)
212
{
213
  if (i)
214
    return "On ";
215
  else
216
    return "Off";
217
}
218
 
219
static void PS_level_status(LEVEL l)
220
{
221
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
29 pj 222
  PID p = iq_query_first(&lev->wait);
2 pj 223
 
224
  kern_printf("On-line guarantee : %s\n",
225
            onoff(lev->flags & PS_ENABLE_GUARANTEE_EDF ||
226
                  lev->flags & PS_ENABLE_GUARANTEE_RM  ));
227
  kern_printf("Used Bandwidth    : %u/%u\n",
228
            lev->U, MAX_BANDWIDTH);
229
 
230
  if (lev->activated != -1)
231
    kern_printf("Activated: Pid: %2d Name: %10s Dl: %ld.%ld Nact: %d Stat: %s\n",
232
              lev->activated,
233
              proc_table[lev->activated].name,
29 pj 234
              iq_query_timespec(lev->activated,&lev->wait)->tv_sec,
235
              iq_query_timespec(lev->activated,&lev->wait)->tv_nsec,
2 pj 236
              lev->nact[lev->activated],
237
              PS_status_to_a(proc_table[lev->activated].status));
238
 
239
  while (p != NIL) {
240
    kern_printf("Pid: %2d Name: %10s Stat: %s\n",
241
              p,
242
              proc_table[p].name,
243
              PS_status_to_a(proc_table[p].status));
29 pj 244
    p = iq_query_next(p, &lev->wait);
2 pj 245
  }
246
}
247
 
248
static PID PS_level_scheduler(LEVEL l)
249
{
250
  /* the PS don't schedule anything...
251
     it's an EDF level or similar that do it! */
252
  return NIL;
253
}
254
 
255
static PID PS_level_schedulerbackground(LEVEL l)
256
{
257
  /* the PS catch the background time to exec aperiodic activities */
258
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
259
 
260
  lev->flags |= PS_BACKGROUND;
261
 
262
  if (lev->flags & PS_BACKGROUND_BLOCK)
263
    return NIL;
264
  else
29 pj 265
    return iq_query_first(&lev->wait);
2 pj 266
}
267
 
268
/* The on-line guarantee is enabled only if the appropriate flag is set... */
269
static int PS_level_guaranteeEDF(LEVEL l, bandwidth_t *freebandwidth)
270
{
271
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
272
 
273
  if (*freebandwidth >= lev->U) {
274
    *freebandwidth -= lev->U;
275
    return 1;
276
  }
277
  else
278
    return 0;
279
}
280
 
281
static int PS_level_guaranteeRM(LEVEL l, bandwidth_t *freebandwidth)
282
{
283
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
284
 
285
  if (*freebandwidth > lev->U + RM_MINFREEBANDWIDTH) {
286
    *freebandwidth -= lev->U;
287
    return 1;
288
  }
289
  else
290
    return 0;
291
}
292
 
293
static int PS_task_create(LEVEL l, PID p, TASK_MODEL *m)
294
{
295
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
296
 
297
  /* if the PS_task_create is called, then the pclass must be a
298
     valid pclass. */
299
  SOFT_TASK_MODEL *s = (SOFT_TASK_MODEL *)m;
300
 
301
  if (s->arrivals == SAVE_ARRIVALS)
302
    lev->nact[p] = 0;
303
  else
304
    lev->nact[p] = -1;
305
 
306
  return 0; /* OK, also if the task cannot be guaranteed... */
307
}
308
 
309
static void PS_task_detach(LEVEL l, PID p)
310
{
311
  /* the PS level doesn't introduce any dinamic allocated new field. */
312
}
313
 
314
static int PS_task_eligible(LEVEL l, PID p)
315
{
316
  return 0; /* if the task p is chosen, it is always eligible */
317
}
318
 
319
static void PS_task_dispatch(LEVEL l, PID p, int nostop)
320
{
321
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
322
  struct timespec ty;
323
 
324
//  if (nostop) kern_printf("NOSTOP!!!!!!!!!!!!");
325
  /* there is at least one task ready inserted in an EDF or similar
326
     level note that we can't check the status because the scheduler set it
327
     to exe before calling task_dispatch. we have to check
328
     lev->activated != p instead */
329
  if (lev->activated != p) {
29 pj 330
    iq_extract(p, &lev->wait);
2 pj 331
    //kern_printf("#%d#",p);
332
  }
333
  else {
334
    //if (nostop) kern_printf("(gd status=%d)",proc_table[p].status);
335
    level_table[ lev->scheduling_level ]->
336
      guest_dispatch(lev->scheduling_level,p,nostop);
337
  }
338
 
339
  /* set the capacity timer */
340
  if (!nostop) {
341
    TIMESPEC_ASSIGN(&ty, &schedule_time);
342
    ADDUSEC2TIMESPEC(lev->availCs,&ty);
343
    cap_timer = kern_event_post(&ty, capacity_timer, NULL);
344
  }
345
 
346
//  kern_printf("(disp %d %d)",ty.tv_sec, ty.tv_nsec);
347
}
348
 
349
static void PS_task_epilogue(LEVEL l, PID p)
350
{
351
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
352
  struct timespec ty;
353
  TIME tx;
354
 
355
  /* update the server capacity */
356
  if (lev->flags & PS_BACKGROUND)
357
    lev->flags &= ~PS_BACKGROUND;
358
  else {
359
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
360
    tx = TIMESPEC2USEC(&ty);
361
    lev->availCs -= tx;
362
  }
363
 
364
//  kern_printf("(epil %d %d)",lev->availCs, proc_table[p].avail_time);
365
 
366
  /* check if the server capacity is finished... */
367
  if (lev->availCs < 0) {
368
//    kern_printf("(epil Cs%d %d:%d act%d p%d)",
369
//              lev->availCs,proc_table[p].timespec_priority.tv_sec,
370
//              proc_table[p].timespec_priority.tv_nsec,
371
//              lev->activated,p);
372
    /* the server slice has finished... do the task_end!!!
373
       a first version of the module used the task_endcycle, but it was
374
       not conceptually correct because the task didn't stop because it
375
       finished all the work but because the server didn't have budget!
376
       So, if the task_endcycle is called, the task remain into the
377
       master level, and we can't wake him up if, for example, another
378
       task point the shadow to it!!!*/
379
    if (lev->activated == p)
380
      level_table[ lev->scheduling_level ]->
381
        guest_end(lev->scheduling_level,p);
29 pj 382
    iq_insertfirst(p, &lev->wait);
2 pj 383
    proc_table[p].status = PS_WAIT;
384
    lev->activated = NIL;
385
  }
386
  else
387
    /* the task has been preempted. it returns into the ready queue or to the
388
       wait queue by calling the guest_epilogue... */
389
    if (lev->activated == p) {//kern_printf("Û1");
390
      level_table[ lev->scheduling_level ]->
391
        guest_epilogue(lev->scheduling_level,p);
392
    } else { //kern_printf("Û2");
29 pj 393
      iq_insertfirst(p, &lev->wait);
2 pj 394
      proc_table[p].status = PS_WAIT;
395
    }
396
}
397
 
398
static void PS_task_activate(LEVEL l, PID p)
399
{
400
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
401
 
402
  if (lev->activated == p || proc_table[p].status == PS_WAIT) {
403
    if (lev->nact[p] != -1)
404
      lev->nact[p]++;
405
  }
406
  else if (proc_table[p].status == SLEEP) {
407
    ll_gettime(TIME_EXACT, &proc_table[p].request_time);
408
 
409
    if (lev->activated == NIL && lev->availCs > 0) {
410
      lev->activated = p;
411
      PS_activation(lev);
412
    }
413
    else {
29 pj 414
      iq_insertlast(p, &lev->wait);
2 pj 415
      proc_table[p].status = PS_WAIT;
416
    }
417
  }
418
  else
419
  {  kern_printf("PS_REJ%d %d %d %d ",p, proc_table[p].status, lev->activated, lev->wait.first);
420
     return; }
421
 
422
}
423
 
424
static void PS_task_insert(LEVEL l, PID p)
425
{
426
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
427
 
428
  lev->flags &= ~PS_BACKGROUND_BLOCK;
429
 
430
  lev->activated = -1;
431
 
432
  /* when we reinsert the task into the system, the server capacity
433
     is always 0 because nobody executes with the PS before... */
29 pj 434
  iq_insertfirst(p, &lev->wait);
2 pj 435
  proc_table[p].status = PS_WAIT;
436
}
437
 
438
static void PS_task_extract(LEVEL l, PID p)
439
{
440
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
441
 
442
  /* update the server capacity */
443
  lev->availCs = 0;
444
 
445
  lev->flags |= PS_BACKGROUND_BLOCK;
446
 
447
  if (lev->activated == p)
448
    level_table[ lev->scheduling_level ]->
449
      guest_end(lev->scheduling_level,p);
450
}
451
 
452
static void PS_task_endcycle(LEVEL l, PID p)
453
{
454
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
455
  struct timespec ty;
456
  TIME tx;
457
 
458
  /* update the server capacity */
459
  if (lev->flags & PS_BACKGROUND)
460
    lev->flags &= ~PS_BACKGROUND;
461
  else {
462
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
463
    tx = TIMESPEC2USEC(&ty);
464
    lev->availCs -= tx;
465
  }
466
 
467
  if (lev->activated == p)
468
    level_table[ lev->scheduling_level ]->
469
      guest_end(lev->scheduling_level,p);
470
  else
29 pj 471
    iq_extract(p, &lev->wait);
2 pj 472
 
473
  if (lev->nact[p] > 0)
474
  {
475
    lev->nact[p]--;
29 pj 476
    iq_insertlast(p, &lev->wait);
2 pj 477
    proc_table[p].status = PS_WAIT;
478
  }
479
  else
480
    proc_table[p].status = SLEEP;
481
 
29 pj 482
  lev->activated = iq_getfirst(&lev->wait);
2 pj 483
  if (lev->activated == NIL)
484
    lev->availCs = 0; /* see note (*) at the begin of the file */
485
  else
486
    PS_activation(lev);
487
}
488
 
489
static void PS_task_end(LEVEL l, PID p)
490
{
491
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
492
  struct timespec ty;
493
  TIME tx;
494
 
495
  /* update the server capacity */
496
  if (lev->flags & PS_BACKGROUND)
497
    lev->flags &= ~PS_BACKGROUND;
498
  else {
499
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
500
    tx = TIMESPEC2USEC(&ty);
501
    lev->availCs -= tx;
502
  }
503
 
504
  if (lev->activated == p)
505
    level_table[ lev->scheduling_level ]->
506
      guest_end(lev->scheduling_level,p);
507
 
508
  proc_table[p].status = FREE;
29 pj 509
  iq_insertfirst(p,&freedesc);
2 pj 510
 
29 pj 511
  lev->activated = iq_getfirst(&lev->wait);
2 pj 512
  if (lev->activated == NIL)
513
    lev->availCs = 0; /* see note (*) at the begin of the file */
514
  else
515
    PS_activation(lev);
516
}
517
 
518
static void PS_task_sleep(LEVEL l, PID p)
519
{
520
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
521
  struct timespec ty;
522
  TIME tx;
523
 
524
  /* update the server capacity */
525
  if (lev->flags & PS_BACKGROUND)
526
    lev->flags &= ~PS_BACKGROUND;
527
  else {
528
    SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
529
    tx = TIMESPEC2USEC(&ty);
530
    lev->availCs -= tx;
531
  }
532
 
533
  if (lev->nact[p] >= 0) lev->nact[p] = 0;
534
 
535
  if (lev->activated == p)
536
    level_table[ lev->scheduling_level ]->
537
      guest_end(lev->scheduling_level,p);
538
  else
29 pj 539
    iq_extract(p, &lev->wait);
2 pj 540
 
541
  proc_table[p].status = SLEEP;
542
 
29 pj 543
  lev->activated = iq_getfirst(&lev->wait);
2 pj 544
  if (lev->activated == NIL)
545
    lev->availCs = 0; /* see note (*) at the begin of the file */
546
  else
547
    PS_activation(lev);
548
}
549
 
550
 
551
static int PS_guest_create(LEVEL l, PID p, TASK_MODEL *m)
14 pj 552
{ kern_raise(XINVALID_GUEST,exec_shadow); return 0; }
2 pj 553
 
554
static void PS_guest_detach(LEVEL l, PID p)
14 pj 555
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 556
 
557
static void PS_guest_dispatch(LEVEL l, PID p, int nostop)
14 pj 558
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 559
 
560
static void PS_guest_epilogue(LEVEL l, PID p)
14 pj 561
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 562
 
563
static void PS_guest_activate(LEVEL l, PID p)
14 pj 564
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 565
 
566
static void PS_guest_insert(LEVEL l, PID p)
14 pj 567
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 568
 
569
static void PS_guest_extract(LEVEL l, PID p)
14 pj 570
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 571
 
572
static void PS_guest_endcycle(LEVEL l, PID p)
14 pj 573
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 574
 
575
static void PS_guest_end(LEVEL l, PID p)
14 pj 576
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 577
 
578
static void PS_guest_sleep(LEVEL l, PID p)
14 pj 579
{ kern_raise(XINVALID_GUEST,exec_shadow); }
2 pj 580
 
581
 
582
 
583
 
584
/* Registration functions */
585
 
586
 
587
/*+ This init function install the PS deadline timer
588
    +*/
589
static void PS_dline_install(void *l)
590
{
591
  PS_level_des *lev = (PS_level_des *)(level_table[(LEVEL)l]);
592
 
593
  ll_gettime(TIME_EXACT,&lev->lastdline);
594
  ADDUSEC2TIMESPEC(lev->period, &lev->lastdline);
595
 
596
  kern_event_post(&lev->lastdline, PS_deadline_timer, l);
597
}
598
 
599
 
600
 
601
/*+ Registration function:
602
    int flags                 the init flags ... see PS.h +*/
603
void PS_register_level(int flags, LEVEL master, int Cs, int per)
604
{
605
  LEVEL l;            /* the level that we register */
606
  PS_level_des *lev;  /* for readableness only */
607
  PID i;              /* a counter */
608
 
609
  printk("PS_register_level\n");
610
 
611
  /* request an entry in the level_table */
612
  l = level_alloc_descriptor();
613
 
614
  printk("    alloco descrittore %d %d\n",l,(int)sizeof(PS_level_des));
615
 
616
  /* alloc the space needed for the PS_level_des */
617
  lev = (PS_level_des *)kern_alloc(sizeof(PS_level_des));
618
 
619
  printk("    lev=%d\n",(int)lev);
620
 
621
  /* update the level_table with the new entry */
622
  level_table[l] = (level_des *)lev;
623
 
624
  /* fill the standard descriptor */
625
  strncpy(lev->l.level_name,  PS_LEVELNAME, MAX_LEVELNAME);
626
  lev->l.level_code               = PS_LEVEL_CODE;
627
  lev->l.level_version            = PS_LEVEL_VERSION;
628
 
629
  lev->l.level_accept_task_model  = PS_level_accept_task_model;
630
  lev->l.level_accept_guest_model = PS_level_accept_guest_model;
631
  lev->l.level_status             = PS_level_status;
632
 
633
  if (flags & PS_ENABLE_BACKGROUND)
634
    lev->l.level_scheduler          = PS_level_schedulerbackground;
635
  else
636
    lev->l.level_scheduler          = PS_level_scheduler;
637
 
638
  if (flags & PS_ENABLE_GUARANTEE_EDF)
639
    lev->l.level_guarantee        = PS_level_guaranteeEDF;
640
  else if (flags & PS_ENABLE_GUARANTEE_RM)
641
    lev->l.level_guarantee        = PS_level_guaranteeRM;
642
  else
643
    lev->l.level_guarantee        = NULL;
644
 
645
  lev->l.task_create              = PS_task_create;
646
  lev->l.task_detach              = PS_task_detach;
647
  lev->l.task_eligible            = PS_task_eligible;
648
  lev->l.task_dispatch            = PS_task_dispatch;
649
  lev->l.task_epilogue            = PS_task_epilogue;
650
  lev->l.task_activate            = PS_task_activate;
651
  lev->l.task_insert              = PS_task_insert;
652
  lev->l.task_extract             = PS_task_extract;
653
  lev->l.task_endcycle            = PS_task_endcycle;
654
  lev->l.task_end                 = PS_task_end;
655
  lev->l.task_sleep               = PS_task_sleep;
656
 
657
  lev->l.guest_create             = PS_guest_create;
658
  lev->l.guest_detach             = PS_guest_detach;
659
  lev->l.guest_dispatch           = PS_guest_dispatch;
660
  lev->l.guest_epilogue           = PS_guest_epilogue;
661
  lev->l.guest_activate           = PS_guest_activate;
662
  lev->l.guest_insert             = PS_guest_insert;
663
  lev->l.guest_extract            = PS_guest_extract;
664
  lev->l.guest_endcycle           = PS_guest_endcycle;
665
  lev->l.guest_end                = PS_guest_end;
666
  lev->l.guest_sleep              = PS_guest_sleep;
667
 
668
  /* fill the PS descriptor part */
669
 
670
  for (i=0; i<MAX_PROC; i++)
671
     lev->nact[i] = -1;
672
 
673
  lev->Cs = Cs;
674
  lev->availCs = 0;
675
 
676
  lev->period = per;
677
 
29 pj 678
  iq_init(&lev->wait, &freedesc, 0);
2 pj 679
  lev->activated = NIL;
680
 
681
  lev->U = (MAX_BANDWIDTH / per) * Cs;
682
 
683
  lev->scheduling_level = master;
684
 
685
  lev->flags = flags & 0x07;
686
 
687
  sys_atrunlevel(PS_dline_install,(void *) l, RUNLEVEL_INIT);
688
}
689
 
690
bandwidth_t PS_usedbandwidth(LEVEL l)
691
{
692
  PS_level_des *lev = (PS_level_des *)(level_table[l]);
693
  if (lev->l.level_code    == PS_LEVEL_CODE &&
694
      lev->l.level_version == PS_LEVEL_VERSION)
695
    return lev->U;
696
  else
697
    return 0;
698
}
699