Blame |
Last modification |
View Log
| RSS feed
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
/**
------------
CVS : $Id: crunch.c,v 1.1 2004-07-05 14:17:12 pj Exp $
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2004-07-05 14:17:12 $
------------
**/
/*
* Copyright (C) 2001 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/*
* Crunch.c
*/
//#define DEBUG_CONFFILE
//#define DEBUG_MASTER_HARDCREATE
//#define DEBUG_MASTER_VALUECREATE
#include "valmodel.h"
#include "crunch.h"
#include <kernel/kern.h>
/*
* This small application simply reads the tasks and executes them.
* When they are all finished, the system shuts down.
*/
/*
* this table contains all the tasks information collected from the
* configuration file
*/
#define MAX_PATTERN 100000
struct task_struct pattern
[MAX_PATTERN
];
int pattern_dim
;
/* This is some data collected by the task destructors that
* can be useful for understanding how the Module works */
/* this int contains the value as seen by the application */
int current_value
= 0;
int max_value
= 0;
int min_value
= 0;
int max_created_value
= 0;
int min_created_value
= 0;
/* the number of finished tasks */
int current_finished_tasks
= 0;
/* this flag is triggered by the master task when it finishes */
int finished
= 0;
/* number of instances of an hard tasks
NOTE that it is 79 and not 80 as in the generation algorithm!!! */
#define ASTER_LIM 79
// Master task stuffs
PID master_pid
; // the PID of the master task
int current_task
; // the current position in the pattern array
// number of periodic tasks currently running...
int current_periodic_tasks
= 0;
PID info_pid
; // the PID of the master task
/*
* This function prints all the data read from the configuration file
*/
void print_conffile
(char *name
)
{
int i
;
cprintf
("--------------------------------------------------------------------\n");
cprintf
("Configuration file name : %s\n", name
);
cprintf
("Number of tasks in the pattern : %d\n", pattern_dim
);
cprintf
(" Time Hard/Value Dline WCET Iterations Value Penalty\n");
cprintf
("--------------------------------------------------------------------\n");
for (i
=0; i
<pattern_dim
; i
++) {
cprintf
("%10d %10d %10d %10d %10d %5d %7d\n",
pattern
[i
].
time,
pattern
[i
].
type,
pattern
[i
].
reldline,
pattern
[i
].
wcet,
pattern
[i
].
iterations,
pattern
[i
].
value,
pattern
[i
].
penalty);
}
cprintf
("--------------------------------------------------------------------\n");
}
/*
* main()
*/
void scenario
(void);
void create_master_task
(void);
void create_info_task
(void);
void update_scenario
(void);
void print_statistics
(void);
int main
(int argc
, char **argv
)
{
srand(18);
set_exchandler_grx
();
/*
* Parse the configuration file
*/
crunch_file
(pattern
, &pattern_dim
, MAX_PATTERN
);
if (!pattern_dim
) {
cprintf
("Nothing to do!\n");
sys_end
();
}
/*
* Print configuration file
*/
#ifdef DEBUG_CONFFILE
print_conffile
(argv
[1]); return 0;
#endif
/*
* Print the scenario
*/
scenario
();
/*
* Create the high priority task that will create all the periodic
* and value tasks.
*/
create_master_task
();
/*
* Create a periodic task to display some statistical informations
*/
create_info_task
();
/*
* While in idle time, update the scenario
*/
while (!finished
|| task_counter
!= 3) {
update_scenario
();
}
print_statistics
();
return 0;
}
/*
*
* MASTER TASK STUFFS
*
*/
void activate_master_task
(void *);
void *master_task
(void *);
void *hard_task
(void *);
void *value_task
(void *);
void create_master_task
()
{
NRT_TASK_MODEL nrt
;
struct timespec t
;
nrt_task_default_model
(nrt
);
nrt_task_def_usemath
(nrt
);
nrt_task_def_ctrl_jet
(nrt
);
nrt_task_def_save_arrivals
(nrt
);
master_pid
= task_create
("master", master_task
, &nrt
, NULL
);
if(master_pid
== -1) {
cprintf
("Cannot create the master task!!!\n");
sys_end
();
}
current_task
= 0;
NULL_TIMESPEC
(&t
);
ADDUSEC2TIMESPEC
(pattern
[0].
time, &t
);
kern_cli
();
kern_event_post
(&t
, activate_master_task
, NULL
);
kern_sti
();
}
void activate_master_task
(void *arg
)
{
task_activate
(master_pid
);
}
void *master_task
(void *arg
)
{
int current_time
;
HARD_TASK_MODEL hard
;
PID phard
;
VALUE_TASK_MODEL value
;
PID group_container_pid
[100];
int group_container_pattern
[100];
int group_container_index
;
// used to record the group_creation for value task
int i
;
PID p
;
task_nopreempt
();
hard_task_default_model
(hard
);
hard_task_def_usemath
(hard
);
value_task_default_model
(value
);
value_task_def_usemath
(value
);
do {
// current_task indexes the next task to be activated.
current_time
= pattern
[current_task
].
time;
// create and activate all the hard tasks with the same starting time
if (!pattern
[current_task
].
type) {
do {
#ifdef DEBUG_MASTER_HARDCREATE
{ int i
=current_task
; cprintf
("%10d %10d %10d %10d %10d %5d %7d\n",
pattern
[i
].
time, pattern
[i
].
type, pattern
[i
].
reldline,
pattern
[i
].
wcet, pattern
[i
].
iterations, pattern
[i
].
value,
pattern
[i
].
penalty); }
#endif
hard_task_def_mit
(hard
, pattern
[current_task
].
reldline);
hard_task_def_wcet
(hard
, pattern
[current_task
].
wcet);
hard_task_def_arg
(hard
, (void *)current_task
);
phard
= task_create
("hard_task", hard_task
, &hard
, NULL
);
if (phard
== NIL
) {
clear
();
cprintf
("Cannot create hard task! (errno=%d)\n", errno
);
sys_end
();
}
else {
task_activate
(phard
);
current_periodic_tasks
++;
}
current_task
++;
} while (current_task
!= pattern_dim
&&
pattern
[current_task
].
time == current_time
&&
!pattern
[current_task
].
type);
}
// create and activate all the soft tasks with the same starting time
if (current_task
!= pattern_dim
&&
pattern
[current_task
].
time == current_time
&&
pattern
[current_task
].
type) {
group_container_index
= 0;
kern_cli
();
while (current_task
!= pattern_dim
&&
pattern
[current_task
].
time == current_time
&&
pattern
[current_task
].
type) {
#ifdef DEBUG_MASTER_VALUECREATE
{ int i
=current_task
; cprintf
("V%10d %10d %10d %10d %10d %5d %7d\n",
pattern
[i
].
time, pattern
[i
].
type, pattern
[i
].
reldline,
pattern
[i
].
wcet, pattern
[i
].
iterations, pattern
[i
].
value,
pattern
[i
].
penalty); }
#endif
// kern_printf("master_task: current_value=%d\n",current_value);
value_task_def_wcet
(value
,pattern
[current_task
].
wcet);
value_task_def_dline
(value
,pattern
[current_task
].
reldline);
value_task_def_value
(value
,pattern
[current_task
].
value);
value_task_def_penalty
(value
,pattern
[current_task
].
penalty);
value_task_def_arg
(value
, (void *)current_task
);
p
= group_create
("value_task", value_task
, (TASK_MODEL
*)&value
, NULL
);
// kern_printf("\nCreating %d PID = %d\n",current_task, p);
// we need to know which task we are inserting, so we insert it in
// a list to check them later
group_container_pid
[group_container_index
]=p
;
group_container_pattern
[group_container_index
]=current_task
;
group_container_index
++;
current_task
++;
}
/* {kern_printf("group_container: index=%d, 0=%d, 1=%d, 2=%d, 3=%d\n",
group_container_index, group_container_pid[0], group_container_pid[1],
group_container_pid[2], group_container_pid[3]);}*/
guarantee
();
// kern_printf("group_container_index=%d\n",group_container_index);
for (i
=0; i
<group_container_index
; i
++) {
// {kern_printf("i=%d, group_container: index=%d, 0=%d, 1=%d, 2=%d, 3=%d\n",i,
// group_container_index, group_container_pid[0], group_container_pid[1],
// group_container_pid[2], group_container_pid[3]);}
p
= group_container_pid
[i
];
// kern_printf("+%d\n",p);
max_created_value
+= pattern
[group_container_pattern
[i
]].
value;
min_created_value
-= pattern
[group_container_pattern
[i
]].
penalty;
if (p
== NIL
) continue;
if (crunch_taskaccepted
(p
)) {
// we need to pass the original model for the task...
// but just the common part is needed O:-)
// account for the penalty before the task starts
current_value
-= pattern
[group_container_pattern
[i
]].
penalty;
max_value
+= pattern
[group_container_pattern
[i
]].
value;
min_value
-= pattern
[group_container_pattern
[i
]].
penalty;
value_task_def_arg
(value
, (void *)group_container_pattern
[i
]);
group_create_accept
(p
,(TASK_MODEL
*)&value
);
// kern_printf("Accetto task PID=%d\n",p);
}
else {
group_container_pid
[i
] = NIL
;
// kern_printf("Rigetto task PID=%d\n",p);
group_create_reject
(p
);
}
}
kern_sti
();
for (i
=0; i
<group_container_index
; i
++) {
// kern_printf("Attivo %d PID=%d\n",i,group_container_pid[i]);
if (group_container_pid
[i
] != NIL
)
task_activate
(group_container_pid
[i
]);
}
}
if (current_task
!= pattern_dim
) {
struct timespec t
;
NULL_TIMESPEC
(&t
);
ADDUSEC2TIMESPEC
(pattern
[current_task
].
time, &t
);
kern_cli
();
kern_event_post
(&t
, activate_master_task
, NULL
);
task_endcycle
();
}
} while(current_task
!= pattern_dim
);
/* since all the tasks has been activated, the master_task will stop
forever.
In that way we can look at the elapsed time consumed by the master task.
*/
// task_nopreempt();
finished
= 1;
task_endcycle
();
return (void *)0;
}
#define DEFAULT_SHIFT 1000000
void *hard_task
(void *arg
)
{
struct timespec dl
, curr
; // for deadline checking
int index
, j
, x
, y
, temp
;
char s
[2];
struct timespec t
;
int b
;
task_setcanceltype
(TASK_CANCEL_ASYNCHRONOUS
,&temp
);
index
= (int)arg
;
NULL_TIMESPEC
(&t
);
ADDUSEC2TIMESPEC
((DEFAULT_SHIFT
*2)/3,&t
);
b
= TIMESPEC_A_LT_B
(&proc_table
[exec_shadow
].
request_time,&t
);
do {
x
= 0;
y
= rand() % 6 + 3;
s
[0] = '*'; s
[1] = 0;
while (x
< ASTER_LIM
) {
for (j
=0; j
<pattern
[index
].
iterations; j
++) {
s
[0] = '*' + rand() % 100;
puts_xy
(x
,y
,rand()%15+1,s
);
}
// Dline check :-) it is not perfect, but it works :-)
kern_cli
();
ll_gettime
(TIME_EXACT
,&curr
);
dl
= proc_table
[exec_shadow
].
request_time;
ADDUSEC2TIMESPEC
(pattern
[index
].
reldline, &dl
);
if (TIMESPEC_A_LT_B
(&dl
,&curr
)) {
cprintf
("\n\nPERIODIC TASK %d: Deadline miss!!!\n", index
);
cprintf
("current time= %10ld sec, %10ld ns\n", curr.
tv_sec, curr.
tv_nsec);
cprintf
("deadline = %10ld sec, %10ld ns\n", dl.
tv_sec, dl.
tv_nsec);
sys_end
();
}
task_endcycle
();
puts_xy
(x
,y
,WHITE
," ");
x
++;
}
} while (b
&& !finished
);
kern_cli
();
// account for a finished task
current_finished_tasks
++;
current_periodic_tasks
--;
// Dline check :-) it is not perfect, but it works :-)
ll_gettime
(TIME_EXACT
,&curr
);
dl
=proc_table
[exec_shadow
].
request_time;
ADDUSEC2TIMESPEC
(pattern
[index
].
reldline, &dl
);
if (TIMESPEC_A_LT_B
(&dl
,&curr
)) {
cprintf
("\n\nPERIODIC TASK %d: Deadline miss!!!\n", index
);
cprintf
("current time= %10ld sec, %10ld ns\n", curr.
tv_sec, curr.
tv_nsec);
cprintf
("deadline = %10ld sec, %10ld ns\n", dl.
tv_sec, dl.
tv_nsec);
sys_end
();
}
return (void *)0;
}
void *value_task
(void *arg
)
{
struct timespec dl
, curr
; // for deadline checking
int index
, j
, x
, y
, temp
;
char s
[2];
task_setcanceltype
(TASK_CANCEL_ASYNCHRONOUS
,&temp
);
index
= (int)arg
;
// kern_printf("Ú%dÙ",index);
x
= rand() % 26 + 1;
y
= rand() % 3 + 10;
s
[0] = '*'; s
[1] = 0;
for (j
=0; j
<pattern
[index
].
iterations; j
++) {
s
[0] = '*' + rand() % 100;
puts_xy
(x
,y
,rand()%15+1,s
);
}
// kern_printf("*%d*\n",exec_shadow);
kern_cli
();
// account for a finished task
current_finished_tasks
++;
// Dline check :-) it is not perfect, but it works :-)
ll_gettime
(TIME_EXACT
,&curr
);
TIMESPEC_ASSIGN
(&dl
, &proc_table
[exec_shadow
].
request_time);
ADDUSEC2TIMESPEC
(pattern
[index
].
reldline, &dl
);
if (TIMESPEC_A_GT_B
(&dl
,&curr
)) {
// The task finishes in time. account for the value
current_value
+= pattern
[index
].
penalty + pattern
[index
].
value;
}
// kern_printf("value: arg=%d current_value=%d pen=%d val=%d\n",arg,current_value,
// ((struct task_struct *)arg)->penalty,
// ((struct task_struct *)arg)->value);
return (void *)0;
}
void *info_task
(void *);
void create_info_task
(void)
{
HARD_TASK_MODEL hard
;
hard_task_default_model
(hard
);
hard_task_def_usemath
(hard
);
hard_task_def_mit
(hard
, 2000000);
hard_task_def_wcet
(hard
, 2000);
info_pid
= task_create
("info_task", info_task
, &hard
, NULL
);
task_activate
(info_pid
);
}
void *info_task
(void *arg
)
{
int x
;
task_setcanceltype
(TASK_CANCEL_ASYNCHRONOUS
,&x
);
for (;;) {
update_scenario
();
task_endcycle
();
}
}
void print_statistics
(void)
{
TIME sum
;
clear
();
jet_getstat
(master_pid
, &sum
, 0, 0, 0);
task_activate
(master_pid
); // let the master task die...
task_kill
(info_pid
);
clear
();
cprintf
("CRUNCH 1.12 - by Paolo Gai 2001\n\n");
cprintf
("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n\n");
cprintf
("Final Results:\n\n");
cprintf
("The Master task elapsed time : %d microseconds.\n\n",(int)sum
);
cprintf
("Total number of tasks : %9d\n", pattern_dim
);
cprintf
("Total number of scheduled tasks: %9d\n\n",current_task
);
cprintf
("Per.tasks created but not ended: %9d\n\n",current_periodic_tasks
);
cprintf
("Maximum created value : %9d\n",max_created_value
);
cprintf
("Minimum created value : %9d\n\n",min_created_value
);
cprintf
("Maximum value : %9d\n",max_value
);
cprintf
("Minimum value : %9d\n\n",min_value
);
cprintf
("Total Value (from Module) : %9d\n",crunch_getvalue
());
cprintf
("Total Value (from CRUNCH) : %9d\n",current_value
);
cprintf
("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n\n");
}
/*
* Scenario
*/
void scenario
(void)
{
char buf
[100];
clear
();
puts_xy
(0, 0,BLUE
, "CRUNCH 1.12");
puts_xy
(15,0,GREEN
, "by Paolo Gai 2001");
puts_xy
(0, 2,WHITE
, "ÄÄÄ Hard Periodic Tasks ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
puts_xy
(0, 9,WHITE
, "ÂÄÄ Soft Aperiodic Tasks ÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
puts_xy
(0,10,WHITE
, "³ ³");
puts_xy
(0,11,WHITE
, "³ ³");
puts_xy
(0,12,WHITE
, "³ ³");
puts_xy
(0,13,WHITE
, "ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ");
puts_xy
(29,10,YELLOW
, "Statistics:");
sprintf(buf
,"Total: %5d Already created: Periodic:",pattern_dim
);
puts_xy
(29,11,CYAN
, buf
);
puts_xy
(29,12,BLUE
, "Value reported (by Modules):");
puts_xy
(29,13,RED
, " (by CRUNCH ):");
puts_xy
(69,12,7, "Min:");
puts_xy
(69,13,7, "Max:");
puts_xy
(0,14,WHITE
, "ÄÄÄ Debug space for Logging Module functions... ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
place
(0,15);
}
void update_scenario
(void)
{
char buf
[100];
sprintf(buf
,"%5d",current_task
);
puts_xy
(58,11,WHITE
,buf
);
sprintf(buf
,"%5d",current_periodic_tasks
);
puts_xy
(75,11,WHITE
,buf
);
sprintf(buf
,"%5d",crunch_getvalue
());
puts_xy
(58,12,WHITE
,buf
);
sprintf(buf
,"%5d",current_value
);
puts_xy
(58,13,WHITE
,buf
);
sprintf(buf
,"%6d",min_value
);
puts_xy
(74,12,WHITE
,buf
);
sprintf(buf
,"%6d",max_value
);
puts_xy
(74,13,WHITE
,buf
);
}