Rev 1207 | Rev 1209 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include <kernel/kern.h>
#include "parser.h"
#include "dosread.h"
/* Memory pointers on loaded file */
extern void *start_file;
extern void *end_file;
/* Calibration Loops */
#define CALIBRATION_DELTA 100000
/* Mutex number */
#define MAX_MUTEX 10
/* Activate task output */
#define TASK_OUTPUT
struct timespec zero_time;
int cal_cycles = 0;
int cal_rit_start = 0;
int cal_rit_calc_const = 0;
int cal_rit_calc_mean = 0;
int cal_rit_calc_gauss = 0;
mutex_t mux_table[MAX_MUTEX];
/* Not Real-Time Task */
TASK nrt_test_task(void *arg)
{
long long i,exec_cycles = 0;
int exec_1,exec_2,exec_3;
int act_1,act_2,act_3,next_act;
int crit_1 = 0,crit_2 = 0,crit_3 = 0,crit_4 = 0;
int crit_start,crit_len;
long long crit_start_cycles = 0, crit_len_cycles = 0;
struct timespec next_time;
static int act= 0;
struct loader_task *l = (struct loader_task *)(arg);
act++;
act_1 = TIMESPEC2USEC(&l->act_par_2);
act_2 = TIMESPEC2USEC(&l->act_par_3);
act_3 = TIMESPEC2USEC(&l->act_par_4);
if (l->act_type == PAR_ACT_PERIODIC) {
kern_gettime(&next_time);
ADDUSEC2TIMESPEC(act_1,&next_time);
kern_event_post(&next_time,(void *)((void *)task_activate),(void *)exec_shadow);
}
if (l->act_type == PAR_ACT_MEAN) {
next_act = act_1 + rand() % act_2 - act_2/2;
kern_gettime(&next_time);
ADDUSEC2TIMESPEC(next_act,&next_time);
kern_event_post(&next_time,(void *)((void *)task_activate),(void *)exec_shadow);
}
if (l->act_type == PAR_ACT_GAUSS) {
}
if (l->act_type == PAR_ACT_GAUSS_MAX) {
}
exec_1 = TIMESPEC2USEC(&l->exec_par_1);
exec_2 = TIMESPEC2USEC(&l->exec_par_2);
exec_3 = TIMESPEC2USEC(&l->exec_par_3);
if (l->crit_type == PAR_CRIT) {
crit_1 = TIMESPEC2USEC(&l->crit_par_1);
crit_2 = TIMESPEC2USEC(&l->crit_par_2);
crit_3 = TIMESPEC2USEC(&l->crit_par_3);
crit_4 = TIMESPEC2USEC(&l->crit_par_4);
}
#ifdef TASK_OUTPUT
printf_xy(exec_shadow % 20 + 60, exec_shadow / 20, GREEN, "R");
#endif
if (l->exec_type == PAR_EXEC_CONST)
exec_cycles = (long long)(exec_1 - cal_rit_start - cal_rit_calc_const)
* CALIBRATION_DELTA / cal_cycles;
if (l->exec_type == PAR_EXEC_MEAN)
exec_cycles = (long long)(exec_1 - cal_rit_start - cal_rit_calc_mean
+ rand() % exec_2 - exec_2/2) * CALIBRATION_DELTA / cal_cycles;
if (l->exec_type == PAR_EXEC_GAUSS)
exec_cycles = 0;
if (l->exec_type == PAR_EXEC_GAUSS_MAX)
exec_cycles = 0;
if (l->crit_type == PAR_CRIT) {
crit_start = crit_1 + rand() % crit_2 - crit_2/2;
crit_len = crit_3 + rand() % crit_4 - crit_4/2;
crit_start_cycles = (long long)(crit_start) * CALIBRATION_DELTA / cal_cycles;
crit_len_cycles = (long long)(crit_len) * CALIBRATION_DELTA / cal_cycles;
exec_cycles -= crit_start_cycles + crit_len_cycles;
if (exec_cycles < 0) {
cprintf("Error: exec_cycles < 0\n");
sys_end();
}
}
if (l->crit_type == PAR_NO_CRIT)
for (i=0;i<exec_cycles;i++) kern_gettime(NULL);
else {
for (i=0;i<crit_start_cycles;i++) kern_gettime(NULL);
#ifdef TASK_OUTPUT
printf_xy(exec_shadow % 20 + 59, exec_shadow / 20, RED,"B");
#endif
mutex_lock(&mux_table[l->resource]);
for (i=0;i<crit_len_cycles;i++) kern_gettime(NULL);
mutex_unlock(&mux_table[l->resource]);
#ifdef TASK_OUTPUT
printf_xy(exec_shadow % 20 + 59, exec_shadow / 20, GREEN,"R");
#endif
for (i=0;i<exec_cycles;i++) kern_gettime(NULL);
}
#ifdef TASK_OUTPUT
printf_xy(exec_shadow % 20 + 60, exec_shadow / 20, WHITE, "E");
#endif
return NULL;
}
/* Soft and hard Task */
TASK test_task(void *arg)
{
long long i,exec_cycles = 0;
int exec_1,exec_2,exec_3;
int act_1,act_2,act_3,next_act;
int crit_1 = 0,crit_2 = 0,crit_3 = 0,crit_4 = 0;
int crit_start,crit_len;
long long crit_start_cycles = 0, crit_len_cycles = 0;
struct timespec next_time;
static int act=0;
int extra_rit, k;
struct loader_task *l = (struct loader_task *)(arg);
act++;
act_1 = TIMESPEC2USEC(&l->act_par_2);
act_2 = TIMESPEC2USEC(&l->act_par_3);
act_3 = TIMESPEC2USEC(&l->act_par_4);
exec_1 = TIMESPEC2USEC(&l->exec_par_1);
exec_2 = TIMESPEC2USEC(&l->exec_par_2);
exec_3 = TIMESPEC2USEC(&l->exec_par_3);
extra_rit = cal_rit_start;
if (l->crit_type == PAR_CRIT) {
crit_1 = TIMESPEC2USEC(&l->crit_par_1);
crit_2 = TIMESPEC2USEC(&l->crit_par_2);
crit_3 = TIMESPEC2USEC(&l->crit_par_3);
crit_4 = TIMESPEC2USEC(&l->crit_par_4);
}
k = 0;
while(1) {
task_testcancel();
#ifdef TASK_OUTPUT
k++;
if (k > 15) k = 1;
printf_xy(exec_shadow % 20 + 59, exec_shadow / 20, k,"X");
#endif
if (l->act_type == PAR_ACT_MEAN) {
next_act = act_1 + rand() % act_2 - act_2/2;
kern_gettime(&next_time);
ADDUSEC2TIMESPEC(next_act,&next_time);
kern_event_post(&next_time,(void *)((void *)task_activate),(void *)exec_shadow);
}
if (l->act_type == PAR_ACT_GAUSS) {
}
if (l->act_type == PAR_ACT_GAUSS_MAX) {
}
if (l->exec_type == PAR_EXEC_CONST)
exec_cycles = (long long)(exec_1 - extra_rit - cal_rit_calc_const)
* CALIBRATION_DELTA / cal_cycles;
if (l->exec_type == PAR_EXEC_MEAN)
exec_cycles = (long long)(exec_1 - extra_rit - cal_rit_calc_mean
+ rand() % exec_2 - exec_2/2) * CALIBRATION_DELTA / cal_cycles;
if (l->exec_type == PAR_EXEC_GAUSS)
exec_cycles = 0;
if (l->exec_type == PAR_EXEC_GAUSS_MAX)
exec_cycles = 0;
if (l->crit_type == PAR_CRIT) {
crit_start = crit_1 + rand() % crit_2 - crit_2/2;
crit_len = crit_3 + rand() % crit_4 - crit_4/2;
crit_start_cycles = (long long)(crit_start) * CALIBRATION_DELTA / cal_cycles;
crit_len_cycles = (long long)(crit_len) * CALIBRATION_DELTA / cal_cycles;
exec_cycles -= crit_start_cycles + crit_len_cycles;
if (exec_cycles < 0) {
cprintf("Error: exec_cycles < 0\n");
sys_end();
}
}
extra_rit = 0;
if (l->crit_type == PAR_NO_CRIT)
for (i=0;i<exec_cycles;i++) kern_gettime(NULL);
else {
for (i=0;i<crit_start_cycles;i++) kern_gettime(NULL);
#ifdef TASK_OUTPUT
printf_xy(exec_shadow % 20 + 59, exec_shadow / 20, k,"B");
#endif
mutex_lock(&mux_table[l->resource]);
for (i=0;i<crit_len_cycles;i++) kern_gettime(NULL);
mutex_unlock(&mux_table[l->resource]);
#ifdef TASK_OUTPUT
printf_xy(exec_shadow % 20 + 59, exec_shadow / 20, k,"X");
#endif
for (i=0;i<exec_cycles;i++) kern_gettime(NULL);
}
task_endcycle();
}
return NULL;
}
/* Background Task */
TASK back_task(void *arg)
{
long long i,exec_cycles = 0;
int exec_1,exec_2,exec_3;
int act_1,act_2,act_3,next_act;
int crit_1 = 0,crit_2 = 0,crit_3 = 0,crit_4 = 0;
int crit_start,crit_len;
long long crit_start_cycles = 0, crit_len_cycles = 0;
struct timespec next_time;
static int act=0;
int extra_rit, k;
struct loader_task *l = (struct loader_task *)(arg);
act++;
act_1 = TIMESPEC2USEC(&l->act_par_2);
act_2 = TIMESPEC2USEC(&l->act_par_3);
act_3 = TIMESPEC2USEC(&l->act_par_4);
exec_1 = TIMESPEC2USEC(&l->exec_par_1);
exec_2 = TIMESPEC2USEC(&l->exec_par_2);
exec_3 = TIMESPEC2USEC(&l->exec_par_3);
extra_rit = cal_rit_start;
if (l->crit_type == PAR_CRIT) {
crit_1 = TIMESPEC2USEC(&l->crit_par_1);
crit_2 = TIMESPEC2USEC(&l->crit_par_2);
crit_3 = TIMESPEC2USEC(&l->crit_par_3);
crit_4 = TIMESPEC2USEC(&l->crit_par_4);
}
k = 0;
while(1) {
task_testcancel();
#ifdef TASK_OUTPUT
k++;
if (k > 15) k = 1;
printf_xy(exec_shadow % 20 + 59, exec_shadow / 20, k,"X");
#endif
if (l->act_type == PAR_ACT_MEAN) {
next_act = act_1 + rand() % act_2 - act_2/2;
kern_gettime(&next_time);
ADDUSEC2TIMESPEC(next_act,&next_time);
kern_event_post(&next_time,(void *)((void *)task_activate),(void *)exec_shadow);
}
if (l->act_type == PAR_ACT_GAUSS) {
}
if (l->act_type == PAR_ACT_GAUSS_MAX) {
}
if (l->exec_type == PAR_EXEC_CONST)
exec_cycles = (long long)(exec_1 - extra_rit - cal_rit_calc_const)
* CALIBRATION_DELTA / cal_cycles;
if (l->exec_type == PAR_EXEC_MEAN)
exec_cycles = (long long)(exec_1 - extra_rit - cal_rit_calc_mean
+ rand() % exec_2 - exec_2/2) * CALIBRATION_DELTA / cal_cycles;
if (l->exec_type == PAR_EXEC_GAUSS)
exec_cycles = 0;
if (l->exec_type == PAR_EXEC_GAUSS_MAX)
exec_cycles = 0;
if (l->crit_type == PAR_CRIT) {
crit_start = crit_1 + rand() % crit_2 - crit_2/2;
crit_len = crit_3 + rand() % crit_4 - crit_4/2;
crit_start_cycles = (long long)(crit_start) * CALIBRATION_DELTA / cal_cycles;
crit_len_cycles = (long long)(crit_len) * CALIBRATION_DELTA / cal_cycles;
exec_cycles -= crit_start_cycles + crit_len_cycles;
if (exec_cycles < 0) {
cprintf("Error: exec_cycles < 0\n");
sys_end();
}
}
extra_rit = 0;
if (l->crit_type == PAR_NO_CRIT)
for (i=0;i<exec_cycles;i++) kern_gettime(NULL);
else {
for (i=0;i<crit_start_cycles;i++) kern_gettime(NULL);
#ifdef TASK_OUTPUT
printf_xy(exec_shadow % 20 + 59, exec_shadow / 20, k,"B");
#endif
mutex_lock(&mux_table[l->resource]);
for (i=0;i<crit_len_cycles;i++) kern_gettime(NULL);
mutex_unlock(&mux_table[l->resource]);
#ifdef TASK_OUTPUT
printf_xy(exec_shadow % 20 + 59, exec_shadow / 20, k,"X");
#endif
for (i=0;i<exec_cycles;i++) kern_gettime(NULL);
}
}
return NULL;
}
/* Delay Calibration */
int calibrate_cycle()
{
long long i;
struct timespec start,end,diff;
int temp = 1234567;
int temp_1 = 1234567;
int temp_2 = 1234567;
kern_cli();
kern_gettime(&start);
for (i=0;i<CALIBRATION_DELTA;i++) kern_gettime(NULL);
kern_gettime(&end);
kern_sti();
SUBTIMESPEC(&end,&start,&diff);
cal_cycles = TIMESPEC2USEC(&diff);
cprintf("Calibration usec/[%d cycles] = %d\n",CALIBRATION_DELTA,cal_cycles);
kern_cli();
kern_gettime(&start);
temp = (long long)(temp_1) * CALIBRATION_DELTA / cal_cycles;
kern_gettime(&end);
kern_sti();
SUBTIMESPEC(&end,&start,&diff);
cal_rit_calc_const = TIMESPEC2USEC(&diff);
kern_cli();
kern_gettime(&start);
temp = (long long)(temp_1 + rand() % temp_2 - temp_2/2) * CALIBRATION_DELTA / cal_cycles;
kern_gettime(&end);
kern_sti();
SUBTIMESPEC(&end,&start,&diff);
cal_rit_calc_mean = TIMESPEC2USEC(&diff);
kern_cli();
kern_gettime(&start);
temp = TIMESPEC2USEC(&start);
kern_gettime(&end);
kern_sti();
SUBTIMESPEC(&end,&start,&diff);
cal_rit_start = TIMESPEC2USEC(&diff) * 6 + cal_rit_calc_const;
cprintf("Calibration delay start = %d const = %d mean = %d gauss = %d\n",
cal_rit_start,cal_rit_calc_const,cal_rit_calc_mean,cal_rit_calc_gauss);
return 0;
}
/* Mutex create */
void loader_mutex_create(struct loader_task *start_loader_task)
{
struct loader_task *current = start_loader_task;
int res = 0;
PI_mutexattr_t a;
PI_mutexattr_default(a);
while (current != NULL) {
if (current->crit_type == PAR_CRIT) {
mutex_init(&mux_table[current->resource],&a);
res++;
}
current = current->next;
}
cprintf("Created %d mutex\n",res);
}
/* Task create */
void loader_task_create(struct loader_task *start_loader_task)
{
struct loader_task *current = start_loader_task;
char tmp[30];
int i, total_task;
int total_group = 0;
PID p;
total_task = 0;
while (current != NULL) {
total_group++;
current->group = total_group;
current->bandwidth = 0;
for (i=0; i < current->number; i++) {
if (current->task_type == PAR_TASK_NRT) {
NRT_TASK_MODEL nrt;
nrt_task_default_model(nrt);
nrt_task_def_save_arrivals(nrt);
nrt_task_def_arg(nrt,(void *)(current));
nrt_task_def_ctrl_jet(nrt);
nrt_task_def_level(nrt,current->task_level);
nrt_task_def_group(nrt,total_group);
sprintf(tmp,"NRT %d:%d",current->group,i);
p = task_create(tmp,nrt_test_task,&nrt,NULL);
if (p == NIL) {
cprintf("Error nrt task creating\n");
sys_end();
}
total_task++;
}
if (current->task_type == PAR_TASK_BACK) {
NRT_TASK_MODEL nrt;
nrt_task_default_model(nrt);
nrt_task_def_save_arrivals(nrt);
nrt_task_def_arg(nrt,(void *)(current));
nrt_task_def_ctrl_jet(nrt);
nrt_task_def_level(nrt,current->task_level);
nrt_task_def_group(nrt,total_group);
sprintf(tmp,"BACK %d:%d",current->group,i);
p = task_create(tmp,back_task,&nrt,NULL);
if (p == NIL) {
cprintf("Error back task creating\n");
sys_end();
}
total_task++;
}
if (current->task_type == PAR_TASK_HARD) {
HARD_TASK_MODEL ht;
hard_task_default_model(ht);
hard_task_def_arg(ht,(void *)(current));
hard_task_def_wcet(ht,TIMESPEC2USEC(¤t->wcet));
hard_task_def_ctrl_jet(ht);
hard_task_def_level(ht,current->task_level);
hard_task_def_group(ht,total_group);
if (current->act_type != PAR_ACT_PERIODIC) {
hard_task_def_mit(ht,TIMESPEC2USEC(¤t->deadline));
current->bandwidth += MAX_BANDWIDTH / TIMESPEC2USEC(¤t->deadline)
* TIMESPEC2USEC(¤t->wcet);
hard_task_def_aperiodic(ht);
} else {
hard_task_def_mit(ht,TIMESPEC2USEC(¤t->act_par_2));
current->bandwidth += MAX_BANDWIDTH / TIMESPEC2USEC(¤t->act_par_2)
* TIMESPEC2USEC(¤t->wcet);
}
sprintf(tmp,"HARD %d:%d",current->group,i);
p = task_create(tmp,test_task,&ht,NULL);
if (p == NIL) {
cprintf("Error hard task creating\n");
sys_end();
}
total_task++;
}
if (current->task_type == PAR_TASK_SOFT) {
SOFT_TASK_MODEL st;
soft_task_default_model(st);
soft_task_def_save_arrivals(st);
soft_task_def_arg(st,(void *)(current));
soft_task_def_met(st,TIMESPEC2USEC(¤t->wcet));
soft_task_def_ctrl_jet(st);
soft_task_def_level(st,current->task_level);
soft_task_def_group(st,total_group);
if (current->act_type == PAR_ACT_PERIODIC) {
soft_task_def_period(st,TIMESPEC2USEC(¤t->act_par_2));
current->bandwidth += MAX_BANDWIDTH / TIMESPEC2USEC(¤t->act_par_2)
* TIMESPEC2USEC(¤t->wcet);
} else if (current->act_type != PAR_ACT_SINGLE) {
soft_task_def_period(st,TIMESPEC2USEC(¤t->act_par_2));
current->bandwidth += MAX_BANDWIDTH / TIMESPEC2USEC(¤t->act_par_2)
* TIMESPEC2USEC(¤t->wcet);
soft_task_def_aperiodic(st);
} else {
soft_task_def_period(st,TIMESPEC2USEC(¤t->wcet)*1000);
current->bandwidth += MAX_BANDWIDTH / 1000;
soft_task_def_aperiodic(st);
}
sprintf(tmp,"SOFT %d:%d",current->group,i);
p = task_create(tmp,test_task,&st,NULL);
if (p == NIL) {
cprintf("Error soft task creating\n");
sys_end();
}
total_task++;
}
}
cprintf("Task group %d created. Worst case BW = %d.%d \n",
current->group,(int)( (long long)current->bandwidth * 100 / MAX_BANDWIDTH),
(int)( (long long)current->bandwidth* 100000 / MAX_BANDWIDTH % 1000));
current = current->next;
}
cprintf("Created %d tasks\n",total_task);
}
/* Set the first extivation events */
void loader_first_execution(struct loader_task *start_loader_task)
{
struct loader_task *current = start_loader_task;
struct timespec start_time;
while (current != NULL) {
ADDTIMESPEC(&zero_time,¤t->act_par_1,&start_time);
kern_event_post(&start_time, (void *)((void *)group_activate), (void *)(current->group));
current = current->next;
}
}
int main()
{
struct loader_task *start_loader_task = NULL;
struct timespec total;
struct timespec end_time;
line_reader(start_file, end_file, &total, &start_loader_task);
srand(kern_gettime(NULL));
calibrate_cycle();
loader_mutex_create(start_loader_task);
loader_task_create(start_loader_task);
kern_gettime(&zero_time);
loader_first_execution(start_loader_task);
ADDTIMESPEC(&zero_time,&total,&end_time);
kern_event_post(&end_time,(void *)((void *)(sys_end)),NULL);
return 0;
}