Subversion Repositories shark

Rev

Rev 1618 | Blame | Compare with Previous | Last modification | View Log | RSS feed


/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */


//=====================================================================
//       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.h"
#include "fsf_server.h"
#include <kernel/descr.h>
#include <kernel/func.h>
#include <pistar.h>
#include <arch/i386/string.h>

#define MAX_SHARED_NAME 15

struct hash_entry {
  mutex_t mx;
  char  shared_obj_name[MAX_SHARED_NAME];
  FSF_SHARED_OBJ_HANDLE_T_OPAQUE id;
};


#define MAX_HASH_ENTRY FSF_MAX_N_SHARED_OBJECTS
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);
}

void fsf_register_shared_object(void) {
int i=0;
// Init Hash table
//kern_printf("(IT SO)\n");
for (i=0; i<MAX_HASH_ENTRY; i++) {
  htable[i].id=-1;

}

}
int fsf_init() {

  FSF_start_service_task();
  FSF_init_synch_obj_layer();
  return 0;
}


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

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

  /* 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->policy = FSF_DEFAULT_SCHED_POLICY;

  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,  
   fsf_workload_t          workload)
{

  if (!contract) return  FSF_ERR_BAD_ARGUMENT;

  if (budget_min->tv_sec < 0 || budget_min->tv_nsec > 1000000000)
     return FSF_ERR_BAD_ARGUMENT;
 
  if (period_max->tv_sec < 0 || period_max->tv_nsec > 1000000000)
     return FSF_ERR_BAD_ARGUMENT;

  if (budget_min && (budget_min->tv_sec!=0 || budget_min->tv_nsec!=0)) {
     TIMESPEC_ASSIGN(&contract->budget_min,budget_min);
     TIMESPEC_ASSIGN(&contract->budget_max,budget_min);
  } else return FSF_ERR_BAD_ARGUMENT;
 
  if (period_max && (period_max->tv_sec!=0 || period_max->tv_nsec!=0)) {
     TIMESPEC_ASSIGN(&contract->period_max,period_max);
     TIMESPEC_ASSIGN(&contract->period_min,period_max);
  } else return FSF_ERR_BAD_ARGUMENT;

  switch(workload) {
     case FSF_INDETERMINATE:
     case FSF_BOUNDED:
     case FSF_OVERHEAD:
        contract->workload = workload;
        break;
     default: return FSF_ERR_BAD_ARGUMENT;
  }


  return 0;
 
}

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

  if (!contract) return FSF_ERR_BAD_ARGUMENT;

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

  *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_BAD_ARGUMENT;
  if ((d_equals_t==true && deadline != FSF_NULL_DEADLINE) ||
      (d_equals_t==false && deadline == FSF_NULL_DEADLINE))
     return FSF_ERR_BAD_ARGUMENT;
  if (deadline != FSF_NULL_DEADLINE && TIMESPEC_A_GT_B(deadline, &contract->period_max))
     return FSF_ERR_BAD_ARGUMENT;

  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_BAD_ARGUMENT;
                                                                                                                             
  *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,
   const struct timespec       *budget_max,
   const struct timespec       *period_min,
   fsf_granularity_t            granularity,
   const fsf_utilization_set_t *utilization_set,
   int                          quality,
   int                          importance)
{

  if (!contract) return  FSF_ERR_BAD_ARGUMENT;

  if (budget_max->tv_sec < 0 || budget_max->tv_nsec > 1000000000)
     return FSF_ERR_BAD_ARGUMENT;
 
  if (period_min->tv_sec < 0 || period_min->tv_nsec > 1000000000)
     return FSF_ERR_BAD_ARGUMENT;

  contract->granularity = granularity;

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

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

  contract->quality = quality;
  contract->importance = importance;

  return 0;

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

  if (!contract) return FSF_ERR_BAD_ARGUMENT;
                                                                                                                             
  *granularity = contract->granularity;
  if (utilization_set)
    memcpy(utilization_set,&contract->utilization_set,sizeof(fsf_utilization_set_t));

  TIMESPEC_ASSIGN(budget_max,&contract->budget_max);
  TIMESPEC_ASSIGN(period_min,&contract->period_min);
                                                                                                                             
  *quality = contract->quality;
  *importance = contract->importance;
                                                                                                                             
  return 0;

}

int fsf_set_contract_synchronization_parameters
  (fsf_contract_parameters_t     *contract,
   const fsf_critical_sections_t *critical_sections)
{

  if (!contract) return FSF_ERR_BAD_ARGUMENT;

  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_critical_sections_t         *critical_sections)
{
 
  if (!contract) return FSF_ERR_BAD_ARGUMENT;
  if (critical_sections)
    memcpy(critical_sections,&contract->critical_sections,sizeof(fsf_critical_sections_t));
 
  return 0;

}

int
fsf_set_contract_scheduling_policy
  (fsf_contract_parameters_t *contract,
   fsf_sched_policy_t         sched_policy)
{

  if (!contract) return  FSF_ERR_BAD_ARGUMENT;

  contract->policy = sched_policy;

  return 0;

}

int
fsf_get_contract_scheduling_policy
  (const fsf_contract_parameters_t *contract,
   fsf_sched_policy_t              *sched_policy)
{

  if (!contract) return FSF_ERR_BAD_ARGUMENT;

  *sched_policy = contract->policy;

  return 0;

}

/* OLD VERSION
// mutex lock function

int fsf_lock_object(fsf_shared_operation_t *op) {
  int index, oldindex;
 
  index=hash_fun(&(op->obj_id));  
  //kern_printf("index %d, htableid %d, obj_op_id %d", index, htable[index].id,op->obj_id);

  if (htable[index].id!=op->obj_id) {
    oldindex=index;
    index = (index + 1) % MAX_HASH_ENTRY;
    // find
    while (htable[index].id != op->obj_id && index!=oldindex) index=(index+1) % MAX_HASH_ENTRY;
    if (index==oldindex) return -1;
  }
  //kern_printf("(SO LK)");
  // 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
    while (htable[index].id != op->obj_id && index!=oldindex) index=(index+1) % MAX_HASH_ENTRY;
    if (index==oldindex) return -1;
  }
  //kern_printf("UNLOCK index %d", index);

  return mutex_unlock(&htable[index].mx);
 


}

*/



