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:16 pj Exp $
22
 
23
 File:        $File$
24
 Revision:    $Revision: 1.1 $
25
 Last update: $Date: 2004-07-05 14:17:16 $
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
 
87
/* the number of finished tasks */
88
int current_finished_tasks = 0;
89
 
90
/* this flag is triggered by the master task  when it finishes */
91
int finished = 0;
92
 
93
/* number of instances of an hard tasks
94
   NOTE that it is 79 and not 80 as in the generation algorithm!!! */
95
#define ASTER_LIM 79
96
 
97
// Master task stuffs
98
PID master_pid;    // the PID of the master task
99
int current_task;  // the current position in the pattern array
100
 
101
// number of periodic tasks currently running...
102
int current_periodic_tasks = 0;
103
 
104
 
105
 
106
/*
107
 * This function prints all the data read from the configuration file
108
 */
109
void print_conffile(char *name)
110
{
111
  int i;
112
 
113
  cprintf("--------------------------------------------------------------------\n");
114
  cprintf("Configuration file name        : %s\n", name);
115
  cprintf("Number of tasks in the pattern : %d\n", pattern_dim);
116
  cprintf("      Time Hard/Value      Dline       WCET Iterations Value Penalty\n");
117
  cprintf("--------------------------------------------------------------------\n");
118
 
119
  for (i=0; i<pattern_dim; i++) {
120
    cprintf("%10d %10d %10d %10d %10d %5d %7d\n",
121
            pattern[i].time,
122
            pattern[i].type,
123
            pattern[i].reldline,
124
            pattern[i].wcet,
125
            pattern[i].iterations,
126
            pattern[i].value,
127
            pattern[i].penalty);
128
  }
129
  cprintf("--------------------------------------------------------------------\n");
130
}
131
 
132
/*
133
 * main()
134
 */
135
 
136
void scenario(void);
137
void create_master_task(void);
138
void update_scenario(void);
139
void print_statistics(void);
140
 
141
int main(int argc, char **argv)
142
{
143
  srand(18);
144
 
145
  set_exchandler_grx();
146
 
147
  /*
148
   * Parse the configuration file
149
   */
150
  crunch_file(pattern, &pattern_dim, MAX_PATTERN);
151
 
152
  if (!pattern_dim) {
153
    cprintf("Nothing to do!\n");
154
    sys_end();
155
  }
156
 
157
  /*
158
   * Print configuration file
159
   */
160
  #ifdef DEBUG_CONFFILE
161
  print_conffile(argv[1]); return 0;
162
  #endif
163
 
164
  /*
165
   * Print the scenario
166
   */
167
  scenario();
168
 
169
  /*
170
   * Create the high priority task that will create all the periodic
171
   * and value tasks.
172
   */
173
  create_master_task();
174
 
175
  /*
176
   * While in idle time, update the scenario
177
   */
178
  while (!finished || task_counter != 2) {
179
    update_scenario();
180
  }
181
 
182
  print_statistics();
183
 
184
  return 0;
185
}
186
 
187
 
188
/*
189
 *
190
 * MASTER TASK STUFFS
191
 *
192
 */
193
 
194
 
195
void activate_master_task(void *);
196
void *master_task(void *);
197
void *hard_task(void *);
198
void *value_task(void *);
199
 
200
void create_master_task()
201
{
202
  NRT_TASK_MODEL nrt;
203
  struct timespec t;
204
 
205
  nrt_task_default_model(nrt);
206
  nrt_task_def_usemath(nrt);
207
  nrt_task_def_ctrl_jet(nrt);
208
  nrt_task_def_save_arrivals(nrt);
209
 
210
  master_pid = task_create("master", master_task, &nrt, NULL);
211
  if(master_pid == -1) {
212
    cprintf("Cannot create the master task!!!\n");
213
    sys_end();
214
  }
215
 
216
  current_task = 0;
217
  NULL_TIMESPEC(&t);
218
  ADDUSEC2TIMESPEC(pattern[0].time, &t);
219
  kern_cli();
220
  kern_event_post(&t, activate_master_task, NULL);
221
  kern_sti();
222
}
223
 
224
void activate_master_task(void *arg)
225
{
226
  task_activate(master_pid);
227
}
228
 
