Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1663 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
 ------------
23
 CVS :        $Id: rrvalue.c,v 1.1 2004-07-05 14:17:13 pj Exp $
24
 
25
 File:        $File$
26
 Revision:    $Revision: 1.1 $
27
 Last update: $Date: 2004-07-05 14:17:13 $
28
 ------------
29
 
30
 This file contains the scheduling module RRVALUE (Round Robin)
31
 
32
 Read rrvalue.h for further details.
33
 
34
**/
35
 
36
/*
37
 * Copyright (C) 2001 Paolo Gai
38
 *
39
 * This program is free software; you can redistribute it and/or modify
40
 * it under the terms of the GNU General Public License as published by
41
 * the Free Software Foundation; either version 2 of the License, or
42
 * (at your option) any later version.
43
 *
44
 * This program is distributed in the hope that it will be useful,
45
 * but WITHOUT ANY WARRSOFTANTY; without even the implied waRRSOFTanty of
46
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
47
 * GNU General Public License for more details.
48
 *
49
 * You should have received a copy of the GNU General Public License
50
 * along with this program; if not, write to the Free Software
51
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
52
 *
53
 */
54
 
55
 
56
#include "rrvalue.h"
57
#include <ll/stdio.h>
58
#include <ll/string.h>
59
#include <kernel/model.h>
60
#include <kernel/descr.h>
61
#include <kernel/var.h>
62
#include <kernel/func.h>
63
 
64
/*+ Status used in the level +*/
65
#define RRVALUE_READY   MODULE_STATUS_BASE
66
#define RRVALUE_DELAY   MODULE_STATUS_BASE+1
67
#define RRVALUE_IDLE    MODULE_STATUS_BASE+2
68
 
69
/*+ the level redefinition for the Round Robin level +*/
70
typedef struct {
71
  level_des l;     /*+ the standard level descriptor          +*/
72
 
73
  int nact[MAX_PROC]; /*+ number of pending activations       +*/
74
 
75
  QQUEUE ready;    /*+ the ready queue                        +*/
76
 
77
  int slice;       /*+ the level's time slice                 +*/
78
 
79
  TIME period[MAX_PROC]; /*+  activation period (reldlines for value tasks)+*/
80
 
81
  struct timespec reactivation_time[MAX_PROC];
82
        /*+ the time at witch  the reactivation timer is post,
83
            absdlines for value tasks +*/
84
  int reactivation_timer[MAX_PROC];
85
                                   /*+ the recativation timer +*/
86
 
87
  BYTE periodic[MAX_PROC];
88
 
89
 
90
  struct multiboot_info *multiboot; /*+ used if the level have to insert
91
                                        the main task +*/
92
 
93
  BYTE models;      /*+ Task Model that the Module can Handle +*/
94
 
95
  int totalvalue;
96
  int value[MAX_PROC];
97
  int penalty[MAX_PROC];
98
 
99
  int max_tasks;    /*+ Max number of tasks that the level can afford +*/
100
} RRVALUE_level_des;
101
 
102
 
103
static char *RRVALUE_status_to_a(WORD status)
104
{
105
  if (status < MODULE_STATUS_BASE)
106
    return status_to_a(status);
107
 
108
  switch (status) {
109
    case RRVALUE_READY: return "RRVALUE_Ready";
110
    case RRVALUE_DELAY: return "RRVALUE_Delay";
111
    case RRVALUE_IDLE : return "RRVALUE_Idle";
112
    default      : return "RRVALUE_Unknown";
113
  }
114
}
115
 
116
 
117
/* this is the periodic reactivation of the task... it is posted only
118
   if the task is a periodic task */
