Subversion Repositories shark

Rev

Rev 1063 | 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
 *
 */


#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>

#include <pthread.h>
#include <sched.h>
#include <fsf.h>
#include "timespec_operations.h"
#include "fsf_os_compatibility.h"


/*

 * This is part of the common tests:
 
 ** Test of the synchronization object primitives

  -  Create two servers, server A and server B. Each with 5 seconds budget
     and 20 seconds period (minimum values equal to the maximum ones),
     preemption levels for A = 4 and for B = 3, A is INDETERMINATE workload
     and B is BOUNDED workload. Deadline is 19.9 seconds for A and it is
     equal to the period for B. Server A is bound to the main thread with
     fsf_negotiate_contract_for_myself, server B is created with
     fsf_negotiate_contract_for_new_thread.
     
  -  Once the main program becomes server A, it creates a Synch_object
     and stores its reference in the global variable SO1_handle, then it
     creates server B for a new thread and releases
     the CPU for 0.5 second. The new thread in server B after starting,
     just waits for SO1 to be signaled, after that it executes during 1 second,
     then it waits for the the synchronization object SO1_handle to be signaled
     again, and finally ends.
     
  -  After the first release of the CPU, the main thread in server A
     signals SO1_handle and then releases the CPU for 0.5 second again,
     after that it signals SO1_handle a second time and releases the CPU for 2 seconds.
     Finally it destroy the synchronization object OS1 and ends.
     
*/


#define LOCAL_ERROR(nn,ss) {if(errno==0) errno=(nn); perror(ss); return (nn);}
//#define ERROR(nn,ss) {if(errno==0) errno=(nn); perror(ss); exit (nn);}
#define FSF_MAX_N_TIME_VALUES     1000

struct timespec            instant_zero = {0,0};
int                        main_priority = 4;
struct timespec            last_time = {0,0};
fsf_server_id_t            server_A = 0;
fsf_server_id_t            server_B = 0;
fsf_synch_obj_handle_t     SO1_handle;

extern int cal_cycles;
extern int calibrate_cycle(void);
extern void eat(TIME wait);

struct pseudo_printed_results {
  char            *s;
  struct timespec  t;
}                                  res[FSF_MAX_N_TIME_VALUES];
volatile int                       res_index = 0;

//reports the real-time it is
//with a comment and the difference to the last reported time
int
put_time(const struct timespec *time, char *s)
{
  struct timespec now = {0,0};
  int terror;

//  if(time == (struct timespec *)NULL) {
    if ((terror=clock_gettime(CLOCK_REALTIME,&now)))
      ERROR(terror,"clock_gettime failed");
//  }
//  else {
//    now = *time;
//  }

  res[res_index].s = s;
  res[res_index].t = now;

  //  printf("(%2d)", res_index+1);
  //  printf("%-60s", s);
  //  printf(" %2d %9d\n", now.tv_sec,now.tv_nsec);

  if (res_index < FSF_MAX_N_TIME_VALUES) res_index++;
 
  return 0;
} /* End of put_time */


int
print_time_results()
{
  struct timespec now = {0,0};
  struct timespec diff = {0,0};
  char            *s = NULL;
  int i;

  fsf_printf("\n");
  for (i=0;i<res_index;i++)
  {
    now  = res[i].t;
    s    = res[i].s;
    if (s==NULL) s = "  - timestamp - ";
    diff = now;
    decr_timespec(&diff, &last_time);
    last_time = now;
    fsf_printf("(%2d)", i+1);
    fsf_printf("%-60s", s);
    fsf_printf(" %2d %9d", now.tv_sec,now.tv_nsec);
    fsf_printf(" [diff=%13.9f]\n", (double)diff.tv_sec+((double)diff.tv_nsec/(double)1000000000));
  }

  return 0;
} /* End of print_time_results */



int
fsf_priority_map (unsigned long plevel)
{
  return plevel;
}


