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
 *   (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
 ------------
21
 CVS :        $Id: crunch.c,v 1.1 2004-07-05 14:17:12 pj Exp $
22
 
23
 File:        $File$
24
 Revision:    $Revision: 1.1 $
25
 Last update: $Date: 2004-07-05 14:17:12 $
26
 ------------
27
 
28
**/
29
 
30
/*
31
 * Copyright (C) 2001 Paolo Gai
32
 *
33
 * This program is free software; you can redistribute it and/or modify
34
 * it under the terms of the GNU General Public License as published by
35
 * the Free Software Foundation; either version 2 of the License, or
36
 * (at your option) any later version.
37
 *
38
 * This program is distributed in the hope that it will be useful,
39
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
41
 * GNU General Public License for more details.
42
 *
43
 * You should have received a copy of the GNU General Public License
44
 * along with this program; if not, write to the Free Software
45
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
46
 *
47
 */
48
 
49
 
50
 
51
/*
52
 * Crunch.c
53
 */
54
 
55
 
56
//#define DEBUG_CONFFILE
57
//#define DEBUG_MASTER_HARDCREATE
58
//#define DEBUG_MASTER_VALUECREATE
59
 
60
#include "valmodel.h"
61
#include "crunch.h"
62
#include <kernel/kern.h>
63
 
64
/*
65
 *  This small application simply reads the tasks and executes them.
66
 *  When they are all finished, the system shuts down.
67
 */
68
 
69
 
70
 
71
 
72
/*
73
 * this table contains all the tasks information collected from the
74
 * configuration file
75
 */
76
 
77
#define MAX_PATTERN 100000
78
struct task_struct pattern[MAX_PATTERN];
79
int pattern_dim;
80
 
81
/* This is some data collected by the task destructors that
82
 * can be useful for understanding how the Module works     */
83
 
84
/* this int contains the value as seen by the application */
85
int current_value = 0;
86
int max_value = 0;
87
int min_value = 0;
88
int max_created_value = 0;
89
int min_created_value = 0;
90
 
91
/* the number of finished tasks */
92
int current_finished_tasks = 0;
93
 
94
/* this flag is triggered by the master task  when it finishes */
95
int finished = 0;
96
 
97
/* number of instances of an hard tasks
98
   NOTE that it is 79 and not 80 as in the generation algorithm!!! */
99
#define ASTER_LIM 79
100
 
101
// Master task stuffs
102
PID master_pid;    // the PID of the master task
103
int current_task;  // the current position in the pattern array
104
 
105
// number of periodic tasks currently running...
106
int current_periodic_tasks = 0;
107
 
108
PID info_pid;    // the PID of the master task
109
 
110
 
111
/*
112
 * This function prints all the data read from the configuration file
113
 */
114
void print_conffile(char *name)
115
{
116
  int i;
117
 
118
  cprintf("--------------------------------------------------------------------\n");
119
  cprintf("Configuration file name        : %s\n", name);
120
  cprintf("Number of tasks in the pattern : %d\n", pattern_dim);
121
  cprintf("      Time Hard/Value      Dline       WCET Iterations Value Penalty\n");
122
  cprintf("--------------------------------------------------------------------\n");
123
 
124
  for (i=0; i<pattern_dim; i++) {
125
    cprintf("%10d %10d %10d %10d %10d %5d %7d\n",
126
            pattern[i].time,
127
            pattern[i].type,
128
            pattern[i].reldline,
129
            pattern[i].wcet,
130
            pattern[i].iterations,
131
            pattern[i].value,
132
            pattern[i].penalty);
133
  }
134
  cprintf("--------------------------------------------------------------------\n");
135
}
136
 
137
/*
138
 * main()
139
 */
140
 
141
void scenario(void);
142
void create_master_task(void);
143
void create_info_task(void);
144
void update_scenario(void);
145
void print_statistics(void);
146
 
147
int main(int argc, char **argv)
148
{
149
  srand(18);
150
 
151
  set_exchandler_grx();
152
 
153
  /*
154
   * Parse the configuration file
155
   */
156
  crunch_file(pattern, &pattern_dim, MAX_PATTERN);
157
 
158
  if (!pattern_dim) {
159
    cprintf("Nothing to do!\n");
160
    sys_end();
161
  }
162
 
163
  /*
164
   * Print configuration file
165
   */
166
  #ifdef DEBUG_CONFFILE
167
  print_conffile(argv[1]); return 0;
168
  #endif
169
 
170
  /*
171
   * Print the scenario
172
   */
173
  scenario();
174
 
175
  /*
176
   * Create the high priority task that will create all the periodic
177
   * and value tasks.
178
   */
179
  create_master_task();
180
 
181
  /*
182
   * Create a periodic task to display some statistical informations
183
   */
184
  create_info_task();
185
 
186
  /*
187
   * While in idle time, update the scenario
188
   */
189
  while (!finished || task_counter != 3) {
190
    update_scenario();
191
  }
192
 
193
  print_statistics();
194
 
195
  return 0;
196
}
197
 
198
 
199
/*
200
 *
201
 * MASTER TASK STUFFS
202
 *
203
 */
204
 
205
 
206
void activate_master_task(void *);
207
void *master_task(void *);
208
void *hard_task(void *);
209
void *value_task(void *);
210
 
211
void create_master_task()
212
{
213
  NRT_TASK_MODEL nrt;
214
  struct timespec t;
215
 
216
  nrt_task_default_model(nrt);
217
  nrt_task_def_usemath(nrt);
218
  nrt_task_def_ctrl_jet(nrt);
219
  nrt_task_def_save_arrivals(nrt);
220
 
221
  master_pid = task_create("master", master_task, &nrt, NULL);
222
  if(master_pid == -1) {
223
    cprintf("Cannot create the master task!!!\n");
224
    sys_end();
225
  }
226
 
227
  current_task = 0;
228
  NULL_TIMESPEC(&t);
229
  ADDUSEC2TIMESPEC(pattern[0].time, &t);
230
  kern_cli();
231
  kern_event_post(&t, activate_master_task, NULL);
232
  kern_sti();
233
}
234
 
235
void activate_master_task(void *arg)
236
{
237
  task_activate(master_pid);
238
}
239
 
240
void *master_task(void *arg)
241
{
242
  int current_time;
243
 
244
  HARD_TASK_MODEL hard;
245
  PID phard;
246
 
247
  VALUE_TASK_MODEL value;
248
 
249
  PID group_container_pid[100];
250
  int group_container_pattern[100];
251
  int group_container_index;
252
 
253
  // used to record the group_creation for value task
254
  int i;
255
  PID p;
256
 
257
  task_nopreempt();
258
 
259
  hard_task_default_model(hard);
260
  hard_task_def_usemath(hard);
261
  value_task_default_model(value);
262
  value_task_def_usemath(value);
263
 
264
  do {
265
    // current_task indexes the next task to be activated.
266
 
267
    current_time = pattern[current_task].time;
268
 
269
    // create and activate all the hard tasks with the same starting time
270
    if (!pattern[current_task].type) {
271
      do {
272
        #ifdef DEBUG_MASTER_HARDCREATE
273
          { int i=current_task; cprintf("%10d %10d %10d %10d %10d %5d %7d\n",
274
            pattern[i].time, pattern[i].type, pattern[i].reldline,
275
            pattern[i].wcet, pattern[i].iterations, pattern[i].value,
276
            pattern[i].penalty); }
277
        #endif
278
 
279
        hard_task_def_mit(hard, pattern[current_task].reldline);
280
        hard_task_def_wcet(hard, pattern[current_task].wcet);
281
        hard_task_def_arg(hard, (void *)current_task);
282
 
283
        phard = task_create("hard_task", hard_task, &hard, NULL);
284
        if (phard == NIL) {
285
          clear();
286
          cprintf("Cannot create hard task! (errno=%d)\n", errno);
287
          sys_end();
288
        }
289
        else {
290
          task_activate(phard);
291
          current_periodic_tasks++;
292
        }
293
 
294
        current_task++;
295
      } while (current_task != pattern_dim &&
296
               pattern[current_task].time == current_time &&
297
               !pattern[current_task].type);
298
    }
299
 
300
    // create and activate all the soft tasks with the same starting time
301
    if (current_task != pattern_dim &&
302
        pattern[current_task].time == current_time &&
303
        pattern[current_task].type) {
304
      group_container_index = 0;
305
 
306
      kern_cli();
307
      while (current_task != pattern_dim &&
308
             pattern[current_task].time == current_time &&
309
             pattern[current_task].type) {
310
 
311
        #ifdef DEBUG_MASTER_VALUECREATE
312
          { int i=current_task; cprintf("V%10d %10d %10d %10d %10d %5d %7d\n",
313
            pattern[i].time, pattern[i].type, pattern[i].reldline,
314
            pattern[i].wcet, pattern[i].iterations, pattern[i].value,
315
            pattern[i].penalty); }
316
        #endif
317
 
318
//  kern_printf("master_task: current_value=%d\n",current_value);
319
 
320
        value_task_def_wcet(value,pattern[current_task].wcet);
321
        value_task_def_dline(value,pattern[current_task].reldline);
322
        value_task_def_value(value,pattern[current_task].value);
323
        value_task_def_penalty(value,pattern[current_task].penalty);
324
        value_task_def_arg(value, (void *)current_task);
325
        p = group_create("value_task", value_task, (TASK_MODEL *)&value, NULL);
326
//        kern_printf("\nCreating %d PID = %d\n",current_task, p);
327
        // we need to know which task we are inserting, so we insert it in
328
        // a list to check them later
329
        group_container_pid[group_container_index]=p;
330
        group_container_pattern[group_container_index]=current_task;
331
        group_container_index++;
332
 
333
        current_task++;
334
      }
335
 
336
/*      {kern_printf("group_container: index=%d, 0=%d, 1=%d, 2=%d, 3=%d\n",
337
       group_container_index, group_container_pid[0], group_container_pid[1],
338
       group_container_pid[2], group_container_pid[3]);}*/
339
 
340
      guarantee();
341
//      kern_printf("group_container_index=%d\n",group_container_index);
342
      for (i=0; i<group_container_index; i++) {
343
//      {kern_printf("i=%d, group_container: index=%d, 0=%d, 1=%d, 2=%d, 3=%d\n",i,
344
//       group_container_index, group_container_pid[0], group_container_pid[1],
345
//       group_container_pid[2], group_container_pid[3]);}
346
        p = group_container_pid[i];
347
//        kern_printf("+%d\n",p);
348
        max_created_value += pattern[group_container_pattern[i]].value;
349
        min_created_value -= pattern[group_container_pattern[i]].penalty;
350
 
351
        if (p == NIL) continue;
352
 
353
        if (crunch_taskaccepted(p)) {
354
          // we need to pass the original model for the task...
355
          // but just the common part is needed O:-)
356
 
357
          // account for the penalty before the task starts
358
          current_value -= pattern[group_container_pattern[i]].penalty;
359
          max_value += pattern[group_container_pattern[i]].value;
360
          min_value -= pattern[group_container_pattern[i]].penalty;
361
 
362
          value_task_def_arg(value, (void *)group_container_pattern[i]);
363
          group_create_accept(p,(TASK_MODEL *)&value);
364
//          kern_printf("Accetto task PID=%d\n",p);
365
        }
366
        else {
367
          group_container_pid[i] = NIL;
368
//          kern_printf("Rigetto task PID=%d\n",p);
369
 
370
          group_create_reject(p);
371
        }
372
      }
373
      kern_sti();
374
 
375
      for (i=0; i<group_container_index; i++) {
376
//        kern_printf("Attivo %d PID=%d\n",i,group_container_pid[i]);
377
        if (group_container_pid[i] != NIL)
378
          task_activate(group_container_pid[i]);
379
      }
380
    }
381
 
382
    if (current_task != pattern_dim) {
383
      struct timespec t;
384
      NULL_TIMESPEC(&t);
385
      ADDUSEC2TIMESPEC(pattern[current_task].time, &t);
386
      kern_cli();
387
      kern_event_post(&t, activate_master_task, NULL);
388
      task_endcycle();
389
    }
390
  } while(current_task != pattern_dim);
391
 
392
  /* since all the tasks has been activated, the master_task will stop
393
     forever.
394
     In that way we can look at the elapsed time consumed by the master task.
395
  */
396
//  task_nopreempt();
397
  finished = 1;
398
  task_endcycle();
399
 
400
  return (void *)0;
401
}
402
 
403
#define DEFAULT_SHIFT 1000000
404
void *hard_task(void *arg)
405
{
406
  struct timespec dl, curr;  // for deadline checking
407
 
408
  int index, j, x, y, temp;
409
  char s[2];
410
 
411
  struct timespec t;
412
  int b;
413
 
414
  task_setcanceltype(TASK_CANCEL_ASYNCHRONOUS,&temp);
415
 
416
  index = (int)arg;
417
 
418
  NULL_TIMESPEC(&t);
419
  ADDUSEC2TIMESPEC((DEFAULT_SHIFT*2)/3,&t);
420
 
421
  b = TIMESPEC_A_LT_B(&proc_table[exec_shadow].request_time,&t);
422
 
423
  do {
424
    x = 0;
425
    y = rand() % 6 + 3;
426
    s[0] = '*'; s[1] = 0;
427
    while (x < ASTER_LIM) {
428
      for (j=0; j<pattern[index].iterations; j++) {
429
        s[0] = '*' + rand() % 100;
430
        puts_xy(x,y,rand()%15+1,s);
431
      }
432
 
433
      // Dline check :-) it is not perfect, but it works :-)
434
      kern_cli();
435
      ll_gettime(TIME_EXACT,&curr);
436
      dl = proc_table[exec_shadow].request_time;
437
      ADDUSEC2TIMESPEC(pattern[index].reldline, &dl);
438
      if (TIMESPEC_A_LT_B(&dl,&curr)) {
439
        cprintf("\n\nPERIODIC TASK %d: Deadline miss!!!\n", index);
440
        cprintf("current time= %10ld sec, %10ld ns\n", curr.tv_sec, curr.tv_nsec);
441
        cprintf("deadline    = %10ld sec, %10ld ns\n", dl.tv_sec, dl.tv_nsec);
442
        sys_end();
443
      }
444
      task_endcycle();
445
 
446
      puts_xy(x,y,WHITE," ");
447
      x++;
448
    }
449
  } while (b && !finished);
450
 
451
  kern_cli();
452
 
453
  // account for a finished task
454
  current_finished_tasks++;
455
  current_periodic_tasks--;
456
 
457
  // Dline check :-) it is not perfect, but it works :-)
458
  ll_gettime(TIME_EXACT,&curr);
459
  dl=proc_table[exec_shadow].request_time;
460
  ADDUSEC2TIMESPEC(pattern[index].reldline, &dl);
461
  if (TIMESPEC_A_LT_B(&dl,&curr)) {
462
    cprintf("\n\nPERIODIC TASK %d: Deadline miss!!!\n", index);
463
    cprintf("current time= %10ld sec, %10ld ns\n", curr.tv_sec, curr.tv_nsec);
464
    cprintf("deadline    = %10ld sec, %10ld ns\n", dl.tv_sec, dl.tv_nsec);
465
    sys_end();
466
  }
467
 
468
  return (void *)0;
469
}
470
 
471
void *value_task(void *arg)
472
{
473
  struct timespec dl, curr;  // for deadline checking
474
  int index, j, x, y, temp;
475
  char s[2];
476
 
477
  task_setcanceltype(TASK_CANCEL_ASYNCHRONOUS,&temp);
478
 
479
  index = (int)arg;
480
 
481
  //  kern_printf("Ú%dÙ",index);
482
 
483
  x = rand() % 26 + 1;
484
  y = rand() % 3  + 10;
485
  s[0] = '*'; s[1] = 0;
486
  for (j=0; j<pattern[index].iterations; j++) {
487
    s[0] = '*' + rand() % 100;
488
    puts_xy(x,y,rand()%15+1,s);
489
  }
490
//  kern_printf("*%d*\n",exec_shadow);
491
 
492
  kern_cli();
493
 
494
  // account for a finished task
495
  current_finished_tasks++;
496
 
497
  // Dline check :-) it is not perfect, but it works :-)
498
  ll_gettime(TIME_EXACT,&curr);
499
  TIMESPEC_ASSIGN(&dl, &proc_table[exec_shadow].request_time);
500
  ADDUSEC2TIMESPEC(pattern[index].reldline, &dl);
501
 
502
  if (TIMESPEC_A_GT_B(&dl,&curr)) {
503
    // The task finishes in time. account for the value
504
    current_value += pattern[index].penalty + pattern[index].value;
505
  }
506
  //  kern_printf("value: arg=%d current_value=%d pen=%d val=%d\n",arg,current_value,
507
  //  ((struct task_struct *)arg)->penalty,
508
  //      ((struct task_struct *)arg)->value);
509
 
510
  return (void *)0;
511
}
512
 
513
void *info_task(void *);
514
 
515
void create_info_task(void)
516
{
517
  HARD_TASK_MODEL hard;
518
 
519
  hard_task_default_model(hard);
520
  hard_task_def_usemath(hard);
521
  hard_task_def_mit(hard, 2000000);
522
  hard_task_def_wcet(hard, 2000);
523
 
524
  info_pid = task_create("info_task", info_task, &hard, NULL);
525
  task_activate(info_pid);
526
}
527
 
528
void *info_task(void *arg)
529
{
530
  int x;
531
 
532
  task_setcanceltype(TASK_CANCEL_ASYNCHRONOUS,&x);
533
 
534
  for (;;) {
535
    update_scenario();
536
    task_endcycle();
537
  }
538
}
539
 
540
void print_statistics(void)
541
{
542
  TIME sum;
543
 
544
  clear();
545
 
546
  jet_getstat(master_pid, &sum, 0, 0, 0);
547
  task_activate(master_pid);         // let the master task die...
548
  task_kill(info_pid);
549
 
550
  clear();
551
  cprintf("CRUNCH 1.12 - by Paolo Gai 2001\n\n");
552
  cprintf("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n\n");
553
  cprintf("Final Results:\n\n");
554
 
555
  cprintf("The Master task elapsed time   : %d microseconds.\n\n",(int)sum);
556
 
557
  cprintf("Total number of tasks          : %9d\n", pattern_dim);
558
  cprintf("Total number of scheduled tasks: %9d\n\n",current_task);
559
 
560
  cprintf("Per.tasks created but not ended: %9d\n\n",current_periodic_tasks);
561
  cprintf("Maximum created value          : %9d\n",max_created_value);
562
  cprintf("Minimum created value          : %9d\n\n",min_created_value);
563
  cprintf("Maximum value                  : %9d\n",max_value);
564
  cprintf("Minimum value                  : %9d\n\n",min_value);
565
  cprintf("Total Value (from Module)      : %9d\n",crunch_getvalue());
566
  cprintf("Total Value (from CRUNCH)      : %9d\n",current_value);
567
  cprintf("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n\n");
568
}
569
 
570
/*
571
 * Scenario
572
 */
573
 
574
void scenario(void)
575
{
576
  char buf[100];
577
  clear();
578
 
579
  puts_xy(0, 0,BLUE , "CRUNCH 1.12");
580
  puts_xy(15,0,GREEN, "by Paolo Gai 2001");
581
  puts_xy(0, 2,WHITE, "ÄÄÄ Hard Periodic Tasks ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
582
  puts_xy(0, 9,WHITE, "ÂÄÄ Soft Aperiodic Tasks ÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
583
  puts_xy(0,10,WHITE, "³                          ³");
584
  puts_xy(0,11,WHITE, "³                          ³");
585
  puts_xy(0,12,WHITE, "³                          ³");
586
  puts_xy(0,13,WHITE, "ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ");
587
  puts_xy(29,10,YELLOW, "Statistics:");
588
  sprintf(buf,"Total: %5d Already created:        Periodic:",pattern_dim);
589
  puts_xy(29,11,CYAN,   buf);
590
  puts_xy(29,12,BLUE,   "Value reported (by Modules):");
591
  puts_xy(29,13,RED,    "               (by CRUNCH ):");
592
  puts_xy(69,12,7,   "Min:");
593
  puts_xy(69,13,7,   "Max:");
594
 
595
  puts_xy(0,14,WHITE, "ÄÄÄ Debug space for Logging Module functions... ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
596
  place(0,15);
597
}
598
 
599
void update_scenario(void)
600
{
601
  char buf[100];
602
  sprintf(buf,"%5d",current_task);
603
  puts_xy(58,11,WHITE,buf);
604
  sprintf(buf,"%5d",current_periodic_tasks);
605
  puts_xy(75,11,WHITE,buf);
606
  sprintf(buf,"%5d",crunch_getvalue());
607
  puts_xy(58,12,WHITE,buf);
608
  sprintf(buf,"%5d",current_value);
609
  puts_xy(58,13,WHITE,buf);
610
  sprintf(buf,"%6d",min_value);
611
  puts_xy(74,12,WHITE,buf);
612
  sprintf(buf,"%6d",max_value);
613
  puts_xy(74,13,WHITE,buf);
614
}