Rev 267 | Rev 298 | 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 "fsf_server.h"
#include <pthread.h>
#include <stdlib.h>
//#define FSF_DEBUG
int fsf_server_level;
int FSF_register_module(int server_level)
{
printk("FSF Module\n");
fsf_server_level = server_level;
return 0;
}
/* 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->local_scheduler_id) {
case FSF_SCHEDULER_POSIX:
local_scheduler_level = POSIXSTAR_register_level(fsf_server_level,5000,32);
break;
case FSF_SCHEDULER_EDF:
local_scheduler_level = EDFSTAR_register_level(fsf_server_level);
break;
case FSF_SCHEDULER_RM:
local_scheduler_level = RMSTAR_register_level(fsf_server_level);
break;
}
*budget = SERVER_setbudget(fsf_server_level,
TIMESPEC2USEC(&(contract->budget_min)),
TIMESPEC2USEC(&(contract->period_max)),
local_scheduler_level,contract->local_scheduler_id);
return 0;
}
int adjust_SERVER_budget_from_contract
(const fsf_contract_parameters_t *contract,
int budget)
{
SERVER_adjust_budget(fsf_server_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_SERVER_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_create_thread
(fsf_server_id_t server,
pthread_t *thread,
pthread_attr_t *attr,
fsf_thread_code_t thread_code,
void *arg,
void *local_scheduler_arg)
{
NRT_TASK_MODEL nrt;
int local_scheduler_level,scheduler_id;
#ifdef FSF_DEBUG
kern_printf("(FSF:Insert thread = %d to Server = %d)",*thread,server);
#endif
/* Check if server and thread exsist */
if (server == NIL)
return FSF_ERR_INVALID_SERVER;
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);
/* Check if thread is already bind */
switch (scheduler_id) {
case FSF_SCHEDULER_POSIX:
if (local_scheduler_arg == NULL) {
nrt_task_default_model(nrt);
nrt_task_def_save_arrivals(nrt);
nrt_task_def_arg(nrt,arg);
nrt_task_def_ctrl_jet(nrt);
nrt_task_def_level(nrt,local_scheduler_level);
*thread = task_create("POSIXSTAR", thread_code, &nrt, NULL);
}
if (*thread == NIL) {
#ifdef FSF_DEBUG
kern_printf("(FSF:Error creating thread)");
#endif
return FSF_ERR_CREATE_THREAD;
}
POSIXSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
task_activate(*thread);
break;
case FSF_SCHEDULER_EDF:
hard_task_def_arg(*(HARD_TASK_MODEL *)(local_scheduler_arg),arg);
hard_task_def_level(*(HARD_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
*thread = task_create("EDFSTAR", thread_code, local_scheduler_arg, NULL);
if (*thread == NIL)
return FSF_ERR_CREATE_THREAD;
EDFSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
task_activate(*thread);
break;
case FSF_SCHEDULER_RM:
hard_task_def_arg(*(HARD_TASK_MODEL *)(local_scheduler_arg),arg);
hard_task_def_level(*(HARD_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
*thread = task_create("RMSTAR", thread_code, local_scheduler_arg, NULL);
if (*thread == NIL)
return FSF_ERR_CREATE_THREAD;
RMSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
task_activate(*thread);
break;
default:
return FSF_ERR_INVALID_SERVER;
break;
}
return 0;
}
int fsf_get_server
(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_SCHEDULER_POSIX:
return POSIXSTAR_getbudget(local_scheduler_level,thread);
case FSF_SCHEDULER_EDF:
return EDFSTAR_getbudget(local_scheduler_level,thread);
case FSF_SCHEDULER_RM:
return RMSTAR_getbudget(local_scheduler_level,thread);
default:
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 = 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_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:
/* Check if some thread use the server */
if(EDFSTAR_budget_has_thread(local_scheduler_level,*server))
return FSF_ERR_SERVER_USED;
break;
case FSF_SCHEDULER_RM:
/* Check if some thread use the server */
if(RMSTAR_budget_has_thread(local_scheduler_level,*server))
return FSF_ERR_SERVER_USED;
break;
}
SERVER_removebudget(fsf_server_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_SERVER_budget_from_contract(new_contract,server);
}