void * fsf_bounded_server_B (void * arg)
{
  //fsf_server_id_t       in = *((fsf_server_id_t *)arg);
  int                   terror=0;

  //fsf_server_id_t     server;

  //struct timespec  next_activation_time = in.offset;
  struct timespec  next_budget;
  struct timespec  next_period;
  bool             was_deadline_missed = 0;
  bool             was_budget_overran = 0;

  //executes for 0.1 second

  put_time(NULL, "B start one tenth of second execution   ");
  eat(100000);
  put_time(NULL, "B complete one tenth of second execution");

  //wait for the the synchronization object SO1_handle to be signaled

  put_time(NULL, "B called first fsf_schedule_triggered_job     ");

  if ((terror=fsf_schedule_triggered_job (
                                       SO1_handle,
                                       &next_budget,
                                       &next_period,
                                       &was_deadline_missed,
                                       &was_budget_overran)))
  {
     ERROR(terror,"fsf_bounded_server: first call to fsf_schedule_triggered_job failed");
  }
  put_time(NULL, "B returned from first fsf_schedule_triggered_job");



  //executes for 1 second

  put_time(NULL, "B start 1 second execution   ");
  eat(1000000);
  put_time(NULL, "B complete the 1 second execution");

  //wait for the the synchronization object SO1_handle to be signaled again
  put_time(NULL, "B called fsf_schedule_triggered_job");
  terror=fsf_schedule_triggered_job (
                                       SO1_handle,
                                       &next_budget,
                                       &next_period,
                                       &was_deadline_missed,
                                       &was_budget_overran);
  put_time(NULL, "B returned from fsf_schedule_triggered_job");
  if (terror)
  {
     ERROR(terror,"fsf_bounded_server: second call to fsf_schedule_triggered_job failed");
  }


  //end
  put_time(NULL, "B ends");

  return 0;

} /* End of fsf_bounded_server_B */