229
void *master_task(void *arg)
230
{
231
  int current_time;
232
 
233
  HARD_TASK_MODEL hard;
234
  PID phard;
235
 
236
  VALUE_TASK_MODEL value;
237
 
238
  PID group_container_pid[100];
239
  int group_container_pattern[100];
240
  int group_container_index;
241
 
242
  // used to record the group_creation for value task
243
  int i;
244
  PID p;
245
 
246
  task_nopreempt();
247
 
248
  hard_task_default_model(hard);
249
  hard_task_def_usemath(hard);
250
  value_task_default_model(value);
251
  value_task_def_usemath(value);
252
 
253
  do {
254
    // current_task indexes the next task to be activated.
255
 
256
    current_time = pattern[current_task].time;
257
 
258
    // create and activate all the hard tasks with the same starting time
259
    if (!pattern[current_task].type) {
260
      do {
261
        #ifdef DEBUG_MASTER_HARDCREATE
262
          { int i=current_task; cprintf("%10d %10d %10d %10d %10d %5d %7d\n",
263
            pattern[i].time, pattern[i].type, pattern[i].reldline,
264
            pattern[i].wcet, pattern[i].iterations, pattern[i].value,
265
            pattern[i].penalty); }
266
        #endif
267
 
268
        hard_task_def_mit(hard, pattern[current_task].reldline);
269
        hard_task_def_wcet(hard, pattern[current_task].wcet);
270
        hard_task_def_arg(hard, (void *)current_task);
271
 
272
        phard = task_create("hard_task", hard_task, &hard, NULL);
273
        if (phard == NIL) {
274
          clear();
275
          cprintf("Cannot create hard task! (errno=%d)\n", errno);
276
          sys_end();
277
        }
278
        else {
279
          task_activate(phard);
280
          current_periodic_tasks++;
281
        }
282
 
283
        current_task++;
284
      } while (current_task != pattern_dim &&
285
               pattern[current_task].time == current_time &&
286
               !pattern[current_task].type);
287
    }
288
 
289
    // create and activate all the soft tasks with the same starting time
290
    if (current_task != pattern_dim &&
291
        pattern[current_task].time == current_time &&
292
        pattern[current_task].type) {
293
      group_container_index = 0;
294
 
295
      kern_cli();
296
      while (current_task != pattern_dim &&
297
             pattern[current_task].time == current_time &&
298
             pattern[current_task].type) {
299
 
300
        #ifdef DEBUG_MASTER_VALUECREATE
301
          { int i=current_task; cprintf("V%10d %10d %10d %10d %10d %5d %7d\n",
302
            pattern[i].time, pattern[i].type, pattern[i].reldline,
303
            pattern[i].wcet, pattern[i].iterations, pattern[i].value,
304
            pattern[i].penalty); }
305
        #endif
306
 
307
        // account for the penalty before the task starts
308
        current_value -= pattern[current_task].penalty;
309
//  kern_printf("master_task: current_value=%d\n",current_value);
310
 
311
        value_task_def_wcet(value,pattern[current_task].wcet);
312
        value_task_def_dline(value,pattern[current_task].reldline);
313
        value_task_def_value(value,pattern[current_task].value);
314
        value_task_def_penalty(value,pattern[current_task].penalty);
315
        value_task_def_arg(value, (void *)current_task);
316
        p = group_create("value_task", value_task, (TASK_MODEL *)&value, NULL);
317
//        kern_printf("\nCreating %d PID = %d\n",current_task, p);
318
        // we need to know which task we are inserting, so we insert it in
319
        // a list to check them later
320
        group_container_pid[group_container_index]=p;
321
        group_container_pattern[group_container_index]=current_task;
322
        group_container_index++;
323
 
324
        current_task++;
325
      }
326
 
327
/*      {kern_printf("group_container: index=%d, 0=%d, 1=%d, 2=%d, 3=%d\n",
328
       group_container_index, group_container_pid[0], group_container_pid[1],
329
       group_container_pid[2], group_container_pid[3]);}*/
330
 
331
      guarantee();
332
//      kern_printf("group_container_index=%d\n",group_container_index);
333
      for (i=0; i<group_container_index; i++) {
334
//      {kern_printf("i=%d, group_container: index=%d, 0=%d, 1=%d, 2=%d, 3=%d\n",i,
335
//       group_container_index, group_container_pid[0], group_container_pid[1],
336
//       group_container_pid[2], group_container_pid[3]);}
337
        p = group_container_pid[i];
338
//        kern_printf("+%d\n",p);
339
        if (crunch_taskaccepted(p)) {
340
          // we need to pass the original model for the task...
341
          // but just the common part is needed O:-)
342
          value_task_def_arg(value, (void *)group_container_pattern[i]);
343
          group_create_accept(p,(TASK_MODEL *)&value);
344
//          kern_printf("Accetto task PID=%d\n",p);
345
        }
346
        else {
347
          group_container_pid[i] = NIL;
348
//          kern_printf("Rigetto task PID=%d\n",p);
349
 
350
          group_create_reject(p);
351
        }
352
      }
353
      kern_sti();
354
 
355
      for (i=0; i<group_container_index; i++) {
356
//        kern_printf("Attivo %d PID=%d\n",i,group_container_pid[i]);
357
        if (group_container_pid[i] != NIL)
358
          task_activate(group_container_pid[i]);
359
      }
360
    }
361
 
362
    if (current_task != pattern_dim) {
363
      struct timespec t;
364
      NULL_TIMESPEC(&t);
365
      ADDUSEC2TIMESPEC(pattern[current_task].time, &t);
366
      kern_cli();
367
      kern_event_post(&t, activate_master_task, NULL);
368
      task_endcycle();
369
    }
370
  } while(current_task != pattern_dim);
371
 
372
  /* since all the tasks has been activated, the master_task will stop
373
     forever.
374
     In that way we can look at the elapsed time consumed by the master task.
375
  */
376
//  task_nopreempt();
377
  finished = 1;
378
  task_endcycle();
379
 
380
  return (void *)0;
381
}
382
 