119
static void RRVALUE_timer_reactivate(void *par)
120
{
121
  PID p = (PID) par;
122
  RRVALUE_level_des *lev;
123
//  kern_printf("react");
124
 
125
  lev = (RRVALUE_level_des *)level_table[proc_table[p].task_level];
126
 
127
  if (proc_table[p].status == RRVALUE_IDLE) {
128
    /* the task has finished the current activation and must be
129
       reactivated */
130
    TIMESPEC_ASSIGN(&proc_table[p].request_time,
131
                    &lev->reactivation_time[p]);
132
    ll_gettime(TIME_EXACT, &proc_table[p].request_time);
133
    proc_table[p].status = RRVALUE_READY;
134
    qq_insertlast(p,&lev->ready);
135
 
136
    event_need_reschedule();
137
  }
138
  else if (lev->nact[p] >= 0)
139
    /* the task has not completed the current activation, so we save
140
       the activation incrementing nact... */
141
    lev->nact[p]++;
142
 
143
  /* repost the event at the next period end... */
144
  ADDUSEC2TIMESPEC(lev->period[p], &lev->reactivation_time[p]);
145
  lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
146
                                               RRVALUE_timer_reactivate,
147
                                               (void *)p);
148
  /* tracer stuff */
149
//  trc_logevent(TRC_INTACTIVATION,&p);
150
}
151
 
152
 
153
/*+ this function is called when a task finish his delay +*/
154
static void RRVALUE_timer_delay(void *par)
155
{
156
  PID p = (PID) par;
157
  RRVALUE_level_des *lev;
158
 
159
  lev = (RRVALUE_level_des *)level_table[proc_table[p].task_level];
160
 
161
  proc_table[p].status = RRVALUE_READY;
162
  qq_insertlast(p,&lev->ready);
163
 
164
  proc_table[p].delay_timer = NIL;  /* Paranoia */
165
 
166
//  kern_printf(" DELAY TIMER %d ", p);
167
 
168
  event_need_reschedule();
169
}
170
 
171
 
172
static int RRVALUE_level_accept_task_model(LEVEL l, TASK_MODEL *m)
173
{
174
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
175
 
176
  if ((m->pclass == NRT_PCLASS || m->pclass == (NRT_PCLASS | l)) && lev->models & RRVALUE_ONLY_NRT)
177
    return 0;
178
  else if ((m->pclass == SOFT_PCLASS || m->pclass == (SOFT_PCLASS | l)) && lev->models & RRVALUE_ONLY_SOFT)
179
    return 0;
180
  else if ((m->pclass == HARD_PCLASS || m->pclass == (HARD_PCLASS | l)) && lev->models & RRVALUE_ONLY_HARD)
181
    return 0;
182
  else if ((m->pclass == VALUE_PCLASS || m->pclass == (VALUE_PCLASS | l)) && lev->models & RRVALUE_ONLY_VALUE)
183
    return 0;
184
  else
185
    return -1;
186
}
187
 
188
static int RRVALUE_level_accept_guest_model(LEVEL l, TASK_MODEL *m)
189
{
190
    return -1;
191
}
192
 
193
static void RRVALUE_level_status(LEVEL l)
194
{
195
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
196
  PID p = qq_queryfirst(&lev->ready);
197
 
198
  kern_printf("Slice: %d \n", lev->slice);
199
 
200
  while (p != NIL) {
201
    kern_printf("Pid: %d\t Name: %20s Status: %s\n",p,proc_table[p].name,
202
              RRVALUE_status_to_a(proc_table[p].status));
203
    p = proc_table[p].next;
204
  }
205
 
206
  for (p=0; p<MAX_PROC; p++)
207
    if (proc_table[p].task_level == l && proc_table[p].status != RRVALUE_READY
208
        && proc_table[p].status != FREE )
209
      kern_printf("Pid: %d\t Name: %20s Status: %s\n",p,proc_table[p].name,
210
                RRVALUE_status_to_a(proc_table[p].status));
211
 
212
}
213
 
214
 
215
/* This is not efficient but very fair :-)
216
   The need of all this stuff is because if a task execute a long time
217
   due to (shadow!) priority inheritance, then the task shall go to the
218
   tail of the queue many times... */
