/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Giacomo Guidi <giacomo@gandalf.sssup.it>
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
/*
* Copyright (C) 2000 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
*/
#include "kernel/kern.h"
#include "fsf.h"
#include "fsf_server.h"
#include "stdlib.h"
#include "unistd.h"
#include "string.h"
#include "pistar.h"
#include "pthread.h"
#include "drivers/glib.h"
#include <tracer.h>
#include "FTrace_udp.h"
#include "FTrace_chunk.h"
#include <drivers/shark_keyb26.h>
#define TEST_PERIOD 50000
mutex_t mux
;
int main_chunk
;
TASK finish_task
() {
#ifdef __NEW_TRACER__
group_kill
(1);
group_kill
(2);
FTrace_OSD_init_udp
(1,"192.168.82.43","192.168.82.41");
FTrace_send_chunk
(main_chunk
, 0, FTRACE_CHUNK_FLAG_FREE
| FTRACE_CHUNK_FLAG_CYC
);
exit(0);
#else
exit(0);
#endif
return NULL
;
}
void print_timer
(int x
, int y
)
{
long nsec
,sec
,min
,hrs
,day
;
struct timespec actual_timer
;
char tmp
[100];
sys_gettime
(&actual_timer
);
nsec
= actual_timer.
tv_nsec;
sec
= actual_timer.
tv_sec;
min
= sec
/ 60;
sec
%= 60;
hrs
= min
/ 60;
min
%= 60;
day
= hrs
/ 24;
hrs
%= 24;
sprintf(tmp
,"Time: %2ld d %2ld h %2ld m %2ld s %12ld ns",day
,hrs
,min
,sec
,(long)nsec
);
mutex_lock
(&mux
);
grx_text
(tmp
,x
,y
,rgb16
(255,255,255),0);
mutex_unlock
(&mux
);
}
#define LOAD_VARIATION 10
#define MAX_V_QOS 30
#define MIN_V_QOS 2
void *test_task_variable
(void *arg
) {
struct timespec next_time
;
bool was_deadline_missed
= false, was_budget_overran
= false;
char tmp
[100];
long long i
;
int task_qos
;
int var_load
, rd_per
;
TIME exectime
;
task_qos
= 7;
var_load
= 5;
rd_per
= 0;
while(1) {
print_timer
(307,10+30*exec_shadow
);
sprintf(tmp
,"Test Thread V QOS = %5d PID = %3d VLOAD = %3d",task_qos
,exec_shadow
,var_load
);
mutex_lock
(&mux
);
if (!was_deadline_missed
)
grx_text
(tmp
,307,20+30*exec_shadow
,rgb16
(255,255,255),0);
else
grx_text
(tmp
,307,20+30*exec_shadow
,rgb16
(255,0,0),0);
mutex_unlock
(&mux
);
//jet_gettable(exec_shadow, &exectime, 1);
//sprintf(tmp,"Thread Exec Timer = %10d us",(int)exectime);
//grx_text(tmp,307,30+30*exec_shadow,rgb16(255,255,255),0);
if (rd_per
> LOAD_VARIATION
) {
var_load
+= rand()%3-1;
if (var_load
> 20) var_load
= 20;
if (var_load
< 0) var_load
= 0;
rd_per
= 0;
} else {
rd_per
++;
}
for(i
= 0; i
< 10000*(task_qos
+var_load
); i
++);
}
return NULL
;
}
#define MAX_C_QOS 30
#define MIN_C_QOS 2
void *test_task_constant
(void *arg
) {
struct timespec next_time
;
bool was_deadline_missed
= false, was_budget_overran
= false;
char tmp
[100];
long long i
;
int task_qos
;
task_qos
= 7;
while(1) {
print_timer
(307,10+20*exec_shadow
);
sprintf(tmp
,"Test Task C QOS = %5d PID = %3d",task_qos
,exec_shadow
);
mutex_lock
(&mux
);
if (!was_deadline_missed
)
grx_text
(tmp
,307,20+20*exec_shadow
,rgb16
(255,255,255),0);
else
grx_text
(tmp
,307,20+20*exec_shadow
,rgb16
(255,0,0),0);
mutex_unlock
(&mux
);
for(i
= 0; i
< 10000*task_qos
; i
++);
}
return NULL
;
}
void draw_box
(int x1
, int y1
, int x2
, int y2
)
{
grx_rect
(x1
,y1
,x2
,y2
,rgb16
(160,160,160));
grx_rect
(x1
+2,y1
+2,x2
-2,y2
-2,rgb16
(210,210,210));
}
void layout_screen
()
{
draw_box
(0,0,300,500);
grx_text
("Application Task List",5,5,rgb16
(255,255,255),0);
draw_box
(303,0,799,500);
grx_text
("Task Output",305,5,rgb16
(255,255,255),0);
draw_box
(0,503,799,599);
grx_line
(140,505,140,597,rgb16
(255,255,255));
grx_line
(140,583,797,583,rgb16
(255,255,255));
grx_text
("Application Statistics",142,507,rgb16
(255,255,255),0);
}
void program_end
()
{
grx_close
();
}
void *mpeg2decoder
(void *arg
);
void add_posixstar_thread
(fsf_server_id_t server
)
{
int err
;
pthread_t j
= -1;
static fsf_sched_params_t pr
;
NRT_TASK_MODEL nrt
;
pr.
policy=FSF_RR
;
pr.
params=&nrt
;
nrt_task_default_model
(nrt
);
nrt_task_def_save_arrivals
(nrt
);
nrt_task_def_group
(nrt
,1);
err
= pthread_create
(&j
, NULL
, test_task_variable
, NULL
);
if (err
) {
perror("Could not create task...");
exit(1);
}
err
=fsf_bind_local_thread_to_server
(server
, j
, (fsf_sched_params_t
*)(&pr
));
if (err
) {
grx_close
();
kern_printf
("Could not bind task.. %d", err
);
exit(1);
}
}
void add_edfstar_thread
(fsf_server_id_t server
)
{
int err
;
pthread_t j
= -1;
HARD_TASK_MODEL ht
;
static fsf_sched_params_t pr
;
pr.
policy=FSF_EDF
;
pr.
params=&ht
;
hard_task_default_model
(ht
);
hard_task_def_mit
(ht
,100000);
hard_task_def_wcet
(ht
,90000);
nrt_task_def_group
(ht
,2);
err
= pthread_create
(&j
, NULL
, mpeg2decoder
, NULL
);
if (err
) {
grx_close
();
perror("Could not create task...");
exit(1);
}
err
=fsf_bind_local_thread_to_server
(server
, j
,(fsf_sched_params_t
*)(&pr
));
if (err
) {
grx_close
();
perror("Could not bind task..");
exit(1);
}
}
void ending_system
(KEY_EVT
*e
) {
grx_close
();
#ifdef __NEW_TRACER__
NRT_TASK_MODEL nrt
;
TRACER_LOGEVENT
(FTrace_EVT_trace_stop
,0,0);
FTrace_disable
();
//group_kill(l->group);
nrt_task_default_model
(nrt
);
task_activate
(task_create
("Finish",finish_task
,&nrt
,NULL
));
#else
exit(0);
#endif
}
int main
(int argc
, char **argv
)
{
char ch
;
int err
;
//KEY_EVT k;
PI_mutexattr_t a
;
KEY_EVT ev
;
union sigval no_sigval
= {0};
struct timespec period
= {0,10000000};
struct timespec budget
= {0,1000000};
struct timespec period1
= {0,10000000};
struct timespec period2
= {0,10000000};
struct timespec budget1
= {0,3000000};
struct timespec budget2
= {0,3000000};
fsf_server_id_t server1
, server2
;
fsf_contract_parameters_t contract1
, contract2
;
union sigval sval
;
ev.
ascii = 'c';
ev.
scan = KEY_C
;
ev.
status = KEY_PRESSED
;
ev.
flag = CNTR_BIT
;
keyb_hook
(ev
, ending_system
, FALSE
);
#ifdef __NEW_TRACER__
main_chunk
= FTrace_chunk_create
(10000000, 1000, FTRACE_CHUNK_FLAG_FREE
| FTRACE_CHUNK_FLAG_CYC
);
FTrace_actual_chunk_select
(main_chunk
);
FTrace_enable
();
#endif
TRACER_LOGEVENT
(FTrace_EVT_trace_start
,0,0);
PI_mutexattr_default
(a
);
FSF_start_service_task
();
mutex_init
(&mux
,&a
);
fsf_initialize_contract
(&contract1
);
fsf_set_contract_basic_parameters
(&contract1
,&budget1
,&period1
,FSF_DEFAULT_WORKLOAD
);
fsf_set_contract_timing_requirements
(&contract1
,true,NULL
,0,no_sigval
,0,no_sigval
);
fsf_initialize_contract
(&contract2
);
fsf_set_contract_scheduling_policy
(&contract1
, FSF_RR
);
fsf_set_contract_basic_parameters
(&contract2
,&budget2
,&period2
,FSF_DEFAULT_WORKLOAD
);
fsf_set_contract_timing_requirements
(&contract2
,true,NULL
,0,no_sigval
,0,no_sigval
);
fsf_set_contract_scheduling_policy
(&contract2
, FSF_EDF
);
err
= fsf_negotiate_contract
(&contract1
,&server1
);
if (err
) cprintf
("(FSF ERROR %d)",err
);
err
= fsf_negotiate_contract
(&contract2
,&server2
);
if (err
) cprintf
("(FSF ERROR %d)",err
);
//graphic card Initialization
if (grx_init
() < 1) {
exit(1);
}
if (grx_open
(800, 600, 16) < 0) {
cprintf
("GRX Err\n");
exit(0);
}
layout_screen
();
ch
= keyb_getch
(BLOCK
);
while(ch
!= ESC
) {
switch (ch
) {
case '1':
add_posixstar_thread
(server1
);
break;
case '2':
add_edfstar_thread
(server2
);
break;
case '3':
fsf_set_contract_basic_parameters
(&contract2
,&budget
,&period
,FSF_DEFAULT_WORKLOAD
);
fsf_request_contract_renegotiation
(&contract2
,server2
, 0, sval
);
break;
case '4':
ending_system
(NULL
);
break;
case '5':
break;
}
ch
= keyb_getch
(BLOCK
);
}
ending_system
(NULL
);
return 0;
}