Rev 226 | Rev 235 | 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 "fsf_contract.h"
#include "cbsstar.h"
#include "posixstar.h"
#include "edfstar.h"
#include "posix.h"
#include "comm_message.h"
#include <pthread.h>
#include <stdlib.h>
//#define FSF_DEBUG
int fsf_cbsstar_level;
int fsf_posix_level;
int FSF_register_module(int posix_level, int cbsstar_level)
{
printk("FSF Module\n");
fsf_posix_level = posix_level;
fsf_cbsstar_level = cbsstar_level;
return 0;
}
/* Convert the contract specification to
* budget parameters
*/
int set_CBSSTAR_budget_from_contract
(const fsf_contract_parameters_t *contract,
int *budget)
{
int local_scheduler_level = 0;
switch (contract->local_scheduler_id) {
case FSF_SCHEDULER_POSIX:
local_scheduler_level = POSIXSTAR_register_level(fsf_cbsstar_level,5000,32);
break;
case FSF_SCHEDULER_EDF:
local_scheduler_level = EDFSTAR_register_level(fsf_cbsstar_level);
break;
case FSF_SCHEDULER_RM:
break;
}
*budget = CBSSTAR_setbudget(fsf_cbsstar_level,
TIMESPEC2USEC(&(contract->budget_min)),
TIMESPEC2USEC(&(contract->period_max)),
local_scheduler_level,contract->local_scheduler_id);
return 0;
}
int adjust_CBSSTAR_budget_from_contract
(const fsf_contract_parameters_t *contract,
int budget)
{
CBSSTAR_adjust_budget(fsf_cbsstar_level,
TIMESPEC2USEC(&(contract->budget_min)),
TIMESPEC2USEC(&(contract->period_max)),
budget);
return 0;
}
/* Admission Test function */
int add_contract(const fsf_contract_parameters_t *contract)
{
return 0;
}
int link_contract_to_server(const fsf_contract_parameters_t *contract,
fsf_server_id_t server)
{
return 0;
}
int remove_contract(fsf_server_id_t server)
{
return 0;
}
int fsf_negotiate_contract
(const fsf_contract_parameters_t *contract,
fsf_server_id_t *server)
{
/* Check if contract is initialized */
if (!contract) return FSF_ERR_NOT_INITIALIZED;
/* Admission Test */
if (FSF_ADMISSION_TEST_IS_ENABLED)
if (add_contract(contract))
return FSF_ERR_CONTRACT_REJECTED;
/* SERVER = BUDGET */
set_CBSSTAR_budget_from_contract(contract,server);
#ifdef FSF_DEBUG
kern_printf("(New Server %d)",*server);
#endif
if (*server >= 0)
link_contract_to_server(contract,*server);
else
return FSF_ERR_CREATE_SERVER;
return 0;
}
int fsf_bind_thread_to_server
(fsf_server_id_t server,
pthread_t thread,
void *rt_arg)
{
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_BIND_THREAD;
local_scheduler_level = CBSSTAR_get_local_scheduler_level_from_budget(fsf_cbsstar_level,server);
scheduler_id = CBSSTAR_get_local_scheduler_id_from_budget(fsf_cbsstar_level,server);
/* Check if thread is already bind */
switch (scheduler_id) {
case FSF_SCHEDULER_POSIX:
if (POSIXSTAR_getbudget(local_scheduler_level,thread) != -1)
return FSF_ERR_BIND_THREAD;
/* Set server on local scheduler */
POSIXSTAR_setbudget(local_scheduler_level,thread,(int)(server));
/* Send change level command to posix level */
msg = (STD_command_message *)malloc(sizeof(STD_command_message));
#ifdef FSF_DEBUG
kern_printf("(MSG POSIXSTAR LEV %d SER %d THR %d)",local_scheduler_level,server,thread);
#endif
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);
break;
case FSF_SCHEDULER_EDF:
if (EDFSTAR_getbudget(local_scheduler_level,thread) != -1)
return FSF_ERR_BIND_THREAD;
/* Set server on local scheduler */
EDFSTAR_setbudget(local_scheduler_level,thread,(int)(server));
/* Send change level command to posix level */
msg = (STD_command_message *)malloc(sizeof(STD_command_message));
#ifdef FSF_DEBUG
kern_printf("(MSG EDFSTAR LEV %d SEV %d THR %d)",local_scheduler_level,server,thread);
#endif
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);
break;
case FSF_SCHEDULER_RM:
default:
return FSF_ERR_BIND_THREAD;
break;
}
return 0;
}
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_UNBIND_THREAD;
local_scheduler_level = CBSSTAR_get_local_scheduler_level_from_pid(fsf_cbsstar_level,thread);
scheduler_id = CBSSTAR_get_local_scheduler_id_from_pid(fsf_cbsstar_level,thread);
switch (scheduler_id) {
case FSF_SCHEDULER_POSIX:
/* Check if it is bind to a server */
if (POSIXSTAR_getbudget(local_scheduler_level,thread) == -1)
return FSF_ERR_UNBIND_THREAD;
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);
}
break;
case FSF_SCHEDULER_EDF:
if (EDFSTAR_getbudget(local_scheduler_level,thread) == -1)
return FSF_ERR_UNBIND_THREAD;
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);
}
break;
case FSF_SCHEDULER_RM:
break;
}
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,
void *rt_arg)
{
int error;
/* Create server */
error = fsf_negotiate_contract(contract, server);
if (error) return error;
/* Create pthread */
if (pthread_create(thread, attr, thread_code, arg))
return FSF_ERR_CREATE_THREAD;
/* Bind thread to server */
error = fsf_bind_thread_to_server(*server, *thread, rt_arg);
if (error) return error;
return 0;
}
int fsf_negotiate_contract_for_myself
(const fsf_contract_parameters_t *contract,
fsf_server_id_t *server,
void *rt_arg)
{
int error;
/* Create server */
error = fsf_negotiate_contract(contract, server);
if (error) return error;
/* Bind current thread to server */
error = fsf_bind_thread_to_server(*server, exec_shadow, rt_arg);
if (error) return error;
return 0;
}
int fsf_get_server
(fsf_server_id_t *server,
pthread_t thread)
{
int local_scheduler_level, scheduler_id;
local_scheduler_level = CBSSTAR_get_local_scheduler_level_from_pid(fsf_cbsstar_level,thread);
scheduler_id = CBSSTAR_get_local_scheduler_id_from_pid(fsf_cbsstar_level, thread);
switch (scheduler_id) {
case FSF_SCHEDULER_POSIX:
return POSIXSTAR_getbudget(local_scheduler_level,thread);
case FSF_SCHEDULER_EDF:
case FSF_SCHEDULER_RM:
return -1;
}
return -1;
}
int fsf_cancel_contract
(fsf_server_id_t *server)
{
int local_scheduler_level, scheduler_id;
#ifdef FSF_DEBUG
kern_printf("(Remove server %d)",*server);
#endif
/* Check server id */
if (*server < 0)
return FSF_ERR_INVALID_SERVER;
local_scheduler_level = CBSSTAR_get_local_scheduler_level_from_budget(fsf_cbsstar_level,*server);
scheduler_id = CBSSTAR_get_local_scheduler_id_from_budget(fsf_cbsstar_level,*server);
switch (scheduler_id) {
case FSF_SCHEDULER_POSIX:
/* Check if some thread use the server */
if(POSIXSTAR_budget_has_thread(local_scheduler_level,*server))
return FSF_ERR_SERVER_USED;
break;
case FSF_SCHEDULER_EDF:
case FSF_SCHEDULER_RM:
break;
}
CBSSTAR_removebudget(fsf_cbsstar_level,*server);
level_free_descriptor(local_scheduler_level);
remove_contract(*server);
*server = -1;
return 0;
}
int fsf_renegotiate_contract
(const fsf_contract_parameters_t *new_contract,
fsf_server_id_t server)
{
#ifdef FSF_DEBUG
kern_printf("(Renegotiate for server %d)",server);
#endif
if (!new_contract)
return FSF_ERR_NOT_INITIALIZED;
if (server < 0)
return FSF_ERR_INVALID_SERVER;
return adjust_CBSSTAR_budget_from_contract(new_contract,server);
}