Subversion Repositories shark

Rev

Rev 221 | Rev 811 | 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 <kernel/descr.h>
#include <kernel/func.h>
#include <pistar.h>

struct hash_entry {
  mutex_t mx;
  fsf_shared_obj_id_t id;
};


#define MAX_HASH_ENTRY FSF_MAX_SHARED_OPERATION
struct  hash_entry htable[MAX_HASH_ENTRY];


/*----------------------------------------------------------------------*/
/* hash_fun() : address hash table                                      */
/*----------------------------------------------------------------------*/
static int hash_fun(fsf_shared_obj_id_t *id)
{
    return (*id % MAX_HASH_ENTRY);
}


int fsf_initialize_contract
  (fsf_contract_parameters_t *contract)
{
  struct timespec default_deadline = FSF_DEFAULT_DEADLINE;

  /* Check */
  if (!contract) return FSF_ERR_NOT_INITIALIZED;

  /* Set to default value */
  NULL_TIMESPEC(&contract->budget_min);
  NULL_TIMESPEC(&contract->budget_max);
  NULL_TIMESPEC(&contract->period_min);
  NULL_TIMESPEC(&contract->period_max);

  contract->workload = FSF_DEFAULT_WORKLOAD;

  contract->local_scheduler_id = FSF_DEFAULT_SCHEDULER;

  contract->d_equals_t = FSF_DEFAULT_D_EQUALS_T;

  TIMESPEC_ASSIGN(&contract->deadline,&default_deadline);

  contract->budget_overrun_sig_notify = 0;
  memset(&contract->budget_overrun_sig_value,0,sizeof(union sigval));

  contract->deadline_miss_sig_notify = 0;
  memset(&contract->deadline_miss_sig_value,0,sizeof(union sigval));

  contract->granularity = FSF_DEFAULT_GRANULARITY;
  contract->utilization_set.size = 0;
  contract->quality = FSF_DEFAULT_QUALITY;
  contract->importance = FSF_DEFAULT_IMPORTANCE;

  contract->preemption_level = 0;
  contract->critical_sections.size = 0;
 
  return 0;

}
 
int fsf_set_contract_basic_parameters
  (fsf_contract_parameters_t *contract,
   const struct timespec  *budget_min,
   const struct timespec  *period_max,
   const struct timespec  *budget_max,
   const struct timespec  *period_min,
   fsf_workload_t          workload)
{

  if (!contract) return FSF_ERR_NOT_INITIALIZED;

  if (budget_min) TIMESPEC_ASSIGN(&contract->budget_min,budget_min);
  if (period_max) TIMESPEC_ASSIGN(&contract->period_max,period_max);
  if (budget_max) TIMESPEC_ASSIGN(&contract->budget_max,budget_max);
  if (period_min) TIMESPEC_ASSIGN(&contract->period_min,period_min);

  contract->workload = workload;

  return 0;
 
}

int fsf_get_contract_basic_parameters
  (const fsf_contract_parameters_t *contract,
   struct timespec  *budget_min,
   struct timespec  *period_max,
   struct timespec  *budget_max,
   struct timespec  *period_min,
   fsf_workload_t   *workload)
{

  if (!contract) return FSF_ERR_NOT_INITIALIZED;

  TIMESPEC_ASSIGN(budget_min,&contract->budget_min);
  TIMESPEC_ASSIGN(period_max,&contract->period_max);
  TIMESPEC_ASSIGN(budget_max,&contract->budget_max);
  TIMESPEC_ASSIGN(period_min,&contract->period_min);

  *workload = contract->workload;

  return 0;

}

int fsf_set_contract_timing_requirements
  (fsf_contract_parameters_t *contract,
   bool                   d_equals_t,
   const struct timespec *deadline,
   int                    budget_overrun_sig_notify,
   union sigval           budget_overrun_sig_value,
   int                    deadline_miss_sig_notify,
   union sigval           deadline_miss_sig_value)
{

  if (!contract) return FSF_ERR_NOT_INITIALIZED;

  contract->d_equals_t = d_equals_t;

  if (deadline) TIMESPEC_ASSIGN(&contract->deadline,deadline);

  contract->budget_overrun_sig_notify = budget_overrun_sig_notify;
  contract->budget_overrun_sig_value = budget_overrun_sig_value;
  contract->deadline_miss_sig_notify = deadline_miss_sig_notify;
  contract->deadline_miss_sig_value = deadline_miss_sig_value;

  return 0;

}

int fsf_get_contract_timing_requirements
  (const fsf_contract_parameters_t *contract,
   bool                            *d_equals_t,
   struct timespec                 *deadline,
   int                             *budget_overrun_sig_notify,
   union sigval                    *budget_overrun_sig_value,
   int                             *deadline_miss_sig_notify,
   union sigval                    *deadline_miss_sig_value)
{

  if (!contract) return FSF_ERR_NOT_INITIALIZED;
                                                                                                                             
  *d_equals_t = contract->d_equals_t;
                                                                                                                             
  TIMESPEC_ASSIGN(deadline,&contract->deadline);
                                                                                                                             
  *budget_overrun_sig_notify = contract->budget_overrun_sig_notify;
  *budget_overrun_sig_value = contract->budget_overrun_sig_value;
  *deadline_miss_sig_notify = contract->deadline_miss_sig_notify;
  *deadline_miss_sig_value = contract->deadline_miss_sig_value;

  return 0;

}

int fsf_set_contract_reclamation_parameters
  (fsf_contract_parameters_t    *contract,
   fsf_granularity_t            granularity,
   const fsf_utilization_set_t  *utilization_set,
   int                          quality,
   int                          importance)
{

  if (!contract) return FSF_ERR_NOT_INITIALIZED;

  contract->granularity = granularity;

  if (utilization_set) memcpy(&contract->utilization_set,utilization_set,sizeof(fsf_utilization_set_t));
 
  contract->quality = quality;
  contract->importance = importance;

  return 0;

}
                                                                                                                             