219
static PID RRVALUE_level_scheduler(LEVEL l)
220
{
221
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
222
 
223
  PID p;
224
 
225
  for (;;) {
226
    p = qq_queryfirst(&lev->ready);
227
    if (p == -1)
228
      return p;
229
//{kern_printf("(s%d)",p);      return p;}
230
 
231
//    kern_printf("(p=%d l=%d avail=%d wcet =%d)\n",p,l,proc_table[p].avail_time, proc_table[p].wcet);
232
    if (proc_table[p].avail_time <= 0) {
233
      proc_table[p].avail_time += proc_table[p].wcet;
234
      qq_extract(p,&lev->ready);
235
      qq_insertlast(p,&lev->ready);
236
    }
237
    else
238
//{kern_printf("(s%d)",p);      return p;}
239
      return p;
240
  }
241
}
242
 
243
static int RRVALUE_level_guarantee(LEVEL l, bandwidth_t *freebandwidth)
244
{
245
  /* the RRVALUE level always guarantee... the function is defined because
246
     there can be an aperiodic server at a level with less priority than
247
     the RRVALUE that need guarantee (e.g., a TBS server) */
248
 
249
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
250
 
251
//  kern_printf("R%d ",lev->max_tasks>0);
252
  return lev->max_tasks > 0;
253
}
254
 
255
 
256
static int RRVALUE_task_create(LEVEL l, PID p, TASK_MODEL *m)
257
{
258
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
259
 
260
//  kern_printf("create %d mod %d\n",p,m->pclass);
261
  /* the task state is set at SLEEP by the general task_create
262
     the only thing to set remains the capacity stuffs that are set
263
     to the values passed in the model... */
264
 
265
  /* I used the wcet field because using wcet can account if a task
266
     consume more than the timeslice... */
267
 
268
  if (lev->models & RRVALUE_ONLY_NRT &&
269
      (m->pclass == NRT_PCLASS || m->pclass == (NRT_PCLASS | l))) {
270
    NRT_TASK_MODEL *nrt = (NRT_TASK_MODEL *)m;
271
 
272
//    kern_printf("nrt");
273
    if (nrt->slice) {
274
      proc_table[p].avail_time = nrt->slice;
275
      proc_table[p].wcet       = nrt->slice;
276
    }
277
    else {
278
      proc_table[p].avail_time = lev->slice;
279
      proc_table[p].wcet       = lev->slice;
280
    }
281
    proc_table[p].control   |= CONTROL_CAP;
282
 
283
    if (nrt->arrivals == SAVE_ARRIVALS)
284
      lev->nact[p] = 0;
285
    else
286
      lev->nact[p] = -1;
287
 
288
    lev->periodic[p] = 0;
289
    lev->period[p] = 0;
290
 
291
    lev->value[p] = 0;
292
    lev->penalty[p] = 0;
293
  }
294
  else if (lev->models & RRVALUE_ONLY_SOFT &&
295
           (m->pclass == SOFT_PCLASS || m->pclass == (SOFT_PCLASS | l))) {
296
    SOFT_TASK_MODEL *soft = (SOFT_TASK_MODEL *)m;
297
//    kern_printf("soft");
298
    proc_table[p].avail_time = lev->slice;
299
    proc_table[p].wcet       = lev->slice;
300
    proc_table[p].control   |= CONTROL_CAP;
301
 
302
    if (soft->arrivals == SAVE_ARRIVALS)
303
      lev->nact[p] = 0;
304
    else
305
      lev->nact[p] = -1;
306
 
307
    if (soft->periodicity == PERIODIC) {
308
      lev->periodic[p] = 1;
309
      lev->period[p] = soft->period;
310
    }
311
    else {
312
      lev->periodic[p] = 0;
313
      lev->period[p] = 0;
314
    }
315
 
316
    lev->value[p] = 0;
317
    lev->penalty[p] = 0;
318
  }
319
  else if (lev->models & RRVALUE_ONLY_HARD &&
320
           (m->pclass == HARD_PCLASS || m->pclass == (HARD_PCLASS | l))) {
321
    HARD_TASK_MODEL *hard = (HARD_TASK_MODEL *)m;
322
//    kern_printf("hard");
323
    proc_table[p].avail_time = lev->slice;
324
    proc_table[p].wcet       = lev->slice;
325
    proc_table[p].control   |= CONTROL_CAP;
326
 
327
    lev->nact[p] = 0;
328
 
329
    if (hard->periodicity == PERIODIC) {
330
      lev->periodic[p] = 1;
331
      lev->period[p] = hard->mit;
332
    }
333
    else {
334
      lev->periodic[p] = 0;
335
      lev->period[p] = 0;
336
    }
337
 
338
    lev->value[p] = 0;
339
    lev->penalty[p] = 0;
340
  }
341
 
342
  if (lev->models & RRVALUE_ONLY_VALUE &&
343
      (m->pclass == VALUE_PCLASS || m->pclass == (VALUE_PCLASS | l))) {
344
    VALUE_TASK_MODEL *v = (VALUE_TASK_MODEL *)m;
345
    proc_table[p].avail_time = lev->slice;
346
    proc_table[p].wcet       = lev->slice;
347
    proc_table[p].control   |= CONTROL_CAP;
348
    lev->nact[p] = -1;
349
    lev->periodic[p] = 0;
350
 
351
    lev->value[p] = v->value;
352
    lev->penalty[p] = v->penalty;
353
    lev->period[p] = v->dline;
354
  }
355
 
356
  lev->max_tasks--;
357
 
358
  return 0; /* OK */
359
}
360
 