383
 
384
void *hard_task(void *arg)
385
{
386
  struct timespec dl, curr;  // for deadline checking
387
 
388
  int index, j, x, y;
389
  char s[2];
390
 
391
  task_setcanceltype(TASK_CANCEL_ASYNCHRONOUS,&index);
392
 
393
  index = (int)arg;
394
 
395
  x = 0;
396
  y = rand() % 6 + 3;
397
  s[0] = '*'; s[1] = 0;
398
  while (x < ASTER_LIM) {
399
    for (j=0; j<pattern[index].iterations; j++) {
400
      s[0] = '*' + rand() % 100;
401
      puts_xy(x,y,rand()%15+1,s);
402
    }
403
 
404
    // Dline check :-) it is not perfect, but it works :-)
405
    kern_cli();
406
    ll_gettime(TIME_EXACT,&curr);
407
    dl = proc_table[exec_shadow].request_time;
408
    ADDUSEC2TIMESPEC(pattern[index].reldline, &dl);
409
    if (TIMESPEC_A_LT_B(&dl,&curr)) {
410
      cprintf("\n\nPERIODIC TASK %d: Deadline miss!!!\n", index);
411
      cprintf("current time= %10ld sec, %10ld ns\n", curr.tv_sec, curr.tv_nsec);
412
      cprintf("deadline    = %10ld sec, %10ld ns\n", dl.tv_sec, dl.tv_nsec);
413
      sys_end();
414
    }
415
    task_endcycle();
416
 
417
    puts_xy(x,y,WHITE," ");
418
    x++;
419
  }
420
 
421
  kern_cli();
422
 
423
  // account for a finished task
424
  current_finished_tasks++;
425
  current_periodic_tasks--;
426
 
427
  // Dline check :-) it is not perfect, but it works :-)
428
  ll_gettime(TIME_EXACT,&curr);
429
  dl=proc_table[exec_shadow].request_time;
430
  ADDUSEC2TIMESPEC(pattern[index].reldline, &dl);
431
  if (TIMESPEC_A_LT_B(&dl,&curr)) {
432
    cprintf("\n\nPERIODIC TASK %d: Deadline miss!!!\n", index);
433
    cprintf("current time= %10ld sec, %10ld ns\n", curr.tv_sec, curr.tv_nsec);
434
    cprintf("deadline    = %10ld sec, %10ld ns\n", dl.tv_sec, dl.tv_nsec);
435
    sys_end();
436
  }
437
 
438
  return (void *)0;
439
}
440
 
