Subversion Repositories shark

Rev

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

Rev Author Line No. Line
990 trimarchi 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 "ll/i386/64bit.h"
39
#include "fedfstar.h"
40
#include <ll/stdio.h>
41
#include <ll/string.h>
42
#include <kernel/model.h>
43
#include <kernel/descr.h>
44
#include <kernel/var.h>
45
#include <kernel/func.h>
46
 
47
#include <tracer.h>
48
 
49
/* for iqueues */
50
/* #include "iqueue.h" Now iqueues are the only queue type available
51
   into the kernel */
52
#include <kernel/iqueue.h>
53
 
54
/* for BUDGET_TASK_MODEL */
55
#include "fsf_configuration_parameters.h"
56
#include "fsf_core.h"
57
#include "fsf_server.h"
58
#include <posix/posix/comm_message.h>
59
 
60
 
61
/*
62
 * DEBUG stuffs begin
63
 */
64
 
65
//#define FEDFSTAR_DEBUG
66
//#define FDB_DEBUG
67
 
68
#ifdef FEDFSTAR_DEBUG
69
 
70
static __inline__ fake_printf(char *fmt, ...) {}
71
 
72
//#define fedfstar_printf fake_printf
73
//#define fedfstar_printf2 fake_printf
74
//#define fedfstar_printf3 fake_printf
75
 
76
#define fedfstar_printf kern_printf
77
#define fedfstar_printf2 kern_printf
78
#define fedfstar_printf3 kern_printf
79
#endif
80
 
81
/*
82
 * DEBUG stuffs end
83
 */
84
 
85
/* Status used in the level */
86
#define FEDFSTAR_READY         MODULE_STATUS_BASE    /* - Ready status        */
87
#define FEDFSTAR_IDLE          MODULE_STATUS_BASE+4  /* to wait the deadline  */
88
 
89
/* flags */
90
#define FEDFSTAR_CHANGE_LEVEL     8 
91
#define FEDFSTAR_FLAG_NOPREEMPT   4 
92
#define FEDFSTAR_FLAG_NORAISEEXC  2
93
#define FEDFSTAR_FLAG_SPORADIC    1
94
 
95
 
96
/* the level redefinition for the Earliest Deadline First level */
97
typedef struct {
98
  level_des l;     /* the standard level descriptor          */
99
 
100
  TIME period[MAX_PROC]; /* The task periods; the deadlines are
101
                       stored in the priority field           */
102
  int deadline_timer[MAX_PROC];
103
                   /* The task deadline timers               */
104
 
105
  struct timespec deadline_timespec[MAX_PROC];
106
 
107
  int dline_miss[MAX_PROC]; /* Deadline miss counter */
108
  int wcet_miss[MAX_PROC];  /* Wcet miss counter */
109
 
110
  int nact[MAX_PROC];       /* Wcet miss counter */
111
 
112
  int flag[MAX_PROC];
113
                   /* used to manage the JOB_TASK_MODEL and the
114
                       periodicity                            */
115
 
116
  IQUEUE ready;     /* the ready queue                        */
117
 
118
  PID activated;   /* the task that has been inserted into the
119
                       master module */
120
 
121
  int budget[MAX_PROC];
122
 
123
  int scheduling_level;
124
 
125
  int cap_lev;
126
  struct timespec cap_lasttime;
127
 
128
  int new_level[MAX_PROC];
129
  int wcet[MAX_PROC]; /* save the wcet fields */
130
 
131
  int ctime[MAX_PROC]; /* last computation time */
132
  int cavg[MAX_PROC]; /* avg of computation time */
133
  int ccount[MAX_PROC]; /* number of istance */
134
 
135
} FEDFSTAR_level_des;
136
 
137
#define HISTORY_BACK 4
138
#define GRANULARITY  5 // in microseconds
139
 
140
typedef bandwidth_t inv_bandwidth_t;
141
 
142
static long long int delta_new;
143
static long long int tita[HISTORY_BACK][FSF_MAX_N_SERVERS];
144
static bandwidth_t u[HISTORY_BACK][FSF_MAX_N_SERVERS];
145
 
146
void init_feedbackstruct(void) {
147
  int i=0, j=0;
148
  for (i=0; i<FSF_MAX_N_SERVERS; i++)
149
    for (j=0; j<HISTORY_BACK; j++) {
150
      u[j][i]=0;
151
      tita[j][i]=0;
152
    }
153
}
154
 
155
 