361
static void RRVALUE_task_detach(LEVEL l, PID p)
362
{
363
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
364
 
365
  //lev->totalvalue += lev->penalty[p];
366
 
367
  lev->max_tasks++;
368
}
369
 
370
static int RRVALUE_task_eligible(LEVEL l, PID p)
371
{
372
  return 0; /* if the task p is chosen, it is always eligible */
373
}
374
 
375
#ifdef __TEST1__
376
extern int testactive;
377
extern struct timespec s_stime[];
378
extern TIME s_curr[];
379
extern TIME s_PID[];
380
extern int useds;
381
#endif
382
 
383
static void RRVALUE_task_dispatch(LEVEL l, PID p, int nostop)
384
{
385
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
386
  struct timespec t;
387
 
388
  /* the task state is set EXE by the scheduler()
389
     we extract the task from the ready queue
390
     NB: we can't assume that p is the first task in the queue!!! */
391
  qq_extract(p, &lev->ready);
392
 
393
  // kill the task if it already has missed the deadline
394
  t = proc_table[p].request_time;
395
  ADDUSEC2TIMESPEC(lev->period[p],&t);
396
  if (TIMESPEC_A_LT_B(&t,&schedule_time))
397
    proc_table[p].control |= KILL_REQUEST;
398
}
399
 
400
static void RRVALUE_task_epilogue(LEVEL l, PID p)
401
{
402
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
403
 
404
  /* check if the slice is finished and insert the task in the coRRVALUEect
405
     qqueue position */
406
  if (proc_table[p].avail_time <= 0) {
407
    proc_table[p].avail_time += proc_table[p].wcet;
408
    qq_insertlast(p,&lev->ready);
409
    proc_table[p].control |= KILL_REQUEST;
410
  }
411
  else
412
    /* curr is >0, so the running task have to run for another cuRRVALUE usec */
413
    qq_insertfirst(p,&lev->ready);
414
 
415
  proc_table[p].status = RRVALUE_READY;
416
}
417
 
418
static void RRVALUE_task_activate(LEVEL l, PID p)
419
{
420
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
421
 
422
  /* Test if we are trying to activate a non sleeping task    */
423
  /* save activation (only if needed... */
424
  if (proc_table[p].status != SLEEP && proc_table[p].status != RRVALUE_IDLE) {
425
    if (lev->nact[p] != -1)
426
      lev->nact[p]++;
427
    return;
428
  }
429
 
430
  ll_gettime(TIME_EXACT, &proc_table[p].request_time);
431
 
432
  /* Insert task in the coRRVALUEect position */
433
  proc_table[p].status = RRVALUE_READY;
434
  qq_insertlast(p,&lev->ready);
435
 
436
 
437
  /* Set the reactivation timer */
438
  TIMESPEC_ASSIGN(&lev->reactivation_time[p], &proc_table[p].request_time);
439
  ADDUSEC2TIMESPEC(lev->period[p], &lev->reactivation_time[p]);
440
  if (lev->periodic[p])
441
  {
442
    // timespec stuffs moved up for value tasks!
443
    lev->reactivation_timer[p] = kern_event_post(&lev->reactivation_time[p],
444
                                                 RRVALUE_timer_reactivate,
445
                                                 (void *)p);
446
  }
447
}
448
 
