//=====================================================================
// FFFFFFIII RRRRR SSTTTTTTT
// FF IIR RR SS
// FF IR SS
// FFFFFF RRRR SSSSST
// FF FI RRR SS
// FF II RRR SS
// FF IIIIIR RS
//
// Basic FSF(FIRST Scheduling Framework) contract management
// S.Ha.R.K. Implementation
//=====================================================================
#include "ll/i386/64bit.h"
#include <kernel/kern.h>
#include <modules/sem.h>
#include <modules/hartport.h>
#include <modules/cabs.h>
#include "fsf.h"
#include "fsf_service_task.h"
#include "fsf_server.h"
#include "message.h"
#include "posixstar.h"
#include "edfstar.h"
#include "nonestar.h"
#include "rmstar.h"
#include <pthread.h>
#include <stdlib.h>
#include "pistar.h"
#include <modules/comm_message.h>
//#define FSF_DEBUG
int current_server
=0;
server_elem server_list
[FSF_MAX_N_SERVERS
];
bandwidth_t fsf_max_bw
= 0;
int fsf_server_level
;
int fsf_posix_level
= -1;
int shared_object_level
;
PID server_task
;
fsf_contract_parameters_t contract
;
PORT channel
[2];
fsf_server_id_t service_server
= -1;
fsf_contract_parameters_t service_contract
;
bandwidth_t SERVER_return_bandwidth
();
int FSF_register_shared_object_module
(void) {
fsf_register_shared_object
();
return PISTAR_register_module
();
}
int FSF_get_shared_object_level
() {
return shared_object_level
;
}
int FSF_register_module
(int posix_level
, int server_level
, bandwidth_t max_bw
)
{
printk
("FSF Module\n");
current_server
=0;
fsf_server_level
= server_level
;
fsf_posix_level
= posix_level
;
fsf_max_bw
= max_bw
;
shared_object_level
= FSF_register_shared_object_module
();
return 0;
}
void FSF_start_service_task
(void) {
int err
;
struct timespec default_period
= FSF_SERVICE_THREAD_PERIOD
;
struct timespec default_budget
= FSF_SERVICE_THREAD_BUDGET
;
DUMMY_TASK_MODEL m
;
fsf_sched_params_t pr
;
pr.
policy=FSF_NONE
;
pr.
params=&m
;
dummy_task_default_model
(m
);
// create the service task
// create the communication channel for negotiation and renegotiation
channel
[1] = port_create
("CHANW",sizeof(struct mess
),1,STREAM
,WRITE
);
channel
[0] = port_create
("CHANR",sizeof(struct mess
),1,STREAM
,READ
);
fsf_initialize_contract
(&service_contract
);
fsf_set_contract_basic_parameters
(&service_contract
,&default_budget
,&default_period
,FSF_DEFAULT_WORKLOAD
);
negotiate_contract
(&service_contract
,&service_server
);
//server_task = task_create("stask",service_task,model,NULL);
err
= fsf_create_local_thread
(service_server
,&pr
, &server_task
,NULL
,(fsf_thread_code_t
)service_task
,NULL
);
if (err
) {
cprintf
("error creating service task\n");
sys_shutdown_message
("Could not create service_task");
sys_end
();
return;
}
task_activate
(server_task
);
}
/* Convert the contract specification to
* budget parameters
*/
int set_SERVER_budget_from_contract
(const fsf_contract_parameters_t
*contract
,
int *budget
)
{
int local_scheduler_level
= 0;
switch (contract
->policy
) {
case FSF_POSIX
:
local_scheduler_level
= POSIXSTAR_register_level
(fsf_server_level
,5000,32);
break;
case FSF_EDF
:
local_scheduler_level
= EDFSTAR_register_level
(fsf_server_level
);
break;
case FSF_RM
:
local_scheduler_level
= RMSTAR_register_level
(fsf_server_level
);
break;
case FSF_NONE
:
local_scheduler_level
= NONESTAR_register_level
(fsf_server_level
);
break;
}
if (contract
->d_equals_t
== true) {
*budget
= SERVER_setbudget
(fsf_server_level
,
TIMESPEC2USEC
(&(contract
->budget_min
)),
TIMESPEC2USEC
(&(contract
->period_max
)),
TIMESPEC2USEC
(&(contract
->period_max
)),
local_scheduler_level
,contract
->policy
);
} else {
*budget
= SERVER_setbudget
(fsf_server_level
,
TIMESPEC2USEC
(&(contract
->budget_min
)),
TIMESPEC2USEC
(&(contract
->period_max
)),
TIMESPEC2USEC
(&(contract
->deadline
)),
local_scheduler_level
,contract
->policy
);
}
return 0;
}
int adjust_SERVER_budget
(int budget
, const TIME budget_actual
,
const TIME period_actual
, const TIME dline_actual
)
{
SERVER_adjust_budget
(fsf_server_level
,
budget_actual
,
period_actual
,
dline_actual
,
budget
);
return 0;
}
/* Admission Test function */
int add_contract
(const fsf_contract_parameters_t
*contract
)
{
bandwidth_t current_bandwidth
,U
;
TIME T
,Q
;
#ifdef FSF_DEBUG
kern_printf
("(GA TEST)");
#endif
T
=TIMESPEC2USEC
(&(contract
->period_max
));
Q
=TIMESPEC2USEC
(&(contract
->budget_min
));
mul32div32to32
(MAX_BANDWIDTH
,Q
,T
,U
);
/* The current bandwidth is the min bandwidth */
current_bandwidth
=SERVER_return_bandwidth
(fsf_server_level
);
if (fsf_max_bw
<current_bandwidth
+U
) return -1;
return 0;
}
void contract_to_server
(const fsf_contract_parameters_t
*contract
, int i
) {
TIME T
,Q
;
#ifdef FSF_DEBUG
int temp
;
#endif
T
=TIMESPEC2USEC
(&contract
->period_min
);
Q
=TIMESPEC2USEC
(&contract
->budget_max
);
server_list
[i
].
Cmax=Q
;
mul32div32to32
(MAX_BANDWIDTH
,Q
,T
,server_list
[current_server
].
Umax);
T
=TIMESPEC2USEC
(&contract
->period_min
);
server_list
[i
].
Tmin=T
;
T
=TIMESPEC2USEC
(&contract
->period_max
);
server_list
[i
].
Tmax=T
;
Q
=TIMESPEC2USEC
(&contract
->budget_min
);
server_list
[i
].
Cmin=Q
;
mul32div32to32
(MAX_BANDWIDTH
,Q
,T
,server_list
[i
].
Umin);
server_list
[i
].
U=server_list
[i
].
Umin;
if (contract
->d_equals_t
== true) {
server_list
[i
].
deadline = 0;
server_list
[i
].
d_equals_t = true;
} else {
server_list
[i
].
deadline = TIMESPEC2USEC
(&contract
->deadline
);;
server_list
[i
].
d_equals_t = false;
}
server_list
[i
].
Qs = contract
->quality
;
server_list
[i
].
Is = contract
->importance
;
#ifdef FSF_DEBUG
mul32div32to32
(server_list
[i
].
Umax,100, MAX_BANDWIDTH
, temp
);
kern_printf
("(Umax %d)",temp
);
mul32div32to32
(server_list
[i
].
Umin,100, MAX_BANDWIDTH
, temp
);
kern_printf
("(Umin %d)",temp
);
#endif
}
int relink_contract_to_server
(const fsf_contract_parameters_t
*contract
,
fsf_server_id_t server
)
{
int i
=0;
#ifdef FSF_DEBUG
kern_printf
("(Relink Server %d)",server
);
#endif
// find contract
while(i
<current_server
) {
if (server_list
[i
].
server==server
) break;
i
++;
}
server_list
[i
].
server=server
;
// server_list[i].Qs=1;
contract_to_server
(contract
, i
);
return 0;
}
int link_contract_to_server
(const fsf_contract_parameters_t
*contract
,
fsf_server_id_t server
)
{
#ifdef FSF_DEBUG
kern_printf
("(Link Server %d)",server
);
#endif
server_list
[current_server
].
server=server
;
//server_list[current_server].Qs=1;
contract_to_server
(contract
,current_server
);
current_server
++;
return 0;
}
int remove_contract
(fsf_server_id_t server
)
{
int i
=0;
// find the contract
while(i
<current_server
) {
if (server_list
[i
].
server==server
) break;
i
++;
}
// compress the array;
while (i
<(current_server
-1)) {
server_list
[i
].
server=server_list
[i
+1].
server;
server_list
[i
].
Umin=server_list
[i
+1].
Umin;
server_list
[i
].
U=server_list
[i
+1].
Umin;
server_list
[i
].
Umax=server_list
[i
+1].
Umax;
server_list
[i
].
Cmin=server_list
[i
+1].
Cmin;
server_list
[i
].
Cmax=server_list
[i
+1].
Cmax;
server_list
[i
].
Tmin=server_list
[i
+1].
Tmin;
server_list
[i
].
Tmax=server_list
[i
+1].
Tmax;
server_list
[i
].
Qs=server_list
[i
+1].
Qs;
server_list
[i
].
deadline = server_list
[i
+1].
deadline;
server_list
[i
].
d_equals_t = server_list
[i
+1].
d_equals_t;
server_list
[i
].
Is = server_list
[i
+1].
Is;
i
++;
}
current_server
--;
return 0;
}
int
fsf_get_renegotiation_status
(fsf_server_id_t server
,
fsf_renegotiation_status_t
*renegotiation_status
)
{
if (SERVER_get_renegotiation_status
(fsf_server_level
,server
))
*renegotiation_status
=FSF_IN_PROGRESS
;
else
*renegotiation_status
=FSF_ADMITTED
;
return 0;
}
int
fsf_request_change_quality_and_importance
(fsf_server_id_t server
,
int new_importance
,
int new_quality
)
{
struct mess m
;
// send response server is -1 if the operation fail
m.
type=CHANGE_PARAMETER
;
m.
server=server
;
m.
qi.
quality = new_quality
;
m.
qi.
importance = new_importance
;
//memmove(&m.contract,contract, sizeof(fsf_contract_parameters_t));
port_send
(channel
[1],&m
,BLOCK
);
port_receive
(channel
[0], &m
, BLOCK
);
if (m.
server==-1)
return FSF_ERR_CONTRACT_REJECTED
;
//*server=m.server;
return 0;
}
int fsf_negotiate_contract
(const fsf_contract_parameters_t
*contract
,
fsf_server_id_t
*server
)
{
struct mess m
;
// send response server is -1 if the operation fail
m.
type=NEGOTIATE_CONTRACT
;
memmove(&m.
contract,contract
, sizeof(fsf_contract_parameters_t
));
//kern_printf("(SN:%d)",*server);
port_send
(channel
[1],&m
,BLOCK
);
//kern_printf("BR:%d)", *server);
port_receive
(channel
[0], &m
, BLOCK
);
//kern_printf("(EN:%d)", *server);
if (m.
server==-1)
return FSF_ERR_CONTRACT_REJECTED
;
*server
=m.
server;
return 0;
}
int
fsf_negotiate_contract_for_new_thread
(const fsf_contract_parameters_t
*contract
,
fsf_server_id_t
*server
,
pthread_t
*thread
,
pthread_attr_t
*attr
,
fsf_thread_code_t thread_code
,
void *arg
) {
int err
=0;
err
= fsf_negotiate_contract
(contract
,server
);
if (!err
) {
err
= pthread_create
(thread
, attr
, thread_code
, arg
);
if (!err
)
err
= fsf_bind_thread_to_server
(*server
,*thread
);
} else return err
;
return err
;
}
int
fsf_negotiate_contract_for_myself
(const fsf_contract_parameters_t
*contract
,
fsf_server_id_t
*server
) {
int err
=0;
err
= fsf_negotiate_contract
(contract
,server
);
//kern_printf("ENMyS:%d", *server);
if (!err
) {
err
= fsf_bind_thread_to_server
(*server
,exec_shadow
);
//kern_printf("EMMyE:%d:%d",*server,err);
} else return err
;
return err
;
}
int fsf_unbind_thread_from_server
(pthread_t thread
)
{
int local_scheduler_level
, scheduler_id
;
/* Move thread from the local scheduler module to posix level */
#ifdef FSF_DEBUG
kern_printf
("(UnBind thread = %d)",thread
);
#endif
/* Check if thread exsists */
if (thread
== -1)
return FSF_ERR_BAD_ARGUMENT
;
local_scheduler_level
= SERVER_get_local_scheduler_level_from_pid
(fsf_server_level
,thread
);
scheduler_id
= SERVER_get_local_scheduler_id_from_pid
(fsf_server_level
,thread
);
/* Check if thread is already bind */
if (scheduler_id
== FSF_NONE
) {
/* Check if it is bind to a server */
if (NONESTAR_getbudget
(local_scheduler_level
,thread
) == -1)
return FSF_ERR_BAD_ARGUMENT
;
else {
STD_command_message
*msg
;
NRT_TASK_MODEL nrt
;
nrt_task_default_model
(nrt
);
nrt_task_def_save_arrivals
(nrt
);
/* Send change level command to local scheduler */
msg
= (STD_command_message
*)malloc(sizeof(STD_command_message
));
msg
->command
= STD_SET_NEW_MODEL
;
msg
->param
= (void *)(&nrt
);
level_table
[fsf_posix_level
]->public_message
(fsf_posix_level
,thread
,msg
);
msg
->command
= STD_SET_NEW_LEVEL
;
msg
->param
= (void *)(fsf_posix_level
);
task_message
(msg
,thread
,0);
free(msg
);
}
}
return 0;
}
int
fsf_bind_local_thread_to_server
(fsf_server_id_t server
,
pthread_t thread
,
fsf_sched_params_t
*sched_params
)
{
STD_command_message
*msg
;
int local_scheduler_level
,scheduler_id
;
/* Move thread from the posix module to local scheduler */
#ifdef FSF_DEBUG
kern_printf
("(Bind thread = %d to Server = %d)",thread
,server
);
#endif
/* Check if server and thread exsist */
if (server
== -1 || thread
== -1)
return FSF_ERR_BAD_ARGUMENT
;
local_scheduler_level
= SERVER_get_local_scheduler_level_from_budget
(fsf_server_level
,server
);
if (local_scheduler_level
==-1)
return FSF_ERR_UNKNOWN_APPSCHEDULED_THREAD
;
scheduler_id
= SERVER_get_local_scheduler_id_from_budget
(fsf_server_level
,server
);
if (scheduler_id
!=sched_params
->policy
)
return FSF_ERR_SCHED_POLICY_NOT_COMPATIBLE
;
/* Check if thread is already bind */
switch(scheduler_id
) {
case FSF_RM
:
{
TASK_MODEL
*m
=(TASK_MODEL
*)(sched_params
->params
);
HARD_TASK_MODEL
*h
=(HARD_TASK_MODEL
*)(sched_params
->params
);
if (m
->pclass
!= HARD_PCLASS
)
return FSF_ERR_SCHED_POLICY_NOT_COMPATIBLE
;
h
= (HARD_TASK_MODEL
*)m
;
if (!h
->wcet
|| !h
->mit
) return FSF_ERR_SCHED_POLICY_NOT_COMPATIBLE
;
/* now we know that m is a valid model */
if (RMSTAR_getbudget
(local_scheduler_level
,thread
) != -1)
return FSF_ERR_BAD_ARGUMENT
;
/* Set server on local scheduler */
RMSTAR_setbudget
(local_scheduler_level
,thread
,(int)(server
));
/* Send change level command to posix level */
}
break;
case FSF_EDF
:
{
TASK_MODEL
*m
=(TASK_MODEL
*)(sched_params
->params
);
HARD_TASK_MODEL
*h
=(HARD_TASK_MODEL
*)(sched_params
->params
);
if (m
->pclass
!= HARD_PCLASS
)
return FSF_ERR_SCHED_POLICY_NOT_COMPATIBLE
;
h
= (HARD_TASK_MODEL
*)m
;
if (!h
->wcet
|| !h
->mit
) return FSF_ERR_SCHED_POLICY_NOT_COMPATIBLE
;
if (EDFSTAR_getbudget
(local_scheduler_level
,thread
) != -1)
return FSF_ERR_BAD_ARGUMENT
;
/* Set server on local scheduler */
EDFSTAR_setbudget
(local_scheduler_level
,thread
,(int)(server
));
}
break;
case FSF_POSIX
:
{
TASK_MODEL
*m
=(TASK_MODEL
*)(sched_params
->params
);
if (m
->pclass
!= NRT_PCLASS
)
return FSF_ERR_SCHED_POLICY_NOT_COMPATIBLE
;
if (POSIXSTAR_getbudget
(local_scheduler_level
,thread
) != -1)
return FSF_ERR_BAD_ARGUMENT
;
/* Set server on local scheduler */
POSIXSTAR_setbudget
(local_scheduler_level
,thread
,(int)(server
));
}
break;
default:
return FSF_ERR_BAD_ARGUMENT
;
}
msg
= (STD_command_message
*)malloc(sizeof(STD_command_message
));
if (msg
) {
SYS_FLAGS f
;
f
=kern_fsave
();
msg
->command
= STD_SET_NEW_MODEL
;
msg
->param
= (void *)(sched_params
->params
);
level_table
[local_scheduler_level
]->public_message
(local_scheduler_level
,thread
,msg
);
msg
->command
= STD_SET_NEW_LEVEL
;
msg
->param
= (void *)(local_scheduler_level
);
task_message
(msg
,thread
,0);
kern_frestore
(f
);
free(msg
);
} else return FSF_ERR_INTERNAL_ERROR
;
return 0;
}
int fsf_bind_thread_to_server
(fsf_server_id_t server
,
pthread_t thread
)
{
STD_command_message
*msg
;
int local_scheduler_level
,scheduler_id
;
/* Move thread from the posix module to local scheduler */
#ifdef FSF_DEBUG
kern_printf
("(Bthr=%d to Sr=%d)",thread
,server
);
#endif
/* Check if server and thread exsist */
if (server
== -1 || thread
== -1)
return FSF_ERR_BAD_ARGUMENT
;
local_scheduler_level
= SERVER_get_local_scheduler_level_from_budget
(fsf_server_level
,server
);
if (local_scheduler_level
==-1)
return FSF_ERR_UNKNOWN_APPSCHEDULED_THREAD
;
scheduler_id
= SERVER_get_local_scheduler_id_from_budget
(fsf_server_level
,server
);
/* Check if thread is already bind */
if (scheduler_id
== FSF_NONE
) {
DUMMY_TASK_MODEL rt_arg
;
if (NONESTAR_getbudget
(local_scheduler_level
,thread
) != -1)
return FSF_ERR_BAD_ARGUMENT
;
/* Set server on local scheduler */
NONESTAR_setbudget
(local_scheduler_level
,thread
,(int)(server
));
/* Send change level command to posix level */
msg
= (STD_command_message
*)malloc(sizeof(STD_command_message
));
msg
->command
= STD_SET_NEW_MODEL
;
msg
->param
= (void *)(&rt_arg
);
level_table
[local_scheduler_level
]->public_message
(local_scheduler_level
,thread
,msg
);
msg
->command
= STD_SET_NEW_LEVEL
;
msg
->param
= (void *)(local_scheduler_level
);
task_message
(msg
,thread
,0);
free(msg
);
} else return FSF_ERR_BAD_ARGUMENT
;
return 0;
}
int fsf_create_local_thread
(fsf_server_id_t server
,
fsf_sched_params_t
*local_scheduler_arg
,
pthread_t
*thread
,
pthread_attr_t
*attr
,
fsf_thread_code_t thread_code
,
void *arg
)
{
int local_scheduler_level
,scheduler_id
;
/* Check if server and thread exsist */
if (server
== NIL
)
return FSF_ERR_BAD_ARGUMENT
;
local_scheduler_level
= SERVER_get_local_scheduler_level_from_budget
(fsf_server_level
,server
);
scheduler_id
= SERVER_get_local_scheduler_id_from_budget
(fsf_server_level
,server
);
#ifdef FSF_DEBUG
kern_printf
("sched policy %d", scheduler_id
);
#endif
if (scheduler_id
!=local_scheduler_arg
->policy
)
return FSF_ERR_SCHED_POLICY_NOT_COMPATIBLE
;
/* Check if thread is already bind */
switch (scheduler_id
) {
case FSF_POSIX
:
nrt_task_def_arg
(*(NRT_TASK_MODEL
*)(local_scheduler_arg
->params
),arg
);
nrt_task_def_level
(*(NRT_TASK_MODEL
*)(local_scheduler_arg
->params
),local_scheduler_level
);
*thread
= task_create
("POSIXSTAR", thread_code
, local_scheduler_arg
->params
, NULL
);
if (*thread
== NIL
) {
#ifdef FSF_DEBUG
kern_printf
("(FSF:Error creating thread)");
#endif
return FSF_ERR_INTERNAL_ERROR
;
}
POSIXSTAR_setbudget
(local_scheduler_level
, *thread
, (int)(server
));
break;
case FSF_EDF
:
hard_task_def_arg
(*(HARD_TASK_MODEL
*)(local_scheduler_arg
->params
),arg
);
hard_task_def_level
(*(HARD_TASK_MODEL
*)(local_scheduler_arg
->params
),local_scheduler_level
);
*thread
= task_create
("EDFSTAR", thread_code
, local_scheduler_arg
->params
, NULL
);
if (*thread
== NIL
)
return FSF_ERR_INTERNAL_ERROR
;
EDFSTAR_setbudget
(local_scheduler_level
, *thread
, (int)(server
));
break;
case FSF_RM
:
hard_task_def_arg
(*(HARD_TASK_MODEL
*)(local_scheduler_arg
->params
),arg
);
hard_task_def_level
(*(HARD_TASK_MODEL
*)(local_scheduler_arg
->params
),local_scheduler_level
);
*thread
= task_create
("RMSTAR", thread_code
, local_scheduler_arg
->params
, NULL
);
if (*thread
== NIL
)
return FSF_ERR_INTERNAL_ERROR
;
RMSTAR_setbudget
(local_scheduler_level
, *thread
, (int)(server
));
break;
case FSF_NONE
:
dummy_task_def_arg
(*( DUMMY_TASK_MODEL
*)(local_scheduler_arg
->params
),arg
);
dummy_task_def_level
(*( DUMMY_TASK_MODEL
*)(local_scheduler_arg
->params
),local_scheduler_level
);
#ifdef FSF_DEBUG
kern_printf
("(None Server create task)");
#endif
*thread
= task_create
("NONESTAR", thread_code
, local_scheduler_arg
->params
, NULL
);
if (*thread
== NIL
)
return FSF_ERR_INTERNAL_ERROR
;
NONESTAR_setbudget
(local_scheduler_level
, *thread
, (int)(server
));
break;
default:
return FSF_ERR_INTERNAL_ERROR
;
break;
}
#ifdef FSF_DEBUG
kern_printf
("(FSF:Insert thread = %d to Server = %d)",*thread
,server
);
#endif
return 0;
}
int fsf_settask_nopreemptive
(fsf_server_id_t
*server
,
pthread_t thread
)
{
int local_scheduler_level
, scheduler_id
;
local_scheduler_level
= SERVER_get_local_scheduler_level_from_pid
(fsf_server_level
,thread
);
scheduler_id
= SERVER_get_local_scheduler_id_from_pid
(fsf_server_level
, thread
);
switch (scheduler_id
) {
case FSF_POSIX
:
POSIXSTAR_set_nopreemtive_current
(local_scheduler_level
);
return 1;
break;
case FSF_EDF
:
EDFSTAR_set_nopreemtive_current
(local_scheduler_level
);
return 1;
break;
case FSF_RM
:
RMSTAR_set_nopreemtive_current
(local_scheduler_level
);
return 1;
break;
case FSF_NONE
:
break;
default:
return -1;
}
return -1;
}
int fsf_settask_preemptive
(fsf_server_id_t
*server
,
pthread_t thread
)
{
int local_scheduler_level
, scheduler_id
;
local_scheduler_level
= SERVER_get_local_scheduler_level_from_pid
(fsf_server_level
,thread
);
scheduler_id
= SERVER_get_local_scheduler_id_from_pid
(fsf_server_level
, thread
);
switch (scheduler_id
) {
case FSF_POSIX
:
POSIXSTAR_unset_nopreemtive_current
(local_scheduler_level
);
return 1;
break;
case FSF_EDF
:
EDFSTAR_unset_nopreemtive_current
(local_scheduler_level
);
return 1;
break;
case FSF_RM
:
RMSTAR_unset_nopreemtive_current
(local_scheduler_level
);
return 1;
break;
case FSF_NONE
:
break;
default:
return -1;
}
return -1;
}
int fsf_get_server
(pthread_t thread
,
fsf_server_id_t
*server
)
{
int local_scheduler_level
, scheduler_id
;
local_scheduler_level
= SERVER_get_local_scheduler_level_from_pid
(fsf_server_level
,thread
);
scheduler_id
= SERVER_get_local_scheduler_id_from_pid
(fsf_server_level
, thread
);
switch (scheduler_id
) {
case FSF_POSIX
:
*server
= POSIXSTAR_getbudget
(local_scheduler_level
,thread
);
return 0;
case FSF_EDF
:
*server
= EDFSTAR_getbudget
(local_scheduler_level
,thread
);
return 0;
case FSF_RM
:
*server
= RMSTAR_getbudget
(local_scheduler_level
,thread
);
return 0;
case FSF_NONE
:
*server
= NONESTAR_getbudget
(local_scheduler_level
,thread
);
return 0;
default:
return -1;
}
return -1;
}
int fsf_get_server_level
(void)
{
return fsf_server_level
;
}
int fsf_cancel_contract
(fsf_server_id_t server
)
{
int local_scheduler_level
, scheduler_id
;
SYS_FLAGS f
;
TIME T
,Q
;
int i
=0;
#ifdef FSF_DEBUG
kern_printf
("(Remove server %d)",server
);
#endif
/* Check server id */
if (server
< 0)
return FSF_ERR_BAD_ARGUMENT
;
local_scheduler_level
= SERVER_get_local_scheduler_level_from_budget
(fsf_server_level
,server
);
scheduler_id
= SERVER_get_local_scheduler_id_from_budget
(fsf_server_level
,server
);
switch (scheduler_id
) {
case FSF_POSIX
:
/* Check if some thread use the server */
if(POSIXSTAR_budget_has_thread
(local_scheduler_level
,server
))
return FSF_ERR_NOT_CONTRACTED_SERVER
;
break;
case FSF_EDF
:
/* Check if some thread use the server */
if(EDFSTAR_budget_has_thread
(local_scheduler_level
,server
))
return FSF_ERR_NOT_CONTRACTED_SERVER
;
break;
case FSF_RM
:
/* Check if some thread use the server */
if(RMSTAR_budget_has_thread
(local_scheduler_level
,server
))
return FSF_ERR_NOT_CONTRACTED_SERVER
;
break;
case FSF_NONE
:
/* Check if some thread use the server */
if(NONESTAR_budget_has_thread
(local_scheduler_level
,server
))
return FSF_ERR_NOT_CONTRACTED_SERVER
;
break;
}
SERVER_removebudget
(fsf_server_level
,server
);
level_free_descriptor
(local_scheduler_level
);
remove_contract
(server
);
f
=kern_fsave
();
if (recalculate_contract
(fsf_max_bw
)==-1) {
kern_frestore
(f
);
return FSF_ERR_INTERNAL_ERROR
;
}
#ifdef FSF_DEBUG
kern_printf
("(Adjust budget)");
#endif
for (i
=0; i
<current_server
; i
++) {
mul32div32to32
(MAX_BANDWIDTH
,server_list
[i
].
Cmin,server_list
[i
].
U,T
);
if (T
> server_list
[i
].
Tmin ) {
server_list
[i
].
actual_budget = server_list
[i
].
Cmin;
server_list
[i
].
actual_period = T
;
#ifdef FSF_DEBUG
kern_printf
("(1 - Q %ld T %ld)", server_list
[i
].
actual_budget, server_list
[i
].
actual_period);
#endif
if (server_list
[i
].
d_equals_t == true)
adjust_SERVER_budget
(server_list
[i
].
server,server_list
[i
].
Cmin, T
, T
);
else
adjust_SERVER_budget
(server_list
[i
].
server,server_list
[i
].
Cmin, T
, server_list
[i
].
deadline);
} else {
mul32div32to32
(server_list
[i
].
Tmin,server_list
[i
].
U,MAX_BANDWIDTH
,Q
);
server_list
[i
].
actual_budget = Q
;
server_list
[i
].
actual_period = server_list
[i
].
Tmin;
#ifdef FSF_DEBUG
kern_printf
("(2 - Q %ld T %ld)", server_list
[i
].
actual_budget, server_list
[i
].
actual_period);
#endif
if (server_list
[i
].
d_equals_t == true)
adjust_SERVER_budget
(server_list
[i
].
server,Q
, server_list
[i
].
Tmin, server_list
[i
].
Tmin);
else
adjust_SERVER_budget
(server_list
[i
].
server,Q
, server_list
[i
].
Tmin, server_list
[i
].
deadline);
}
server_list
[i
].
U=server_list
[i
].
Umin;
}
kern_frestore
(f
);
return 0;
}
bandwidth_t SERVER_return_bandwidth
() {
int i
=0;
bandwidth_t U
;
U
=0;
for(i
=0;i
<current_server
;i
++) {
U
+=server_list
[i
].
Umin;
}
return U
;
}
int recalculate_contract
(bandwidth_t U
) {
bandwidth_t current_bandwidth
;
unsigned int temp_U
;
int Qt
;
int isok
=0;
int i
=0;
int target_importance
=FSF_DEFAULT_IMPORTANCE
;
#define MAX_IMPORTANCE 5
#ifdef FSF_DEBUG
int temp
;
kern_printf
("(RC)");
#endif
/* The current bandwidth is the min bandwidth */
current_bandwidth
=SERVER_return_bandwidth
(fsf_server_level
);
#ifdef FSF_DEBUG
kern_printf
("(SER%d)", current_server
);
#endif
//kern_printf("(CS:%d)", current_server);
do {
current_bandwidth
=0;
Qt
=0;
for (i
=0; i
<current_server
; i
++) {
if (server_list
[i
].
Is==target_importance
&& server_list
[i
].
U<server_list
[i
].
Umax && server_list
[i
].
Qs>0)
Qt
+=server_list
[i
].
Qs;
current_bandwidth
+=server_list
[i
].
U;
#ifdef FSF_DEBUG
kern_printf
("(Qs %d, Qt %d, Is %d)", server_list
[i
].
Qs, Qt
,server_list
[i
].
Is);
#endif
}
#ifdef FSF_DEBUG
kern_printf
("(TQ%d)", Qt
);
#endif
isok
=1;
for (i
=0; i
<current_server
; i
++) {
if (server_list
[i
].
Is==target_importance
&& server_list
[i
].
U<server_list
[i
].
Umax && server_list
[i
].
Qs>0) {
temp_U
=server_list
[i
].
U;
server_list
[i
].
U=U
-current_bandwidth
;
mul32div32to32
(server_list
[i
].
U, server_list
[i
].
Qs, Qt
, server_list
[i
].
U);
temp_U
+=server_list
[i
].
U;
if (temp_U
<=server_list
[i
].
Umin) {
server_list
[i
].
U=server_list
[i
].
Umin;
} else if (temp_U
>server_list
[i
].
Umax) {
server_list
[i
].
U=server_list
[i
].
Umax;
isok
=0;
} else server_list
[i
].
U=temp_U
;
#ifdef FSF_DEBUG
mul32div32to32
(server_list
[i
].
U,100, MAX_BANDWIDTH
, temp
);
kern_printf
("(SER %d BW %d)", server_list
[i
].
server, temp
);
#endif
}
}
target_importance
++;
} while (!isok
|| target_importance
<=MAX_IMPORTANCE
);
//kern_printf("(RNDNL)");
return 0;
}
int fsf_renegotiate_contract
(const fsf_contract_parameters_t
*new_contract
,
fsf_server_id_t server
)
{
struct mess msg
;
// send response server is -1 if the operation fail
msg.
type=RENEGOTIATE_CONTRACT
;
memmove(&msg.
contract,new_contract
, sizeof(fsf_contract_parameters_t
));
msg.
server = server
;
//kern_printf("(REN %d)", server);
port_send
(channel
[1],&msg
,BLOCK
);
port_receive
(channel
[0], &msg
, BLOCK
);
//kern_printf("(REN %d)", msg.server);
if (msg.
server==-1) return FSF_ERR_CONTRACT_REJECTED
;
return 0;
}
int fsf_request_contract_renegotiation
(const fsf_contract_parameters_t
*new_contract
,
fsf_server_id_t server
,
int sig_notify
,
union sigval sig_value
)
{
struct mess msg
;
// send response server is -1 if the operation fail
msg.
type=REQUEST_RENEGOTIATE_CONTRACT
;
memmove(&msg.
contract,new_contract
, sizeof(fsf_contract_parameters_t
));
msg.
server = server
;
port_send
(channel
[1],&msg
,BLOCK
);
port_receive
(channel
[0], &msg
, BLOCK
);
if (msg.
server==-1) return FSF_ERR_CONTRACT_REJECTED
;
return 0;
}
void print_server_list
()
{
int i
;
kern_printf
("Server List\n");
for(i
=0;i
<current_server
;i
++) {
kern_printf
("[%d] Q:%d T:%d D:%d [DeT = %d]\n",server_list
[i
].
server,(int)server_list
[i
].
actual_budget,(int)server_list
[i
].
actual_period,(int)server_list
[i
].
deadline,(int)server_list
[i
].
d_equals_t);
}
}
int fsf_get_remain_budget
(fsf_server_id_t server
) {
return SERVER_get_remain_capacity
(fsf_server_level
, server
);
}
int fsf_get_budget_and_period
(fsf_server_id_t server
,
struct timespec
*budget
,
struct timespec
*period
) {
TIME bg
;
TIME pd
;
if (!SERVER_getbudgetinfo
(fsf_server_level
, &bg
, &pd
, NULL
, server
)) {
if (budget
) {
NULL_TIMESPEC
(budget
);
ADDUSEC2TIMESPEC
(bg
, budget
);
}
if (period
) {
NULL_TIMESPEC
(period
);
ADDUSEC2TIMESPEC
(pd
, period
);
}
return 0;
}
return FSF_ERR_BAD_ARGUMENT
;
}
int
fsf_set_service_thread_data
(const struct timespec
*budget
,
const struct timespec
*period
,
bool
*accepted
) {
if (budget
==NULL
&& period
==NULL
) return FSF_ERR_BAD_ARGUMENT
;
fsf_set_contract_basic_parameters
(&service_contract
,budget
,period
,FSF_DEFAULT_WORKLOAD
);
*accepted
= !fsf_renegotiate_contract
(&service_contract
,service_server
)?true:false;
return 0;
}
int fsf_get_service_thread_data
(struct timespec
*budget
,
struct timespec
*period
) {
return fsf_get_budget_and_period
(service_server
, budget
, period
);
}