int fsf_get_shared_object_handle
   (fsf_shared_obj_id_t      obj_id,
    fsf_shared_obj_handle_t *obj_handle) {
  int index;
  int oldindex;
  SYS_FLAGS f;

  f=kern_fsave();

  index=hash_fun(obj_id);

  if (strcmp(htable[index].shared_obj_name,obj_id) == 0) {
        kern_frestore(f);
        return index;
  }

  if (htable[index].id!=0) {
    oldindex=index;
    index = (index + 1) % MAX_HASH_ENTRY;
    // collision detection
    while (htable[index].id !=0 && index!=oldindex) {
      if (strcmp(htable[index].shared_obj_name,obj_id) == 0) {
        kern_frestore(f);
        return index;
      }
      index=(index+1) % MAX_HASH_ENTRY;
    }
   
    // table is full
    if (index==oldindex) {
      kern_frestore(f);
      return -1;
    }
  }

  kern_frestore(f);
  return -1;

}



int fsf_init_shared_object
   (fsf_shared_obj_id_t      id,
    fsf_shared_obj_handle_t *obj,
    pthread_mutex_t         *mutex) {
  int index;
  int oldindex;
  PISTAR_mutexattr_t a;
  SYS_FLAGS f;

  PISTAR_mutexattr_default(a);
  //kern_printf("(SI SO)\n");
  f=kern_fsave();
 
  index=hash_fun(id);
  //kern_printf("Index %d Hash %d", index, htable[index].id);

  if (strcmp(htable[index].shared_obj_name,id) == 0) {
        kern_frestore(f);
        return -1;
  }

  if (htable[index].id!=0) {
    oldindex=index;
    index = (index + 1) % MAX_HASH_ENTRY;
    // collision detection
    while (htable[index].id !=0 && index!=oldindex) index=(index+1) % MAX_HASH_ENTRY;
    // table is full
    if (index==oldindex) {
        kern_frestore(f);
        return -1;
    }
  }
 
  //obj->size=0;

  mutex_init(&(htable[index]).mx, &a);
  mutex=&(htable[index]).mx;
  strncpy(htable[index].shared_obj_name, id,MAX_SHARED_NAME);
  *obj=index;
  kern_frestore(f);

  return 0;

  //kern_printf("(EI SO)\n");
}