449
static void RRVALUE_task_insert(LEVEL l, PID p)
450
{
451
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
452
 
453
  /* Similar to RRVALUE_task_activate, but we don't check in what state
454
     the task is and we don't set the request_time */
455
 
456
  /* Insert task in the coRRVALUEect position */
457
  proc_table[p].status = RRVALUE_READY;
458
  qq_insertlast(p,&lev->ready);
459
}
460
 
461
static void RRVALUE_task_extract(LEVEL l, PID p)
462
{
463
  /* Extract the running task from the level
464
     . we have already extract it from the ready queue at the dispatch time.
465
     . the capacity event have to be removed by the generic kernel
466
     . the wcet don't need modification...
467
     . the state of the task is set by the calling function
468
 
469
     So, we do nothing!!!
470
  */
471
}
472
 
473
static void RRVALUE_task_endcycle(LEVEL l, PID p)
474
{
475
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
476
 
477
  if (lev->nact[p] > 0) {
478
    /* continue!!!! */
479
    ll_gettime(TIME_EXACT, &proc_table[p].request_time);
480
    lev->nact[p]--;
481
//    qq_insertlast(p,&lev->ready);
482
    qq_insertfirst(p,&lev->ready);
483
    proc_table[p].status = RRVALUE_READY;
484
  }
485
  else
486
    proc_table[p].status = RRVALUE_IDLE;
487
}
488
 
489
static void RRVALUE_task_end(LEVEL l, PID p)
490
{
491
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
492
  struct timespec t;
493
 
494
  lev->nact[p] = -1;
495
 
496
  /* we delete the reactivation timer */
497
  if (lev->periodic[p]) {
498
    event_delete(lev->reactivation_timer[p]);
499
    lev->reactivation_timer[p] = -1;
500
  }
501
 
502
  /* then, we insert the task in the free queue */
503
  proc_table[p].status = FREE;
504
  q_insert(p,&freedesc);
505
 
506
  // account for the value only if it<finishes in time
507
  if (lev->penalty[p] || lev->value[p]) {
508
    ll_gettime(TIME_EXACT,&t);
509
    if (TIMESPEC_A_LT_B(&t, &lev->reactivation_time[p]))
510
      lev->totalvalue += lev->penalty[p] + lev->value[p];
511
  }
512
 
513
  lev->max_tasks++;
514
}
515
 
516
static void RRVALUE_task_sleep(LEVEL l, PID p)
517
{
518
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
519
 
520
  if (lev->nact[p] >= 0) lev->nact[p] = 0;
521
 
522
  /* we delete the reactivation timer */
523
  if (lev->periodic[p]) {
524
    event_delete(lev->reactivation_timer[p]);
525
    lev->reactivation_timer[p] = -1;
526
  }
527
 
528
  proc_table[p].status = SLEEP;
529
}
530
 
531
static void RRVALUE_task_delay(LEVEL l, PID p, TIME usdelay)
532
{
533
//  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
534
  struct timespec wakeuptime;
535
 
536
  /* equal to RRVALUE_task_endcycle */
537
  proc_table[p].status = RRVALUE_DELAY;
538
 
539
  /* we need to delete this event if we kill the task while it is sleeping */
540
  ll_gettime(TIME_EXACT,&wakeuptime);
541
  ADDUSEC2TIMESPEC(usdelay,&wakeuptime);
542
  proc_table[p].delay_timer = kern_event_post(&wakeuptime,
543
                                              RRVALUE_timer_delay,
544
                                              (void *)p);
545
}
546
 
547
 
548
static int RRVALUE_guest_create(LEVEL l, PID p, TASK_MODEL *m)
549
{ kern_raise(XUNVALID_GUEST,exec_shadow); return 0; }
550
 
551
static void RRVALUE_guest_detach(LEVEL l, PID p)
552
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
553
 