156
long long int FDB_sample(int sched_error, TIME server_period, TIME cavg)
157
{
158
  static long long int delta_old=0;
159
  static int sched_error_prev=0;
160
  long long int temp,temp1;
161
  int beta_1; //Not really this value
162
  int gamma_1;
163
  int beta_2;
164
  int gamma_2;
165
 
166
  #ifdef FDB_DEBUG
167
     kern_printf("(FDB:sample:period:%d:cavg:%d:sched_error:%d)",(int)server_period,(int)cavg, sched_error);
168
  #endif
169
 
170
  temp=1000*server_period/cavg;
171
  beta_1=temp*6/5;
172
  gamma_1=temp*(-93)/100;
173
  beta_2=temp/5;
174
  gamma_2=temp*7/100;
175
 
176
  #ifdef FDB_DEBUG
177
     kern_printf("(FDB:sample:b1:%d:g1:%d:b2:%d:g2:%d:temp:%d)",beta_1,gamma_1,beta_2,gamma_2, (int)temp);
178
  #endif
179
 
180
  if ((long long int)sched_error>=(long long int)server_period) {
181
    temp=beta_1*(long long int)sched_error/server_period;
182
    temp1=gamma_1*(long long int)sched_error_prev/server_period;
183
    delta_new=delta_old-temp-temp1;
184
  }
185
  else {
186
    temp=beta_2*(long long int)sched_error/server_period;
187
    temp1=gamma_2*(long long int)sched_error_prev/server_period;
188
    delta_new=delta_old-temp-temp1;
189
  }
190
 #ifdef FDB_DEBUG
191
     kern_printf("(FDB1:sched_error:%d:delta_new:%d)",sched_error, (int)delta_new);
192
  #endif
193
 
194
 delta_old=delta_new;
195
 
196
 sched_error_prev=sched_error;
197
 
198
 return(delta_new);
199
}
200
 
201
 
202
/* This function preditcs the value of the next execution time based on the history of the task.
203
The algorithm is known as LMS and minimizes the square error.
204
It has to add the blocking time if the task may be block
205
And to determine the bandwidth it has to add the bandwidth determine in the previous function
206
*/
207
TIME FDB_activate(fsf_server_id_t server, TIME server_period, TIME blk_time, TIME c_time, TIME c_avg, bandwidth_t bw)
208
{
209
  //Filter coefficients
210
  static int mu=2000; //convergence factor
211
  static long long int u_predicted=0;
212
  static long long int pred_error=0;
213
  bandwidth_t u_avg;
214
  bandwidth_t unew;
215
  int i;
216
  TIME Q_new;
217
  long long int u_new;
218
  static long long int u_p_avg=0;
219
  static int nro=0;
220
 
221
  //u_avg=server_bandwidth_avg;
222
 
223
 
224
  nro++;
225
  pred_error=u_predicted-(long long int)u[0][server];
226
 
227
 
228
  for (i=0;i<HISTORY_BACK;i++) {
229
    long long int temp=0;
1003 trimarchi 230
    temp=pred_error*(long long int)u[i][server]/mu;
990 trimarchi 231
    tita[i][server]=tita[i][server]-temp;    
232
  }
233
 
234
  u_predicted=0;
235
  for (i=0;i<HISTORY_BACK;i++)
1003 trimarchi 236
    u_predicted+=((tita[i][server]*(long long int)u[i][server]));
990 trimarchi 237
 
238
  for (i=0; i<(HISTORY_BACK-1); i++)
239
    u[i+1][server]=u[i][server];
240
 
241
  u_p_avg=(u_p_avg*(nro-1)+u_predicted)/nro; //OK
242
 
243
 
244
  if (c_avg!=0)
245
    mul32div32to32(MAX_BANDWIDTH,c_avg,server_period,u_avg);
246
  else
247
    u_avg=bw;
248
 
249
  kern_printf("(FDB:act_int:cavg:%d:sp:%d)", c_avg, server_period, u_avg);
250
 
251
  mul32div32to32(MAX_BANDWIDTH,c_time,server_period,u[0][server]); // last real computation value
252
 
253
  // c_predicted+=blk_time;
254
 
255
 
256
 
257
  /* What follows is the update of the server budget based on the FDB_sample return value and the prediction function
258
   */
259
 
260
 delta_new=MAX_BANDWIDTH*(delta_new/1000);
261
 u_new=delta_new+(long long int)u_avg;
262
 if (u_new<0) exit(-1);
263
 if (u_new>MAX_BANDWIDTH) exit(-1);
264
 unew=(bandwidth_t)u_new;
265
 
266
 mul32div32to32(server_period,unew, MAX_BANDWIDTH, Q_new);
267
 
268
 
269
 
270
 //Q_new=server_period*1000/u;
271
 //#ifdef FDB_DEBUG
272
 kern_printf("(FDB:act_int:unew:%d:delta_new:%d:uavg:%d)",unew, delta_new, u_avg);
273
 //#endif
274
 
275
 kern_printf("(FDB:act_int:qnew:%ld)",Q_new);
276
 return(Q_new);
277
}
278
 
279
 
280
static void capacity_handler(void *l)
281
{
282
  FEDFSTAR_level_des *lev = l;
283
  lev->cap_lev = NIL;
284
  event_need_reschedule();
285
}
286
 