int main()
{
   struct sched_param   param;
   struct timespec      half_second= {0,500000000};
   struct timespec      tmp = {0,0};
   int                  terror = 0;

  fsf_contract_parameters_t  contract;
  struct timespec    budget_min = {7,0};
  struct timespec    period_max = {20,0};
  struct timespec    budget_max = {7,0};
  struct timespec    period_min = {20,0};
  fsf_workload_t     workload = FSF_INDETERMINATE;

  bool               d_equals_t = false;
  struct timespec    deadline = {19,900000000};
  int                budget_overrun_sig_notify = FSF_NULL_SIGNAL;   // 0
  union sigval       budget_overrun_sig_value = {0};
  int                deadline_miss_sig_notify = FSF_NULL_SIGNAL;    // 0
  union sigval       deadline_miss_sig_value = {0};

  fsf_granularity_t      granularity = FSF_DEFAULT_GRANULARITY;       // CONTINUOUS
  fsf_utilization_set_t *utilization_set = FSF_NULL_UTILIZATION_SET;  // NULL
  int                    quality = 1;
  int                    importance = FSF_DEFAULT_IMPORTANCE;         // 1

  fsf_preemption_level_t   preemption_level;
  fsf_critical_sections_t *critical_sections = NULL;

  pthread_t                task_in_b;

  INITIALIZATION_CODE
  SERIAL_CONSOLE_INIT;
 
  param.sched_priority = main_priority;
  if ((terror=pthread_setschedparam(pthread_self(), SCHED_FIFO, &param)))
    ERROR(terror,"pthread_setschedparam");

  instant_zero.tv_sec = 10000000;
  instant_zero.tv_nsec = 10000000;
  clock_settime(CLOCK_REALTIME,&instant_zero);
  clock_gettime(CLOCK_REALTIME,&instant_zero);
  last_time = instant_zero;
  put_time(&instant_zero, "instant_zero");
  put_time(NULL, "printing point 1");
  put_time(NULL, "printing point 2");
 
 

  if ((terror=fsf_initialize_contract(&contract)))
  {
     fsf_printf(" Initialize fail for server A\n");
     ERROR(terror,"fsf_initialize_contract failed");
  }

  if ((terror=fsf_set_contract_basic_parameters (&contract,
                                    &budget_min,
                                    &period_max,                                  
                                    workload)))
  {
     fsf_printf("Set_Basic_Parameters failed for server A\n");
     ERROR(terror,"set_contract_basic_parameters failed");
  }

  if ((terror=fsf_set_contract_timing_requirements (&contract,
                                      d_equals_t,
                                      (d_equals_t?NULL:&deadline),
                                      budget_overrun_sig_notify,
                                      budget_overrun_sig_value,
                                      deadline_miss_sig_notify,
                                      deadline_miss_sig_value)))
  {
     fsf_printf("Set_Timing_Requirements failed for server A\n");
     ERROR(terror,"fsf_set_contract_timing_requirements failed");
  }

  if ((terror=fsf_set_contract_reclamation_parameters (&contract,
                                                       &budget_max,
                                                       &period_min,
                                                       granularity,
                                                       utilization_set,
                                                       quality,
                                                       importance)))
  {
     fsf_printf("Set_Reclamation_Parameters failed for server A\n");
     ERROR(terror,"fsf_set_contract_reclamation_parameters failed");
  }

  preemption_level = (fsf_preemption_level_t) param.sched_priority;
  if ((terror=fsf_set_contract_synchronization_parameters (&contract,                                            
                                              critical_sections)))
  {
     fsf_printf("Set_Synchronization_Parameters failed for server A\n");
     ERROR(terror,"fsf_set_contract_synchronization_parameters failed");
  }


  put_time(NULL, "A start first server contract negotiation");
  terror = fsf_negotiate_contract_for_myself (&contract, &server_A);
  put_time(NULL, "A end first server contract negotiation");
  if (terror)
  {
    fsf_printf("Negotiate_Contract failed for server A\n");
    ERROR(terror,"fsf_negotiate_contract_for_myself failed");
  }

  //creation of the synchronization object
  put_time(NULL, "A start creating synchronization object");
  terror=fsf_create_synch_obj(&SO1_handle);
  put_time(NULL, "A end creating synchronization object");
  if (terror)
  {
     ERROR(terror,"fsf_signal_synchobject failed");    
  }


  //preparation of server B
  workload = FSF_BOUNDED;
  d_equals_t = true;
  //deadline.tv_sec = deadline.tv_nsec = 0;

  if ((terror=fsf_set_contract_basic_parameters (&contract,
                                    &budget_min,
                                    &period_max,                                
                                    workload)))
  {
     fsf_printf("Set_Basic_Parameters failed for server B\n");
     ERROR(terror,"set_contract_basic_parameters failed");
  }

  if ((terror=fsf_set_contract_timing_requirements (&contract,
                                      d_equals_t,
                                      (d_equals_t?NULL:&deadline),
                                      budget_overrun_sig_notify,
                                      budget_overrun_sig_value,
                                      deadline_miss_sig_notify,
                                      deadline_miss_sig_value)))
  {
     fsf_printf("Set_Timing_Requirements failed for server B\n");
     ERROR(terror,"fsf_set_contract_timing_requirements failed");
  }

  preemption_level--;
  if ((terror=fsf_set_contract_synchronization_parameters (&contract,                                            
                                              critical_sections)))
  {
     fsf_printf("Set_Synchronization_Parameters failed for server B\n");
     ERROR(terror,"fsf_set_contract_synchronization_parameters failed");
  }

  put_time(NULL, "A starts server B contract negotiation");
  terror=fsf_negotiate_contract_for_new_thread (&contract, &server_B, &task_in_b, NULL, fsf_bounded_server_B, NULL);
  put_time(NULL, "A ends server B contract negotiation");
  if (terror)
  {
     fsf_printf("Negotiate_Contract failed for server B\n");
     ERROR(terror,"fsf_negotiate_contract_for_new_thread failed");
  }

  if(!server_B) ERROR((-1), "Contract B not accepted");
 
  put_time(NULL, "A starts a half second nanosleep");
  if ((terror=nanosleep(&half_second,NULL)))
  ERROR(terror, "nanosleep 1 failed");
  put_time(NULL, "A completes the half second nanosleep");
 
  put_time(NULL, "A starts post-signaling synchronization object");
  terror=fsf_signal_synch_obj(SO1_handle);
  put_time(NULL, "A ends post-signaling synchronization object");
  if (terror)
  {
     ERROR(terror,"fsf_signal_synchobject failed");
  }
 
  half_second.tv_sec = 3;
  half_second.tv_nsec = 0;
  put_time(NULL, "A starts another 3s nanosleep");
  if ((terror=nanosleep(&half_second,NULL)))
    ERROR(terror, "nanosleep 2 failed");
  put_time(NULL, "A completes the other half second nanosleep");
 
  put_time(NULL, "A starts pre-signaling synchronization object");
  terror=fsf_signal_synch_obj(SO1_handle);
  put_time(NULL, "A ends pre-signaling synchronization object");
  if (terror)
  {
     ERROR(terror,"fsf_signal_synchobject failed");
  }
 
  tmp.tv_sec = 2;
  tmp.tv_nsec = 0;
  put_time(NULL, "A starts a final 2 seconds nanosleep");
  if ((terror=nanosleep(&tmp,NULL)))
    ERROR(terror, "third nanosleep failed");
  put_time(NULL, "A ends the final 2 seconds nanosleep");
 
  put_time(NULL, "A starts destroying synchronization object");
  terror=fsf_destroy_synch_obj(SO1_handle);
  put_time(NULL, "A ends destroying synchronization object");
  if (terror)
  {
     ERROR(terror,"fsf_destroy_synchobject failed");
  }

  print_time_results();
 
  STANDARD_CONSOLE_INIT; //marte1.26i+

  //print_time_results();

  fsf_printf("\nThe End.\n");

  //stop_scheduler = 1;

  exit(0);
  return 0;
} /* End of main */