Subversion Repositories shark

Rev

Rev 799 | Rev 868 | 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"

extern int fsf_server_level;

//#define FSF_DEBUG

int
fsf_create_synchobject(fsf_synch_object_handle_t *synch_handle)
{
  
  if (!synch_handle) return FSF_ERR_INVALID_SYNCH_OBJECT_HANDLE;

  iq_init(&synch_handle->threads, NULL, 0);  
  synch_handle->events = 0;

  return 0;

}

int
fsf_signal_synchobject(fsf_synch_object_handle_t *synch_handle)
{

  PID p;

  if (!synch_handle) return FSF_ERR_INVALID_SYNCH_OBJECT_HANDLE;
  
  if ((p = iq_getfirst(&synch_handle->threads)) != NIL)
    task_activate(p);
  else
    synch_handle->events++;

  return 0;

}

int
fsf_destroy_synchobject(fsf_synch_object_handle_t *synch_handle)
{

  if (!synch_handle) return FSF_ERR_INVALID_SYNCH_OBJECT_HANDLE;

  while (iq_getfirst(&synch_handle->threads) != NIL);  
  synch_handle->events = 0;

  return 0;

}

int fsf_schedule_next_timed_job
  (const struct timespec *at_absolute_time,
   struct timespec       *next_budget,
   struct timespec       *next_period,
   bool                  *was_deadline_missed,
   bool                  *was_budget_overran)
{

  TIME T,Q,D;
  int budget, local_scheduler_level, scheduler_id;

  local_scheduler_level = SERVER_get_local_scheduler_level_from_pid(fsf_server_level, exec_shadow);
  scheduler_id = SERVER_get_local_scheduler_id_from_pid(fsf_server_level, exec_shadow);

  if (proc_table[exec_shadow].task_level != local_scheduler_level) return 0;

  switch (scheduler_id) {
    case FSF_SCHEDULER_POSIX:
      budget = POSIXSTAR_getbudget(local_scheduler_level, exec_shadow);
      break;
    case FSF_SCHEDULER_EDF:
      budget = EDFSTAR_getbudget(local_scheduler_level, exec_shadow);
      break;
    case FSF_SCHEDULER_NONE:
      budget = NONESTAR_getbudget(local_scheduler_level, exec_shadow);
      break;
    case FSF_SCHEDULER_RM:
      budget = RMSTAR_getbudget(local_scheduler_level, exec_shadow);
      break;

    default:
      budget = -1;
      break;
  }

  if (budget == -1) return FSF_ERR_INVALID_SERVER; 

  if (next_budget != NULL && next_period != NULL) {

    SERVER_getbudgetinfo(fsf_server_level, &Q, &T, &D, budget);
 
    #ifdef FSF_DEBUG
      kern_printf("(budget %d Q=%d T=%d)",budget,(int)Q,(int)T);
    #endif

    next_budget->tv_sec = Q / 1000000;
    next_budget->tv_nsec = (Q % 1000000) * 1000;
    next_period->tv_sec = T / 1000000;
    next_period->tv_nsec = (T % 1000000) * 1000;

  }

  if (was_deadline_missed != NULL) 
    *was_deadline_missed = false;
  if (was_budget_overran != NULL) 
    *was_budget_overran = false;

  if (at_absolute_time != NULL)
    kern_event_post(at_absolute_time, (void (*)(void *))task_activate, (void *)(exec_shadow));

  #ifdef FSF_DEBUG
    if (at_absolute_time != NULL)
      kern_printf("(Next act s%d:us%d)",(int)at_absolute_time->tv_sec,(int)at_absolute_time->tv_nsec/1000);
    else
      kern_printf("(End Cycle %d)",exec_shadow);
  #endif

  task_endcycle();

  return 0;

}

int
fsf_schedule_next_event_triggered_job 
  (fsf_synch_object_handle_t *synch_handle,
   struct timespec           *next_budget,
   struct timespec           *next_period,
   bool                      *was_deadline_missed,
   bool                      *was_budget_overran)
{

  TIME T,Q,D;
  int budget, local_scheduler_level, scheduler_id;

  local_scheduler_level = SERVER_get_local_scheduler_level_from_pid(fsf_server_level, exec_shadow);
  scheduler_id = SERVER_get_local_scheduler_id_from_pid(fsf_server_level, exec_shadow);

  if (proc_table[exec_shadow].task_level != local_scheduler_level) return 0; 
 
  switch (scheduler_id) {
    case FSF_SCHEDULER_POSIX:
      budget = POSIXSTAR_getbudget(local_scheduler_level, exec_shadow);
      break;
    case FSF_SCHEDULER_EDF:
      budget = EDFSTAR_getbudget(local_scheduler_level, exec_shadow);
      break;
    case FSF_SCHEDULER_RM:
    default:
      budget = -1;
      break;
  }

  if (budget == -1) return FSF_ERR_INVALID_SERVER; 

  if (next_budget != NULL && next_period != NULL) {

    SERVER_getbudgetinfo(fsf_server_level, &Q, &T, &D, budget);
 
    #ifdef FSF_DEBUG
      kern_printf("(budget %d Q=%d T=%d)",budget,(int)Q,(int)T);
    #endif

    next_budget->tv_sec = Q / 1000000;
    next_budget->tv_nsec = (Q % 1000000) * 1000;
    next_period->tv_sec = T / 1000000;
    next_period->tv_nsec = (T % 1000000) * 1000;

  }

  if (was_deadline_missed != NULL) 
    *was_deadline_missed = false;
  if (was_budget_overran != NULL) 
    *was_budget_overran = false; 

  if (synch_handle->events > 0) {
    task_activate(exec_shadow);
    synch_handle->events--;
  } else
    iq_insertlast(exec_shadow,&synch_handle->threads);

  #ifdef FSF_DEBUG
    kern_printf("(Synch_Handle Events %d)",synch_handle->events);
  #endif

  task_endcycle();

  return 0;

}