287
static void FEDFSTAR_check_preemption(FEDFSTAR_level_des *lev)
288
{
289
  PID first=NIL;
290
 
291
  #ifdef FEDFSTAR_DEBUG
292
    edfstar_printf("(E:chk)");
293
  #endif
294
  /* check if the task is preempteble or not */
295
  if (lev->activated != NIL && lev->flag[lev->activated] & FEDFSTAR_FLAG_NOPREEMPT) return;
296
 
297
  if ((first = iq_query_first(&lev->ready)) != lev->activated) {
298
    if (lev->activated != NIL)
299
      level_table[ lev->scheduling_level ]->
300
        private_extract(lev->scheduling_level, lev->activated);
301
 
302
    lev->activated = first;
303
 
304
    if (first != NIL) {
305
      BUDGET_TASK_MODEL b;
306
      budget_task_default_model(b, lev->budget[first]);
307
 
308
      level_table[ lev->scheduling_level ]->
309
        private_insert(lev->scheduling_level, first, (TASK_MODEL *)&b);
310
    }
311
  }
312
}
313
 
314
static void FEDFSTAR_timer_deadline(void *par);
315
 
316
static void FEDFSTAR_internal_activate(FEDFSTAR_level_des *lev, PID p,
317
                                      struct timespec *t)
318
{
319
  TIME Q, D, T;
320
  int budget;
321
  bandwidth_t bw;
322
 
323
  #ifdef FEDFSTAR_DEBUG
324
    edfstar_printf("(E:iact)");
325
  #endif
326
 
327
  ADDUSEC2TIMESPEC(lev->period[p], t);
328
 
329
  *iq_query_timespec(p, &lev->ready) = *t;
330
  lev->deadline_timespec[p] = *t;
331
 
332
  /* Insert task in the correct position */
333
  proc_table[p].status = FEDFSTAR_READY;
334
  iq_timespec_insert(p,&lev->ready);
335
  proc_table[p].control &= ~CONTROL_CAP;
336
 
337
  budget=lev->budget[p];
338
  SERVER_getbudgetinfo(lev->scheduling_level, &Q, &T, &D, budget);
339
 
340
  mul32div32to32(MAX_BANDWIDTH, Q, T, bw);
341
 
342
  Q=FDB_activate(budget, T, 0, lev->ctime[p], lev->cavg[p], bw);
343
 
344
  SERVER_adjust_budget(lev->scheduling_level, Q, T, D, budget);
345
 
346
 
347
  /* check for preemption */
348
  FEDFSTAR_check_preemption(lev);
349
}
350
 
351
static void FEDFSTAR_timer_deadline(void *par)
352
{
353
  PID p = (PID) par;
354
  FEDFSTAR_level_des *lev;
355
 
356
  lev = (FEDFSTAR_level_des *)level_table[proc_table[p].task_level];
357
  lev->deadline_timer[p] = NIL;  
358
 
359
  switch (proc_table[p].status) {
360
    case FEDFSTAR_IDLE:
361
      /* set the request time */
362
      if (!(lev->flag[p] & FEDFSTAR_FLAG_SPORADIC))
363
        FEDFSTAR_internal_activate(lev,p,iq_query_timespec(p, &lev->ready));
364
 
365
      event_need_reschedule();
366
      break;
367
 
368
    default:
369
      #ifdef FEDFSTAR_DEBUG
370
        kern_printf("(E:Dl:%d)",p);
371
      #endif
372
      /* else, a deadline miss occurred!!! */
373
      lev->dline_miss[p]++;
374
      TRACER_LOGEVENT(FTrace_EVT_task_deadline_miss,proc_table[p].context,proc_table[p].task_level);
375
 
376
      /* the task is into another state */
377
      if (!(lev->flag[p] & FEDFSTAR_FLAG_SPORADIC)) {
378
        lev->nact[p]++;
379
        ADDUSEC2TIMESPEC(lev->period[p], &lev->deadline_timespec[p]);
380
      }
381
  }
382
 
383
  /* Set the deadline timer */
384
  if (!(lev->flag[p] & FEDFSTAR_FLAG_SPORADIC))
385
    lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
386
                                             FEDFSTAR_timer_deadline,
387
                                             (void *)p);
388
 
389
}
390
 
391
static int FEDFSTAR_private_change_level(LEVEL l, PID p)
392
{
393
 
394
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
395
 
396
  /* Change task level */
397
  if (lev->flag[p] & FEDFSTAR_CHANGE_LEVEL) {
398
 
399
#ifdef FEDFSTAR_DEBUG
400
    edfstar_printf("(E:clev)");
401
#endif
402
 
403
    STD_command_message msg;
404
 
405
    proc_table[p].status = SLEEP;
406
    lev->flag[p] &= ~ FEDFSTAR_CHANGE_LEVEL;
407
 
408
    level_table[lev->scheduling_level]->private_extract(lev->scheduling_level,p);
409
    iq_extract(p,&lev->ready);
410
 
411
    if (lev->deadline_timer[p] != -1)
412
      kern_event_delete(lev->deadline_timer[p]);
413
    lev->deadline_timer[p]=NIL;
414
 
415
    FEDFSTAR_check_preemption(lev);
416
 
417
    lev->nact[p] = 0;
418
    lev->budget[p] = -1;
419
    proc_table[p].task_level = lev->new_level[p];
420
 
421
    /* Send change level command to local scheduler */
422
 
423
    msg.command = STD_ACTIVATE_TASK;
424
    msg.param = NULL;
425
 
426
    level_table[ lev->new_level[p] ]->public_message(lev->new_level[p],p,&msg);
427
 
428
    return 1;
429
 
430
  }
431
 
432
  return 0;
433
 
434
}
435
 