554
static void RRVALUE_guest_dispatch(LEVEL l, PID p, int nostop)
555
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
556
 
557
static void RRVALUE_guest_epilogue(LEVEL l, PID p)
558
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
559
 
560
static void RRVALUE_guest_activate(LEVEL l, PID p)
561
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
562
 
563
static void RRVALUE_guest_insert(LEVEL l, PID p)
564
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
565
 
566
static void RRVALUE_guest_extract(LEVEL l, PID p)
567
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
568
 
569
static void RRVALUE_guest_endcycle(LEVEL l, PID p)
570
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
571
 
572
static void RRVALUE_guest_end(LEVEL l, PID p)
573
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
574
 
575
static void RRVALUE_guest_sleep(LEVEL l, PID p)
576
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
577
 
578
static void RRVALUE_guest_delay(LEVEL l, PID p,DWORD tickdelay)
579
{ kern_raise(XUNVALID_GUEST,exec_shadow); }
580
 
581
 
582
 
583
 
584
/* Registration functions */
585
 
586
/*+ This init function install the "main" task +*/
587
static void RRVALUE_call_main(void *l)
588
{
589
  LEVEL lev;
590
  PID p;
591
  NRT_TASK_MODEL m;
592
  void *mb;
593
 
594
  lev = (LEVEL)l;
595
 
596
  nrt_task_default_model(m);
597
  nrt_task_def_level(m,lev); /* with this we are sure that the task aRRVALUEives
598
                                to the coRRVALUEect level */
599
 
600
  mb = ((RRVALUE_level_des *)level_table[lev])->multiboot;
601
  nrt_task_def_arg(m,mb);
602
  nrt_task_def_usemath(m);
603
  nrt_task_def_nokill(m);
604
  nrt_task_def_ctrl_jet(m);
605
 
606
  p = task_create("Main", __init__, (TASK_MODEL *)&m, NULL);
607
 
608
  if (p == NIL)
609
    printk("\nPanic!!! can't create main task...\n");
610
 
611
  RRVALUE_task_activate(lev,p);
612
}
613
 
614
 
615
/*+ Registration function:
616
    TIME slice                the slice for the Round Robin queue
617
    int createmain            1 if the level creates the main task 0 otherwise
618
    struct multiboot_info *mb used if createmain specified   +*/
619
void RRVALUE_register_level(TIME slice,
620
                       int createmain,
621
                       struct multiboot_info *mb,
622
                       BYTE models, int m)