/* OLD VERSION
// 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;
  SYS_FLAGS f;

  f=kern_fsave();

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

  //kern_printf("(DO SO)");
  obj->size++;
  obj->shared_op[i].op_id = op->op_id;
  TIMESPEC_ASSIGN(&obj->shared_op[i].wcet,&op->wcet);
  obj->shared_op[i].obj_id = obj->obj_id;
  op->obj_id = obj->obj_id;

  kern_frestore(f);  

  return 0;


}
*/


/* OLD VERSION
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;
}
*/


// MARTE IMPLEMENTATION SPECIFIC MODULE

// The operations defined in this module are of optional use. They
// only work in the fixed priority implementation, and they may be
// used to enhance the behavior of the applications running under the
// fsf scheduler.

//// The definition of this type is in fsf_basic_types.h
//
//typedef unsigned long      fsf_preemption_level_t;
//                           // range 1..2**32-1


//fsf_set_contract_preemption_level: The operation updates the
//specified contract parameters object by setting its preemption level
//to the specified input parameter.

int
fsf_set_contract_preemption_level
  (fsf_contract_parameters_t     *contract,
   fsf_preemption_level_t         preemption_level) {
  return 0;
}


//fsf_get_contract_preemption_level: The operation obtains from the
//specified contract parameters object its preemption level and copies
//it to the place pointed to by the specified input parameter.

int
fsf_get_contract_preemption_level
  (const fsf_contract_parameters_t *contract,
   fsf_preemption_level_t          *preemption_level)  {
  return 0;
}



//fsf_set_service_thread_preemption_level: this function sets the
//preemption level of the service thread to the specified value. The
//initial preemption level is a configurable parameter

int
fsf_set_service_thread_preemption_level
  (fsf_preemption_level_t         preemption_level) {
  return 0;
}


//fsf_get_service_thread_preemption_level: this function stores the
//current preemption level of the service thread in the variable
//pointed to by preemption_level

int
fsf_get_service_thread_preemption_level
  (fsf_preemption_level_t        *preemption_level) {
  return 0;
}



//fsf_thread_exit: There is a limitation in the current version of the
//MaRTE implementation that causes the information of a terminated
//thread to continue to be stored in the fsf scheduler, and the thread
//to continue to be counted in the number of threads. The
//fsf_thread_exit operation allows the implementation to delete the
//thread's information, and then terminate the thread. Therefore, it
//is recommended to use this function to terminate a thread under fsf.

//This operation shall terminate the calling thread, make the value
//value_ptr available to any successful join with the terminating
//thread, and unbind the thread from its associated server. After
//cleaning up the thread management data, it is unbound and the
//scheduling policy is changed to fixed priority before the posix
//pthread_exit() function is called.

void
fsf_thread_exit (void *value_ptr) {
  return;
}



//fsf_set_shared_obj_preemption_level: The operation updates the
//specified shared object by setting its preemption level
//to the specified input parameter.
//OBSERVATION: if this value is changed being any contract that
//uses the resource already accepted, the system's behavior and
//particularly the acceptance tests correctness are not garantee
//and probably wrong.

int
fsf_set_shared_obj_preemption_level
  (fsf_shared_obj_handle_t  obj_handle,
   fsf_preemption_level_t   preemption_level) {
  return 0;
}



//fsf_get_shared_obj_preemption_level: The operation obtains from the
//specified shared object its preemption level and copies
//it to the place pointed to by the specified input parameter.

int
fsf_get_shared_obj_preemption_level
  (fsf_shared_obj_handle_t  obj_handle,
   fsf_preemption_level_t  *preemption_level) {
  return 0;
}