436
 
437
static void FEDFSTAR_timer_guest_deadline(void *par)
438
{
439
  PID p = (PID) par;
440
 
441
  #ifdef FEDFSTAR_DEBUG
442
    edfstar_printf("(E:gdl)");
443
  #endif
444
 
445
  kern_raise(XDEADLINE_MISS,p);
446
}
447
 
448
static int FEDFSTAR_public_create(LEVEL l, PID p, TASK_MODEL *m)
449
{
450
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
451
 
452
  /* if the FEDFSTAR_task_create is called, then the pclass must be a
453
     valid pclass. */
454
  HARD_TASK_MODEL *h;
455
 
456
  if (m->pclass != HARD_PCLASS) return -1;
457
  if (m->level != 0 && m->level != l) return -1;
458
  h = (HARD_TASK_MODEL *)m;
459
  if (!h->wcet || !h->mit) return -1;
460
  /* now we know that m is a valid model */
461
 
462
  #ifdef FEDFSTAR_DEBUG
463
    edfstar_printf("(E:Crt)");
464
  #endif
465
 
466
  lev->period[p] = h->mit;
467
 
468
  lev->flag[p] = 0;
469
 
470
  if (h->periodicity == APERIODIC)
471
       lev->flag[p] |= FEDFSTAR_FLAG_SPORADIC;
472
 
473
  lev->deadline_timer[p] = -1;
474
  lev->dline_miss[p]     = 0;
475
  lev->wcet_miss[p]      = 0;
476
  lev->nact[p]           = 0;
477
 
478
  /* Enable wcet check */
479
  proc_table[p].avail_time = h->wcet;
480
  proc_table[p].wcet       = h->wcet;
481
  proc_table[p].status     = SLEEP;
482
 
483
  return 0; /* OK, also if the task cannot be guaranteed... */
484
}
485
 
486
 
487
static void FEDFSTAR_account_capacity(FEDFSTAR_level_des *lev, PID p)
488
{
489
  struct timespec ty;
490
  TIME tx;
491
 
492
 
493
  SUBTIMESPEC(&schedule_time, &lev->cap_lasttime, &ty);
494
  tx = TIMESPEC2USEC(&ty);
495
 
496
  proc_table[p].avail_time -= tx;
497
}
498
 
499
static int FEDFSTAR_public_eligible(LEVEL l, PID p)
500
{
501
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
502
 
503
  #ifdef FEDFSTAR_DEBUG
504
    edfstar_printf2("(E:eli:%d)",p);
505
  #endif
506
 
507
  return level_table[ lev->scheduling_level ]->
508
    private_eligible(lev->scheduling_level,p);
509
 
510
}
511
 
512
static void FEDFSTAR_public_dispatch(LEVEL l, PID p, int nostop)
513
{
514
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
515
  struct timespec ty;
516
 
517
  #ifdef FEDFSTAR_DEBUG
518
    edfstar_printf("(E:dis)");
519
  #endif
520
 
521
  if (!nostop || proc_table[exec].task_level==l) {
522
      TIMESPEC_ASSIGN(&ty, &schedule_time);
523
      TIMESPEC_ASSIGN(&lev->cap_lasttime, &schedule_time);
524
 
525
      /* ...and finally, we have to post a capacity event on exec task because the shadow_task consume
526
       *      *        capacity on exe task always */
527
      if (proc_table[exec].avail_time > 0) {
528
        ADDUSEC2TIMESPEC(proc_table[exec].avail_time ,&ty);
529
        lev->cap_lev = kern_event_post(&ty,capacity_handler, lev);
530
      }
531
      level_table[lev->scheduling_level]->private_dispatch(lev->scheduling_level, p, nostop);
532
  }
533
  else
534
      level_table[proc_table[exec].task_level]->public_dispatch(proc_table[exec].task_level, p, nostop);
535
 
536
}
537
 
