Rev 910 | Rev 930 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
//=====================================================================
// 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");
exit(1);
}
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);
*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;
case FSF_TABLE_DRIVEN:
{
DUMMY_TASK_MODEL dt;
dummy_task_default_model(dt);
dummy_task_def_arg(dt,arg);
dummy_task_def_level(dt,local_scheduler_level);
*thread = task_create("TDSTAR", thread_code, &dt, NULL);
if (*thread == NIL)
return FSF_ERR_INTERNAL_ERROR;
TABLEDRIVEN_setbudget(local_scheduler_level, *thread, (int)(server));
TABLEDRIVEN_settable(local_scheduler_level, (fsf_table_driven_params_t *)(local_scheduler_arg->params));
}
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;
msg.sig_notify=sig_notify;
msg.sig_value=sig_value;
msg.process=exec_shadow;
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);
}