Subversion Repositories shark

Rev

Rev 234 | Rev 241 | 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 "rmstar.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:
        local_scheduler_level = RMSTAR_register_level(fsf_cbsstar_level);
       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:

      if (RMSTAR_getbudget(local_scheduler_level,thread) != -1)
        return FSF_ERR_BIND_THREAD;

      /* Set server on local scheduler */
      RMSTAR_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 RMSTAR 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);

    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:

      if (RMSTAR_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;
  }

  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:
      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 = 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:
      /* 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;
  }

  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);

}