538
static void FEDFSTAR_public_epilogue(LEVEL l, PID p)
539
{
540
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
541
 
542
  #ifdef FEDFSTAR_DEBUG
543
    edfstar_printf("(E:epi ");
544
  #endif
545
 
546
  if (lev->cap_lev!=NIL) {
547
       kern_event_delete(lev->cap_lev);
548
       lev->cap_lev=NIL;
549
  }
550
 
551
 
552
  if ( proc_table[exec].task_level==l ) {
553
 
554
     if (proc_table[exec].avail_time > 0) FEDFSTAR_account_capacity(lev,exec);
555
 
556
     if (FEDFSTAR_private_change_level(l, p)) return;
557
 
558
     /* check if the wcet is finished... */
559
     if (proc_table[exec].avail_time < 0) {
560
        /* wcet finished: disable wcet event and count wcet miss */
561
 
562
       #ifdef FEDFSTAR_DEBUG
563
         edfstar_printf2("W%d",p);
564
       #endif
565
        //proc_table[p].control &= ~CONTROL_CAP;
566
        lev->wcet_miss[exec]++;
567
        proc_table[exec].avail_time = 0;
568
        TRACER_LOGEVENT(FTrace_EVT_task_wcet_violation,proc_table[exec].context,proc_table[exec].task_level);
569
     }
570
 
571
     #ifdef FEDFSTAR_DEBUG
572
       edfstar_printf(")");
573
     #endif
574
 
575
     level_table[ lev->scheduling_level ]->
576
       private_epilogue(lev->scheduling_level,p);
577
 
578
      proc_table[exec].status = FEDFSTAR_READY;
579
    } else
580
        level_table[proc_table[exec].task_level]->public_epilogue(proc_table[exec].task_level,p);
581
 
582
}
583
 
584
static void FEDFSTAR_public_activate(LEVEL l, PID p, struct timespec *o)
585
{
586
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
587
  struct timespec t;
588
 
589
  #ifdef FEDFSTAR_DEBUG
590
    edfstar_printf("(E:act:%d)",p);
591
  #endif
592
 
593
  /* Test if we are trying to activate a non sleeping task    */
594
  /* save activation (only if needed... */
595
  if (proc_table[p].status != SLEEP) {
596
    /* a periodic task cannot be activated when it is already active */
597
    /* but aperiodic task can be reactivate before */
598
    if (lev->flag[p] & FEDFSTAR_FLAG_SPORADIC) {
599
        if (proc_table[p].status != FEDFSTAR_IDLE) {
600
          lev->nact[p]++;
601
          //kern_printf("(Inc nact %d)",p);
602
          //kern_printf("(%d STATUS %d %ds %dns)", p, proc_table[p].status, o->tv_sec, o->tv_nsec/1000);
603
          return;
604
        }
605
    } else {
606
      return;
607
      //kern_raise(XACTIVATION,p);
608
    }
609
  }
610
 
611
  kern_gettime(&t);
612
 
613
  FEDFSTAR_internal_activate(lev,p, &t);
614
 
615
  /* Set the deadline timer */
616
  lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
617
                                           FEDFSTAR_timer_deadline,
618
                                           (void *)p);
619
 
620
}
621
 
622
static void FEDFSTAR_public_unblock(LEVEL l, PID p)
623
{
624
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
625
 
626
  #ifdef FEDFSTAR_DEBUG
627
    edfstar_printf("(E:ins)");
628
  #endif
629
 
630
  /* Insert task in the correct position */
631
  proc_table[p].status = FEDFSTAR_READY;
632
  iq_timespec_insert(p,&lev->ready);
633
 
634
  /* and check for preemption! */
635
  FEDFSTAR_check_preemption(lev);
636
 
637
}
638
 
639
static void FEDFSTAR_public_block(LEVEL l, PID p)
640
{
641
 
642
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
643
 
644
  #ifdef FEDFSTAR_DEBUG
645
   edfstar_printf("(E:ext)");
646
  #endif
647
 
648
  /* the task is blocked on a synchronization primitive. we have to
649
     remove it from the master module -and- from the local queue! */
650
  iq_extract(p,&lev->ready);
651
 
652
  /* and finally, a preemption check! (it will also call guest_end) */
653
  FEDFSTAR_check_preemption(lev);
654
}
655
 