int fsf_get_contract_reclamation_parameters
  (const fsf_contract_parameters_t *contract,
   fsf_granularity_t               *granularity,
   fsf_utilization_set_t           *utilization_set,
   int                             *quality,
   int                             *importance)
{

  if (!contract) return FSF_ERR_NOT_INITIALIZED;
                                                                                                                             
  *granularity = contract->granularity;
                                                                                                                             
  memcpy(utilization_set,&contract->utilization_set,sizeof(fsf_utilization_set_t));
                                                                                                                             
  *quality = contract->quality;
  *importance = contract->importance;
                                                                                                                             
  return 0;

}

/* OLD VERSION
int fsf_set_contract_synchronization_parameters
  (fsf_contract_parameters_t     *contract,
   fsf_preemption_level_t         preemption_level,
   const fsf_critical_sections_t *critical_sections)
{

  if (!contract) return FSF_ERR_NOT_INITIALIZED;

  contract->preemption_level = preemption_level;

  if (critical_sections) memcpy(&contract->critical_sections,critical_sections,sizeof(fsf_critical_sections_t));

  return 0;

}
*/

                                                                                                                             
int
fsf_get_contract_synchronization_parameters
  (const fsf_contract_parameters_t *contract,
   fsf_preemption_level_t          *preemption_level,
   fsf_critical_sections_t         *critical_sections)
{
 
  if (!contract) return FSF_ERR_NOT_INITIALIZED;
                                                                                                                             
  *preemption_level = contract->preemption_level;
                                                                                                                             
  memcpy(critical_sections,&contract->critical_sections,sizeof(fsf_critical_sections_t));
 
  return 0;

}

int
fsf_set_local_scheduler_parameter
  (fsf_contract_parameters_t *contract,
   fsf_scheduler_id_t local_scheduler_id)
{

  if (!contract) return FSF_ERR_NOT_INITIALIZED;

  contract->local_scheduler_id = local_scheduler_id;

  return 0;

}

int
fsf_get_local_scheduler_parameter
  (const fsf_contract_parameters_t *contract,
   fsf_scheduler_id_t *local_scheduler_id)
{

  if (!contract) return FSF_ERR_NOT_INITIALIZED;

  *local_scheduler_id = contract->local_scheduler_id;

  return 0;

}

// mutex lock function

int fsf_lock_object(fsf_shared_operation_t *op) {
  int index, oldindex;

  index=hash_fun(&op->obj_id);  

  if (htable[index].id!=op->obj_id) {
    oldindex=index;
    index = (index + 1) % MAX_HASH_ENTRY;
    // find
    for (;htable[index].id != op->obj_id, index!=oldindex; (index++) % MAX_HASH_ENTRY);
    if (index==oldindex) return -1;
  }

  // we need a special implementation for mutex_lock ... additional parameter

  return PISTAR_lock(FSF_get_shared_object_level(), &htable[index].mx,TIMESPEC2USEC(&op->wcet) );

}

int fsf_unlock_object(fsf_shared_operation_t *op) {

  int index, oldindex;

  index=hash_fun(&op->obj_id);  

  if (htable[index].id!=op->obj_id) {
    oldindex=index;
    index = (index + 1) % MAX_HASH_ENTRY;
    // find
    for (;htable[index].id != op->obj_id, index!=oldindex; (index++) % MAX_HASH_ENTRY);
    if (index==oldindex) return -1;
  }
  return mutex_unlock(&htable[index].mx);
 


}

void fsf_init_shared_object(fsf_shared_object_t *obj,
                            fsf_shared_obj_id_t id) {
  int index;
  int oldindex;
  PISTAR_mutexattr_t a;

  PISTAR_mutexattr_default(a);

  obj->size=0;
  index=hash_fun(&id);
  if (htable[index].id>=0) {
    oldindex=index;
    index = (index + 1) % MAX_HASH_ENTRY;
    // collision detection
    for (;htable[index].id >=0, index!=oldindex; (index++) % MAX_HASH_ENTRY);
    // table is full
    if (index==oldindex) return;
  }
  mutex_init(&(htable[index]).mx, &a);
  obj->obj_id=id;

}


// Declare an operation
// This function is used to declare that a shared object has
//    a synchronized operation on it.
// It checks if another operation with the same id has already been
//    declared; if so, return false (-1).
// The obj_id field of the operation is set equal to the shared object id.
// the structure op is copied in the first free element in the array
//    shared_op pof the structure obj. If there are no more free element,
//    returns -1.
// Returns 0 if the operation has been completed, -1 otherwise.

int fsf_declare_shared_object_operation(fsf_shared_object_t *obj,
                                        fsf_shared_operation_t *op) {
  int i;
  for (i=0; i<obj->size; i++) {
    // fail if the operation already declared
    if (op->op_id==obj->shared_op[i].op_id)
      return -1;    
  }
 
  // fail if the object is full
  if (obj->size>(FSF_MAX_SHARED_OPERATION-1))
    return -1;  

  obj->size++;
  obj->shared_op[i].op_id=op->op_id;
  obj->shared_op[i].wcet=op->wcet;
  obj->shared_op[i].obj_id=obj->obj_id;
  op->obj_id=obj->obj_id;
 
  return 0;


}

int fsf_set_contract_synchronization_parameters(
    fsf_contract_parameters_t *contract,
    const fsf_shared_operation_t *shared_ops,
    size_t op_num)
{
  if (shared_ops && op_num < FSF_MAX_SHARED_OPERATION)
    memcpy(&contract->shared_operations,shared_ops,op_num);
  else return -1;
 
  return 0;
}