623
{
624
  LEVEL l;            /* the level that we register */
625
  RRVALUE_level_des *lev;  /* for readableness only */
626
  PID i;
627
 
628
  printk("RRVALUE_register_level\n");
629
 
630
  /* request an entry in the level_table */
631
  l = level_alloc_descriptor();
632
 
633
  /* alloc the space needed for the RRVALUE_level_des */
634
  lev = (RRVALUE_level_des *)kern_alloc(sizeof(RRVALUE_level_des));
635
 
636
  printk("    lev=%d\n",(int)lev);
637
 
638
  /* update the level_table with the new entry */
639
  level_table[l] = (level_des *)lev;
640
 
641
  /* fill the standard descriptor */
642
  strncpy(lev->l.level_name,  RRVALUE_LEVELNAME, MAX_LEVELNAME);
643
  lev->l.level_code               = RRVALUE_LEVEL_CODE;
644
  lev->l.level_version            = RRVALUE_LEVEL_VERSION;
645
 
646
  lev->l.level_accept_task_model  = RRVALUE_level_accept_task_model;
647
  lev->l.level_accept_guest_model = RRVALUE_level_accept_guest_model;
648
  lev->l.level_status             = RRVALUE_level_status;
649
  lev->l.level_scheduler          = RRVALUE_level_scheduler;
650
  lev->l.level_guarantee          = RRVALUE_level_guarantee;
651
 
652
  lev->l.task_create              = RRVALUE_task_create;
653
  lev->l.task_detach              = RRVALUE_task_detach;
654
  lev->l.task_eligible            = RRVALUE_task_eligible;
655
  lev->l.task_dispatch            = RRVALUE_task_dispatch;
656
  lev->l.task_epilogue            = RRVALUE_task_epilogue;
657
  lev->l.task_activate            = RRVALUE_task_activate;
658
  lev->l.task_insert              = RRVALUE_task_insert;
659
  lev->l.task_extract             = RRVALUE_task_extract;
660
  lev->l.task_endcycle            = RRVALUE_task_endcycle;
661
  lev->l.task_end                 = RRVALUE_task_end;
662
  lev->l.task_sleep               = RRVALUE_task_sleep;
663
  lev->l.task_delay               = RRVALUE_task_delay;
664
 
665
  lev->l.guest_create             = RRVALUE_guest_create;
666
  lev->l.guest_detach             = RRVALUE_guest_detach;
667
  lev->l.guest_dispatch           = RRVALUE_guest_dispatch;
668
  lev->l.guest_epilogue           = RRVALUE_guest_epilogue;
669
  lev->l.guest_activate           = RRVALUE_guest_activate;
670
  lev->l.guest_insert             = RRVALUE_guest_insert;
671
  lev->l.guest_extract            = RRVALUE_guest_extract;
672
  lev->l.guest_endcycle           = RRVALUE_guest_endcycle;
673
  lev->l.guest_end                = RRVALUE_guest_end;
674
  lev->l.guest_sleep              = RRVALUE_guest_sleep;
675
  lev->l.guest_delay              = RRVALUE_guest_delay;
676
 
677
  /* fill the RRVALUE descriptor part */
678
  for (i = 0; i < MAX_PROC; i++) {
679
    lev->nact[i] = -1;
680
    NULL_TIMESPEC(&lev->reactivation_time[i]);
681
    lev->reactivation_timer[i] = -1;
682
    lev->periodic[i] = 0;
683
    lev->period[i] = 0;
684
    lev->value[i] = 0;
685
    lev->penalty[i] = 0;
686
  }
687
 
688
  qq_init(&lev->ready);
689
 
690
  if (slice < RRVALUE_MINIMUM_SLICE) slice = RRVALUE_MINIMUM_SLICE;
691
  if (slice > RRVALUE_MAXIMUM_SLICE) slice = RRVALUE_MAXIMUM_SLICE;
692
  lev->slice      = slice;
693
 
694
  lev->multiboot  = mb;
695
 
696
  lev->models     = models;
697
 
698
  lev->totalvalue = 0;
699
 
700
  lev->max_tasks  = m;
701
 
702
  if (createmain)
703
    sys_atrunlevel(RRVALUE_call_main,(void *) l, RUNLEVEL_INIT);
704
}
705
 
706
 
707
/*+ returns the current total value +*/
708
int RRVALUE_getvalue(LEVEL l)
709
{
710
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
711
  if (lev->l.level_code    == RRVALUE_LEVEL_CODE &&
712
      lev->l.level_version == RRVALUE_LEVEL_VERSION)
713
    return lev->totalvalue;
714
  else
715
    return 0;
716
}
717
 
718
/*
719
 * These functions are needed only to link with the crunch application
720
 * They should not be used in other applications.
721
 */
722
 
723
#include <modules/edf.h>
724
 
725
void crunch_register_models(struct multiboot_info *mb)
726
{
727
  EDF_register_level(EDF_ENABLE_ALL);
728
  RRVALUE_register_level(10000, RRVALUE_MAIN_NO, mb,
729
    RRVALUE_ONLY_HARD|RRVALUE_ONLY_SOFT|RRVALUE_ONLY_VALUE,5);
730
}
731
 
732
int crunch_taskaccepted(PID p)
733
{
734
  LEVEL l = proc_table[p].task_level;
735
  RRVALUE_level_des *lev = (RRVALUE_level_des *)(level_table[l]);
736
 
737
  if (lev->max_tasks > 0) {
738
    lev->totalvalue -= lev->penalty[p];
739
    return 1;
740
  }
741
  else {
742
    return 0;
743
  }
744
}
745
 
746
int crunch_getvalue()
747
{
748
  return RRVALUE_getvalue(2);
749
}