656
static int FEDFSTAR_public_message(LEVEL l, PID p, void *m)
657
{
658
 
659
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
660
  struct timespec temp;
661
  STD_command_message *msg;
662
  HARD_TASK_MODEL *h;
663
  TIME Q, D, T;
664
  struct timespec t,diff;
665
  int sched_error_act;
666
  int budget;
667
 
668
  #ifdef FEDFSTAR_DEBUG
669
    edfstar_printf("(E:ecy ");
670
  #endif
671
 
672
  switch ((long)(m)) {
673
 
674
    /* Task EndCycle */
675
    case (long)(NULL):
676
 
677
      if (FEDFSTAR_private_change_level(l,p)) return 0;
678
 
679
      sched_error_act=0;
680
      budget=FEDFSTAR_getbudget(l,p);
681
      SERVER_getbudgetinfo(lev->scheduling_level, &Q, &T, &D, budget);
682
      SERVER_getdeadline(lev->scheduling_level, budget, &t);
683
      //rnumber=CBSNHSTAR_getrecharge_number(lev->scheduling_level, budget);
684
 
685
      /* check if the deadline has already expired */
686
      temp = *iq_query_timespec(p, &lev->ready);
687
      kern_printf("(dt sec %ld, us %ld)", temp.tv_sec, temp.tv_nsec/1000);
688
      kern_printf("(ds sec %ld, us %ld)", t.tv_sec, t.tv_nsec/1000);
689
      if (/* 1 */ TIMESPEC_A_LT_B(&t,&temp)) {   
690
        SUBTIMESPEC(&temp, &t, &diff);
691
        sched_error_act=-TIMESPEC2USEC(&diff);
692
      }
693
      else {
694
        SUBTIMESPEC(&t, &temp, &diff);
695
        sched_error_act=TIMESPEC2USEC(&diff);
696
      }
697
 
698
      if (proc_table[p].avail_time > 0) FEDFSTAR_account_capacity(lev,p);
699
 
700
       /* we call guest_end directly here because the same task may
701
         be reinserted in the queue before calling the preemption check! */
702
       level_table[ lev->scheduling_level ]->
703
         private_extract(lev->scheduling_level,p);
704
       lev->activated = NIL;
705
 
706
       iq_extract(p,&lev->ready);
707
 
708
       /* we reset the capacity counters... */
709
       proc_table[p].avail_time = proc_table[p].wcet;
710
 
711
       lev->ctime[p]=proc_table[p].wcet-proc_table[p].avail_time;
712
 
713
       lev->cavg[p]=(lev->ctime[p]+(lev->cavg[p])*(lev->ccount[p]))/(lev->ccount[p]+1);      
714
 
715
       lev->ccount[p]=(lev->ccount[p]%INT_MAX)+1;
716
 
717
       delta_new=FDB_sample(sched_error_act, T, lev->cavg[p]);
718
 
719
       if (lev->nact[p] > 0) {
720
 
721
         #ifdef FEDFSTAR_DEBUG
722
           kern_printf("E%d",p);
723
         #endif
724
 
725
         /* Pending activation: reactivate the thread!!! */
726
         lev->nact[p]--;
727
 
728
         /* see also FEDFSTAR_timer_deadline */
729
         kern_gettime(&temp);
730
 
731
         FEDFSTAR_internal_activate(lev,p, &temp);
732
 
733
         /* check if the deadline has already expired */
734
         temp = *iq_query_timespec(p, &lev->ready);
735
         if (TIMESPEC_A_LT_B(&temp, &schedule_time)) {
736
           /* count the deadline miss */
737
           lev->dline_miss[p]++;
738
           kern_event_delete(lev->deadline_timer[p]);
739
           lev->deadline_timer[p] = NIL;
740
         }
741
 
742
       } else {
743
 
744
         #ifdef FEDFSTAR_DEBUG
745
           edfstar_printf("e%d",p);
746
         #endif
747
 
748
         /* the task has terminated his job before it consume the wcet. All OK! */
749
         if (lev->flag[p] & FEDFSTAR_FLAG_SPORADIC)
750
                proc_table[p].status = SLEEP;
751
         else
752
                proc_table[p].status = FEDFSTAR_IDLE;
753
 
754
         if (lev->flag[p] & FEDFSTAR_FLAG_SPORADIC && lev->deadline_timer[p] != NIL) {
755
           kern_event_delete(lev->deadline_timer[p]);
756
           lev->deadline_timer[p] = NIL;
757
         }
758
 
759
         /* and finally, a preemption check! */
760
         FEDFSTAR_check_preemption(lev);
761
 
762
         /* when the deadline timer fire, it recognize the situation and set
763
           correctly all the stuffs (like reactivation, etc... ) */
764
       }
765
 
766
    #ifdef FEDFSTAR_DEBUG
767
      edfstar_printf(")");
768
    #endif
769
 
770
    TRACER_LOGEVENT(FTrace_EVT_task_end_cycle,proc_table[p].context,proc_table[p].task_level);
771
    jet_update_endcycle(); /* Update the Jet data... */
772
    break;
773
 
774
  default:
775
    msg = (STD_command_message *)m;
776
 
777
#ifdef FEDFSTAR_DEBUG
778
    edfstar_printf("(E:MSG %d)",msg->command);
779
#endif   
780
 
781
    switch(msg->command) {
782
    case STD_SET_NEW_MODEL:
783
      /* if the FEDFSTAR_task_create is called, then the pclass must be a
784
         valid pclass. */
785
      h=(HARD_TASK_MODEL *)(msg->param);
786
 
787
      /* now we know that m is a valid model */
788
      lev->wcet[p] = h->wcet;
789
      lev->period[p] = h->mit;
790
 
791
#ifdef FEDFSTAR_DEBUG      
792
      kern_printf("(EDF:NM p%d w%d m%d)", p, h->wcet, h->mit);
793
#endif       
794
      lev->flag[p] = 0;
795
      lev->deadline_timer[p] = -1;
796
      lev->dline_miss[p]     = 0;
797
      lev->wcet_miss[p]      = 0;
798
      lev->nact[p]           = 0;
799
 
800
      break;
801
 
802
    case STD_SET_NEW_LEVEL:
803
 
804
      lev->flag[p] |= FEDFSTAR_CHANGE_LEVEL;
805
      lev->new_level[p] = (int)(msg->param);
806
 
807
      break;
808
 
809
    case STD_ACTIVATE_TASK:
810
#ifdef FEDFSTAR_DEBUG
811
      kern_printf("(EDF:SA)");
812
#endif       
813
      /* Enable wcet check */
814
      proc_table[p].avail_time = lev->wcet[p];
815
      proc_table[p].wcet       = lev->wcet[p];
816
      proc_table[p].control &= ~CONTROL_CAP;
817
 
818
      FEDFSTAR_public_activate(l, p,NULL);
819
 
820
      break;
821
 
822
 
823
    }
824
 
825
    break;
826
 
827
  }
828
  return 0;
829
}
830
 
