Subversion Repositories shark

Rev

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