#include <stdlib.h>
#include <unistd.h>
#include <time.h> // For clock_nanosleep
+#include <limits.h>
+
+#include <assert.h>
#include "frsh_error.h"
#include "fosa.h"
/* D E F I N I T I O N S */
/*************************/
#define NUMBER_OF_TESTS 100
-#define MINIMUM_BUDGET_FOR_TIMER_USECS 100
+
+static struct timespec minimum_budget_for_timer = {0, 100000}; // 100 us
+
+#define NUMBER_OF_BYTES_TO_SIMULATE 10000 // Stack limit 40k in
+ // current MaRTE configuration
#define CALIBRATE_THREAD_PRIORITY (fosa_get_priority_min() + 4)
#define MAIN_THREAD_PRIORITY (fosa_get_priority_min() + 3)
-
+#define MINIMUM_BUDGET_FOR_TIMER_USECS 100
#define SIGNAL_CALIBRATE_FINISHED (FRSH_SIGNAL_MIN + 6)
typedef struct _individual_results_t
{
- double first_interval_usec;
+ int first_time_passed;
+ int second_time_passed;
+
+ struct timespec first_interval;
/* The rest of min, max and average are taken over the REST of the
tests */
- double average_interval_usec;
- double min_interval_usec;
+ struct timespec average_interval;
+ struct timespec min_interval;
int iteration_min_interval;
- double max_interval_usec;
+ struct timespec max_interval;
int iteration_max_interval;
- double total_interval_usec;
- int number_of_tries;
+ struct timespec total_interval;
+ long int number_of_tries;
} individual_results_t;
/*************************/
static void work_under_a_interruptible_budget();
-static int frsh_sharedobj_calibrate(measurements_t *measurements);
+static int frsh_sharedobj_calibrate(individual_results_t *fixed_abort_ovhd,
+ individual_results_t *fixed_memory_copy_ovhd,
+ individual_results_t *memory_copy_per_byte_ovhd);
+
+
static void *calibrate_thread_code(void *thread_arg);
+static void process_result(individual_results_t *results, struct timespec interval);
static void print_results(individual_results_t results);
+static struct timespec timespec_divide_by_int(struct timespec numerator, long int denominator);
+
+
+
+
int main()
{
/* We set the signal mask */
- PRW( frsh_sharedobj_calibrate(&measurements) );
+ PRW( frsh_sharedobj_calibrate(&measurements.fixed_abort_ovhd,
+ &measurements.fixed_memory_copy_ovhd,
+ &measurements.memory_copy_per_byte_ovhd) );
/* Print info here */
printf("FIXED ABORT OVHD:\n");
print_results(measurements.fixed_abort_ovhd);
+ printf("\n\nFIXED MEMORY COPY OVHD: \n");
+ print_results(measurements.fixed_memory_copy_ovhd);
+ printf("\n\nMEMORY COPY PER BYTE OVHD: \n");
+ print_results(measurements.memory_copy_per_byte_ovhd);
+
printf("End of test\n");
return 0;
// -----------------------------------------------------------------
-static int frsh_sharedobj_calibrate(measurements_t *measurements)
+static int frsh_sharedobj_calibrate(individual_results_t *fixed_abort_ovhd,
+ individual_results_t *fixed_memory_copy_ovhd,
+ individual_results_t *memory_copy_per_byte_ovhd)
{
int terror = -1;
frsh_signal_t signal_received;
frsh_signal_info_t signal_info_received;
-
+
+ fosa_clock_id_t cpu_clock;
+ struct timespec initial_time = {-1, -1};
+ struct timespec final_time = {-1, -1};
+
+ char memory_region_source[NUMBER_OF_BYTES_TO_SIMULATE];
+ char memory_region_destination[NUMBER_OF_BYTES_TO_SIMULATE];
+ int i = 0;
memset(&signal_set, 0, sizeof(signal_set) );
memset(&thread_data, 0, sizeof(thread_data) );
memset(&signal_received, 0, sizeof(signal_received) );
memset(&signal_info_received, 0, sizeof(signal_info_received) );
+ memset(&cpu_clock, 0, sizeof(cpu_clock) );
/* We set the signal mask and adjust our priority */
/* We measure the fixed_abort_ovhd */
/***********************************/
- thread_data.results = &measurements->fixed_abort_ovhd;
+ thread_data.results = fixed_abort_ovhd;
thread_data.parent_tid = pthread_self();
PRW( frsh_thread_attr_init(&calibrate_thread_attr) );
printf("Main waits for the calibrate code to finish...\n");
PRW( fosa_signal_wait(signal_set, 1, &signal_received, &signal_info_received) );
+
+ /* We measure fixed_memory_copy_ovhd */
+ /*************************************/
+ PRW( fosa_thread_get_cputime_clock( fosa_thread_self(), &cpu_clock) );
+
+
+ for(i = 0 ; i < NUMBER_OF_TESTS ; i++)
+ {
+ fosa_clock_get_time(FOSA_CLOCK_REALTIME, &initial_time);
+ memcpy(memory_region_destination, memory_region_source, 0);
+ fosa_clock_get_time(FOSA_CLOCK_REALTIME, &final_time);
+
+ decr_timespec(&final_time, &initial_time);
+
+ process_result(fixed_memory_copy_ovhd, final_time);
+ }
+
+ fixed_memory_copy_ovhd->average_interval =
+ timespec_divide_by_int(fixed_memory_copy_ovhd->total_interval,
+ fixed_memory_copy_ovhd->number_of_tries - 1);
+
+ /* We measure memory_copy_per_byte_ovhd */
+ /****************************************/
+ for(i = 0 ; i < NUMBER_OF_TESTS ; i++)
+ {
+ fosa_clock_get_time(cpu_clock, &initial_time); // Start measurement
+ memcpy(memory_region_destination, memory_region_source, NUMBER_OF_BYTES_TO_SIMULATE);
+ fosa_clock_get_time(cpu_clock, &final_time); // End measurement
+
+ decr_timespec(&final_time, &initial_time);
+ final_time = timespec_divide_by_int(final_time, NUMBER_OF_BYTES_TO_SIMULATE / 1024);
+
+ process_result(memory_copy_per_byte_ovhd, final_time);
+ }
+
+ memory_copy_per_byte_ovhd->average_interval =
+ timespec_divide_by_int(memory_copy_per_byte_ovhd->total_interval,
+ memory_copy_per_byte_ovhd->number_of_tries - 1);
+
return 0;
}
thread_data_t *thread_data = NULL;
individual_results_t *results = NULL;
- bool first_time = false;
- bool stats_initialised = false;
protection_parameters_t protection_parameters;
frsh_signal_info_t signal_info_to_send;
/* Periodic loop */
/*****************/
- first_time = true;
- stats_initialised = false; // For the second time onwards
protection_parameters.initialised = false;
results->number_of_tries = 0;
struct timespec before_timestamp = {-1, -1 };
struct timespec after_timestamp = {-1, -1 };
- double interval_usec = 0.0;
/* We initialise variables */
results->number_of_tries++;
decr_timespec(&after_timestamp, &before_timestamp);
- interval_usec = t2d(after_timestamp) * 1000000;
- /* We remove the 20 ms that we made it wait for */
- interval_usec -= MINIMUM_BUDGET_FOR_TIMER_USECS;
+ decr_timespec(&after_timestamp, &minimum_budget_for_timer);
- if (first_time)
- {
- results->first_interval_usec = interval_usec;
- first_time = false;
- }
- else
- {
- if (stats_initialised == false)
- {
- results->max_interval_usec = interval_usec;
- results->iteration_max_interval = results->number_of_tries;
-
- results->min_interval_usec = interval_usec;
- results->iteration_min_interval = results->number_of_tries;
-
- stats_initialised = true;
- }
-
- results->total_interval_usec += interval_usec;
+ process_result(results, after_timestamp);
- if (interval_usec > results->max_interval_usec)
- {
- results->max_interval_usec = interval_usec;
- results->iteration_max_interval = results->number_of_tries;
- }
-
- if (interval_usec < results->min_interval_usec)
- {
- results->min_interval_usec = interval_usec;
- results->iteration_min_interval = results->number_of_tries;
- }
- }
}
- results->average_interval_usec = results->total_interval_usec / (results->number_of_tries - 1);
-
+ results->average_interval = timespec_divide_by_int(results->total_interval, results->number_of_tries - 1);
+
PXW( fosa_signal_queue(SIGNAL_CALIBRATE_FINISHED, signal_info_to_send, thread_data->parent_tid) );
return NULL;
// ------------------------------------------------------------------------------
+static void process_result(individual_results_t *results, struct timespec interval)
+{
+ results->number_of_tries++;
+
+ if (results->first_time_passed == 0)
+ {
+ results->first_interval = interval;
+ results->first_time_passed = 1;
+ }
+ else if (results->second_time_passed == 0)
+ {
+ results->max_interval = interval;
+ results->iteration_max_interval = results->number_of_tries;
+
+ results->min_interval = interval;
+ results->iteration_min_interval = results->number_of_tries;
+
+ results->second_time_passed = 1;
+
+ incr_timespec(&results->total_interval, &interval);
+ }
+ else
+ {
+ if (smaller_timespec(&results->max_interval, &interval) )
+ {
+ results->max_interval = interval;
+ results->iteration_max_interval = results->number_of_tries;
+ }
+
+ if (smaller_timespec(&interval, &results->min_interval) )
+ {
+ results->min_interval = interval;
+ results->iteration_min_interval = results->number_of_tries;
+ }
+
+ incr_timespec(&results->total_interval, &interval);
+ }
+}
+
+// ------------------------------------------------------------------------------
+
static void print_results(individual_results_t results)
{
-
- printf("FIRST interval time: %6.3f usecs. All other stats apply to other invocations\n",
- results.first_interval_usec);
- printf("MAX interval time: %6.3f usecs at %d try, MIN interval time: %6.3f usecs at %d try\n",
- results.max_interval_usec, results.iteration_max_interval,
- results.min_interval_usec, results.iteration_min_interval);
-
- printf("AVERAGE interval time: %6.3f usecs, Number of tries: %d\n",
- results.average_interval_usec, results.number_of_tries);
+ assert(results.first_interval.tv_sec == 0);
+ assert(results.max_interval.tv_sec == 0);
+ assert(results.min_interval.tv_sec == 0);
+ assert(results.average_interval.tv_sec == 0);
+
+ printf("FIRST interval time: %d ns. All other stats apply to other invocations\n",
+ results.first_interval.tv_nsec);
+
+ printf("MAX interval time: %d ns at %d try, MIN interval time: %d ns at %d try\n",
+ results.max_interval.tv_nsec, results.iteration_max_interval,
+ results.min_interval.tv_nsec, results.iteration_min_interval);
+
+ printf("AVERAGE interval time: %d ns, Number of tries %ld\n",
+ results.average_interval.tv_nsec, results.number_of_tries);
+}
+
+
+// ------------------------------------------------------------------------------
+
+static struct timespec timespec_divide_by_int(struct timespec numerator, long int denominator)
+{
+ struct timespec result = {-1, -1};
+ long int reminder = -1;
+
+ assert(denominator < 1000000000); // For simplicity
+
+ result.tv_sec = numerator.tv_sec/denominator;
+
+ reminder = numerator.tv_sec % denominator;
+
+ result.tv_nsec = (reminder * 1000000000 + numerator.tv_nsec)/denominator;
+
+ return result;
}