831
static void FEDFSTAR_public_end(LEVEL l, PID p)
832
{
833
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
834
 
835
  #ifdef FEDFSTAR_DEBUG
836
    edfstar_printf("(E:end)");
837
  #endif
838
 
839
  iq_extract(p,&lev->ready);
840
  level_table[ lev->scheduling_level ]->
841
    private_extract(lev->scheduling_level, p);
842
 
843
 
844
  /* we finally put the task in the ready queue */
845
  proc_table[p].status = FREE;
846
 
847
  iq_insertfirst(p,&freedesc);
848
  lev->activated=NIL;
849
 
850
  if (lev->deadline_timer[p] != -1) {
851
    kern_event_delete(lev->deadline_timer[p]);
852
    lev->deadline_timer[p] = NIL;
853
  }
854
 
855
  /* and finally, a preemption check! (it will also call guest_end) */
856
  FEDFSTAR_check_preemption(lev);
857
}
858
 
859
/* Guest Functions
860
   These functions manages a JOB_TASK_MODEL, that is used to put
861
   a guest task in the FEDFSTAR ready queue. */
862
 
863
static void FEDFSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
864
{
865
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
866
  JOB_TASK_MODEL *job;
867
 
868
  if (m->pclass != JOB_PCLASS || (m->level != 0 && m->level != l) ) {
869
    kern_raise(XINVALID_TASK, p);
870
    return;
871
  }
872
 
873
  job = (JOB_TASK_MODEL *)m;
874
 
875
  /* if the FEDFSTAR_guest_create is called, then the pclass must be a
876
     valid pclass. */
877
 
878
  *iq_query_timespec(p, &lev->ready) = job->deadline;
879
 
880
  lev->deadline_timer[p] = -1;
881
  lev->dline_miss[p]     = 0;
882
  lev->wcet_miss[p]      = 0;
883
  lev->nact[p]           = 0;
884
 
885
  if (job->noraiseexc)
886
    lev->flag[p] |= FEDFSTAR_FLAG_NORAISEEXC;
887
  else {
888
    lev->flag[p] &= ~FEDFSTAR_FLAG_NORAISEEXC;
889
    lev->deadline_timer[p] = kern_event_post(iq_query_timespec(p, &lev->ready),
890
                                             FEDFSTAR_timer_guest_deadline,
891
                                             (void *)p);
892
  }
893
 
894
  lev->period[p] = job->period;
895
 
896
  /* Insert task in the correct position */
897
  iq_timespec_insert(p,&lev->ready);
898
  proc_table[p].status = FEDFSTAR_READY;
899
 
900
  /* check for preemption */
901
  FEDFSTAR_check_preemption(lev);
902
 
903
  /* there is no bandwidth guarantee at this level, it is performed
904
     by the level that inserts guest tasks... */
905
}
906
 
907
static void FEDFSTAR_private_dispatch(LEVEL l, PID p, int nostop)
908
{
909
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
910
 
911
  level_table[ lev->scheduling_level ]->
912
    private_dispatch(lev->scheduling_level,p,nostop);
913
}
914
 
915
static void FEDFSTAR_private_epilogue(LEVEL l, PID p)
916
{
917
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
918
 
919
  /* the task has been preempted. it returns into the ready queue... */
920
  level_table[ lev->scheduling_level ]->
921
    private_epilogue(lev->scheduling_level,p);
922
 
923
  proc_table[p].status = FEDFSTAR_READY;
924
}
925
 