441
void *value_task(void *arg)
442
{
443
  struct timespec dl, curr;  // for deadline checking
444
  int index, j, x, y;
445
  char s[2];
446
 
447
  task_setcanceltype(TASK_CANCEL_ASYNCHRONOUS,&index);
448
  index = (int)arg;
449
//  kern_printf("Ú%dÙ",index);
450
 
451
  x = rand() % 26 + 1;
452
  y = rand() % 3  + 10;
453
  s[0] = '*'; s[1] = 0;
454
  for (j=0; j<pattern[index].iterations; j++) {
455
    s[0] = '*' + rand() % 100;
456
    puts_xy(x,y,rand()%15+1,s);
457
  }
458
//  kern_printf("*%d*\n",exec_shadow);
459
 
460
  kern_cli();
461
 
462
  // account for a finished task
463
  current_finished_tasks++;
464
 
465
  // Dline check :-) it is not perfect, but it works :-)
466
  ll_gettime(TIME_EXACT,&curr);
467
  TIMESPEC_ASSIGN(&dl, &proc_table[exec_shadow].request_time);
468
  ADDUSEC2TIMESPEC(pattern[index].reldline, &dl);
469
 
470
  if (TIMESPEC_A_GT_B(&dl,&curr)) {
471
    // The task finishes in time. account for the value
472
    current_value += pattern[index].penalty + pattern[index].value;
473
  }
474
  //  kern_printf("value: arg=%d current_value=%d pen=%d val=%d\n",arg,current_value,
475
  //  ((struct task_struct *)arg)->penalty,
476
  //      ((struct task_struct *)arg)->value);
477
 
478
  return (void *)0;
479
}
480
 
481
void print_statistics(void)
482
{
483
  TIME sum;
484
 
485
  clear();
486
 
487
  jet_getstat(master_pid, &sum, 0, 0, 0);
488
  task_activate(master_pid);         // let the master task die...
489
 
490
  clear();
491
  cprintf("CRUNCH 1.0 - by Paolo Gai 2001\n\n");
492
  cprintf("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n\n");
493
  cprintf("Final Results:\n\n");
494
 
495
  cprintf("The Master task elapsed time   : %d microseconds.\n\n",(int)sum);
496
 
497
  cprintf("Total number of tasks          : %5d\n", pattern_dim);
498
  cprintf("Total number of scheduled tasks: %5d\n\n",current_task);
499
 
500
  cprintf("Per.tasks created but not ended: %5d\n\n",current_periodic_tasks);
501
  cprintf("Total Value (from Module)      : %5d\n",crunch_getvalue());
502
  cprintf("Total Value (from CRUNCH)      : %5d\n",current_value);
503
  cprintf("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n\n");
504
}
505
 
506
/*
507
 * Scenario
508
 */
509
 
510
void scenario(void)
511
{
512
  char buf[100];
513
  clear();
514
 
515
  puts_xy(0, 0,BLUE , "CRUNCH 1.0");
516
  puts_xy(15,0,GREEN, "by Paolo Gai 2001");
517
  puts_xy(0, 2,WHITE, "ÄÄÄ Hard Periodic Tasks ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
518
  puts_xy(0, 9,WHITE, "ÂÄÄ Soft Aperiodic Tasks ÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
519
  puts_xy(0,10,WHITE, "³                          ³");
520
  puts_xy(0,11,WHITE, "³                          ³");
521
  puts_xy(0,12,WHITE, "³                          ³");
522
  puts_xy(0,13,WHITE, "ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ");
523
  puts_xy(29,10,YELLOW, "Statistics:");
524
  sprintf(buf,"Total: %5d Already created:        Periodic:",pattern_dim);
525
  puts_xy(29,11,CYAN,   buf);
526
  puts_xy(29,12,BLUE,   "Value reported (by Modules):");
527
  puts_xy(29,13,RED,    "               (by CRUNCH ):");
528
 
529
  puts_xy(0,14,WHITE, "ÄÄÄ Debug space for Logging Module functions... ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
530
  place(0,15);
531
}
532
 
533
void update_scenario(void)
534
{
535
  char buf[100];
536
  sprintf(buf,"%5d",current_task);
537
  puts_xy(58,11,WHITE,buf);
538
  sprintf(buf,"%5d",current_periodic_tasks);
539
  puts_xy(75,11,WHITE,buf);
540
  sprintf(buf,"%5d",crunch_getvalue());
541
  puts_xy(58,12,WHITE,buf);
542
  sprintf(buf,"%5d",current_value);
543
  puts_xy(58,13,WHITE,buf);
544
}