926
static void FEDFSTAR_private_extract(LEVEL l, PID p)
927
{
928
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
929
 
930
#ifdef FEDFSTAR_DEBUG
931
  kern_printf("FEDFSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
932
#endif
933
 
934
  iq_extract(p, &lev->ready);
935
 
936
  /* we remove the deadline timer, because the slice is finished */
937
  if (lev->deadline_timer[p] != NIL) {
938
#ifdef FEDFSTAR_DEBUG
939
    kern_printf("FEDFSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
940
#endif
941
    kern_event_delete(lev->deadline_timer[p]);
942
    lev->deadline_timer[p] = NIL;
943
  }
944
 
945
  /* and finally, a preemption check! (it will also call guest_end() */
946
  FEDFSTAR_check_preemption(lev);
947
}
948
 
949
/* Registration functions */
950
 
951
/* Registration function:
952
    int flags                 the init flags ... see FEDFSTAR.h */
953
 
954
LEVEL FEDFSTAR_register_level(int master)
955
{
956
  LEVEL l;            /* the level that we register */
957
  FEDFSTAR_level_des *lev;  /* for readableness only */
958
  PID i;              /* a counter */
959
 
960
#ifdef FEDFSTAR_DEBUG
961
  printk("FEDFSTAR_register_level\n");
962
#endif
963
 
964
  /* request an entry in the level_table */
965
  l = level_alloc_descriptor(sizeof(FEDFSTAR_level_des));
966
 
967
  lev = (FEDFSTAR_level_des *)level_table[l];
968
 
969
  /* fill the standard descriptor */
970
  lev->l.private_insert   = FEDFSTAR_private_insert;
971
  lev->l.private_extract  = FEDFSTAR_private_extract;
972
  lev->l.private_dispatch = FEDFSTAR_private_dispatch;
973
  lev->l.private_epilogue = FEDFSTAR_private_epilogue;
974
 
975
  lev->l.public_guarantee = NULL;
976
  lev->l.public_eligible  = FEDFSTAR_public_eligible;
977
  lev->l.public_create    = FEDFSTAR_public_create;
978
  lev->l.public_end       = FEDFSTAR_public_end;
979
  lev->l.public_dispatch  = FEDFSTAR_public_dispatch;
980
  lev->l.public_epilogue  = FEDFSTAR_public_epilogue;
981
  lev->l.public_activate  = FEDFSTAR_public_activate;
982
  lev->l.public_unblock   = FEDFSTAR_public_unblock;
983
  lev->l.public_block     = FEDFSTAR_public_block;
984
  lev->l.public_message   = FEDFSTAR_public_message;
985
 
986
  /* fill the FEDFSTAR descriptor part */
987
  for(i=0; i<MAX_PROC; i++) {
988
    lev->period[i]         = 0;
989
    lev->deadline_timer[i] = -1;
990
    lev->flag[i]           = 0;
991
    lev->dline_miss[i]     = 0;
992
    lev->wcet_miss[i]      = 0;
993
    lev->nact[i]           = 0;
994
    lev->budget[i]         = NIL;
995
    lev->new_level[i]      = -1;
996
    lev->ctime[i]          = 0;
997
    lev->cavg[i]           = 0;
998
    lev->ccount[i]         = 0;
999
  }
1000
 
1001
  iq_init(&lev->ready, NULL, IQUEUE_NO_PRIORITY);
1002
  lev->activated = NIL;
1003
 
1004
  lev->scheduling_level = master;
1005
  lev->cap_lev = NIL;
1006
  NULL_TIMESPEC(&lev->cap_lasttime);
1007
 
1008
  return l;
1009
}
1010
 
1011
int FEDFSTAR_get_dline_miss(PID p)
1012
{
1013
  LEVEL l = proc_table[p].task_level;
1014
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
1015
 
1016
  return lev->dline_miss[p];
1017
}
1018
 
1019
int FEDFSTAR_get_wcet_miss(PID p)
1020
{
1021
  LEVEL l = proc_table[p].task_level;
1022
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
1023
 
1024
  return lev->wcet_miss[p];
1025
}
1026
 
1027
int FEDFSTAR_get_nact(PID p)
1028
{
1029
  LEVEL l = proc_table[p].task_level;
1030
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
1031
 
1032
  return lev->nact[p];
1033
}
1034
 
1035
int FEDFSTAR_reset_dline_miss(PID p)
1036
{
1037
  LEVEL l = proc_table[p].task_level;
1038
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
1039
 
1040
  lev->dline_miss[p] = 0;
1041
  return 0;
1042
}
1043
 
1044
int FEDFSTAR_reset_wcet_miss(PID p)
1045
{
1046
  LEVEL l = proc_table[p].task_level;
1047
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
1048
 
1049
  lev->wcet_miss[p] = 0;
1050
  return 0;
1051
}
1052
 
1053
int FEDFSTAR_setbudget(LEVEL l, PID p, int budget)
1054
{
1055
 
1056
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
1057
 
1058
  lev->budget[p] = budget;
1059
 
1060
  return 0;
1061
 
1062
}
1063
 
1064
int FEDFSTAR_getbudget(LEVEL l, PID p)
1065
{
1066
 
1067
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
1068
 
1069
  return lev->budget[p];
1070
 
1071
}
1072
 
1073
void FEDFSTAR_set_nopreemtive_current(LEVEL l) {
1074
 
1075
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
1076
 
1077
  lev->flag[lev->activated]|=FEDFSTAR_FLAG_NOPREEMPT;
1078
}
1079
 
1080
void FEDFSTAR_unset_nopreemtive_current(LEVEL l) {
1081
 
1082
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
1083
 
1084
  lev->flag[lev->activated]&=~FEDFSTAR_FLAG_NOPREEMPT;
1085
}
1086
 
1087
int FEDFSTAR_budget_has_thread(LEVEL l, int budget)
1088
{
1089
 
1090
  FEDFSTAR_level_des *lev = (FEDFSTAR_level_des *)(level_table[l]);
1091
  int i;
1092
 
1093
  for(i = 0; i< MAX_PROC; i++)
1094
    if (lev->budget[i] == budget) return 1;
1095
 
1096
  return 0;
1097
 
1098
}