2 ** testbench_long_jump.c
4 ** Made by (Miguel marciano)
5 ** Login <miguel@namir.ctr.unican.es>
7 ** Started on Fri Nov 23 11:42:09 2007 Miguel marciano
8 ** Last update Sun May 12 01:17:25 2002 Speed Blue
14 Objective: To get the following overhead:
16 - fixed_abort_ovhd: install handler (only for worst case)
19 fosa_long_jump_was_performed
21 - fixed_memory_copy_ovhd: Copying memory areas of 0 bytes
22 - memory_copy_per_byte_ovhd: Variable copying memory areas per byte.
24 NOTES: I don't take the mutex
32 #include <time.h> // For clock_nanosleep
34 #include "frsh_error.h"
36 #include "frsh_fosa.h"
37 #include "timespec_operations.h"
41 /*************************/
42 /* D E F I N I T I O N S */
43 /*************************/
44 #define NUMBER_OF_TESTS 100
45 #define MINIMUM_BUDGET_FOR_TIMER_USECS 100
47 #define CALIBRATE_THREAD_PRIORITY (fosa_get_priority_min() + 4)
48 #define MAIN_THREAD_PRIORITY (fosa_get_priority_min() + 3)
52 #define SIGNAL_CALIBRATE_FINISHED (FRSH_SIGNAL_MIN + 6)
54 typedef struct _individual_results_t
56 double first_interval_usec;
58 /* The rest of min, max and average are taken over the REST of the
60 double average_interval_usec;
61 double min_interval_usec;
62 int iteration_min_interval;
63 double max_interval_usec;
64 int iteration_max_interval;
65 double total_interval_usec;
68 } individual_results_t;
70 typedef struct _thread_data_t
72 individual_results_t *results;
73 frsh_thread_id_t parent_tid;
76 typedef struct _measurements
78 individual_results_t fixed_abort_ovhd;
79 individual_results_t fixed_memory_copy_ovhd;
80 individual_results_t memory_copy_per_byte_ovhd;
84 /*************************/
85 /* P R O T O T Y P E S */
86 /*************************/
87 static void work_under_a_interruptible_budget();
89 static int frsh_sharedobj_calibrate(measurements_t *measurements);
90 static void *calibrate_thread_code(void *thread_arg);
91 static void print_results(individual_results_t results);
97 measurements_t measurements;
99 memset(&measurements, 0, sizeof(measurements) );
101 /* We set the signal mask */
103 PRW( frsh_sharedobj_calibrate(&measurements) );
105 /* Print info here */
106 printf("FIXED ABORT OVHD:\n");
107 print_results(measurements.fixed_abort_ovhd);
109 printf("End of test\n");
113 // -----------------------------------------------------------------
115 static int frsh_sharedobj_calibrate(measurements_t *measurements)
119 frsh_signal_t signal_set[1];
120 thread_data_t thread_data;
122 frsh_thread_attr_t calibrate_thread_attr;
123 frsh_thread_id_t calibrate_tid;
125 frsh_signal_t signal_received;
126 frsh_signal_info_t signal_info_received;
129 memset(&signal_set, 0, sizeof(signal_set) );
130 memset(&thread_data, 0, sizeof(thread_data) );
132 memset(&calibrate_thread_attr, 0, sizeof(calibrate_thread_attr) );
133 memset(&calibrate_tid, 0, sizeof(calibrate_tid) );
135 memset(&signal_received, 0, sizeof(signal_received) );
136 memset(&signal_info_received, 0, sizeof(signal_info_received) );
139 /* We set the signal mask and adjust our priority */
140 /**************************************************/
141 signal_set[0] = SIGNAL_CALIBRATE_FINISHED;
142 PRW( fosa_set_accepted_signals(signal_set, 1) );
143 PRW( fosa_thread_set_prio(fosa_thread_self(), MAIN_THREAD_PRIORITY) );
145 /* We measure the fixed_abort_ovhd */
146 /***********************************/
147 thread_data.results = &measurements->fixed_abort_ovhd;
148 thread_data.parent_tid = pthread_self();
150 PRW( frsh_thread_attr_init(&calibrate_thread_attr) );
151 PRW( fosa_thread_attr_set_prio(&calibrate_thread_attr, CALIBRATE_THREAD_PRIORITY) );
152 PRW( fosa_thread_create(&calibrate_tid, &calibrate_thread_attr, calibrate_thread_code,
155 printf("Main waits for the calibrate code to finish...\n");
156 PRW( fosa_signal_wait(signal_set, 1, &signal_received, &signal_info_received) );
162 // ------------------------------------------------------------------------
164 typedef struct _protection_parameters
167 fosa_clock_id_t cpu_clock;
168 frsh_thread_id_t jump_handler_thread;
169 frsh_signal_t jump_signal;
170 frsh_signal_info_t jump_signal_info;
171 fosa_timer_id_t jump_timer;
172 } protection_parameters_t;
174 // ------------------------------------------------------------------------
176 static void *calibrate_thread_code(void *thread_arg)
180 thread_data_t *thread_data = NULL;
181 individual_results_t *results = NULL;
183 bool first_time = false;
184 bool stats_initialised = false;
185 protection_parameters_t protection_parameters;
187 frsh_signal_info_t signal_info_to_send;
189 memset(&protection_parameters, 0, sizeof(protection_parameters) );
190 memset(&signal_info_to_send, 0, sizeof(signal_info_to_send) );
193 thread_data = (thread_data_t *) thread_arg;
194 results = thread_data->results;
200 stats_initialised = false; // For the second time onwards
201 protection_parameters.initialised = false;
203 results->number_of_tries = 0;
204 while (results->number_of_tries < NUMBER_OF_TESTS)
207 struct timespec budget = {-1, -1};
208 static fosa_long_jump_context_t context;
210 struct timespec before_timestamp = {-1, -1 };
211 struct timespec after_timestamp = {-1, -1 };
212 double interval_usec = 0.0;
215 /* We initialise variables */
217 memset(&before_timestamp, 0, sizeof(before_timestamp) );
218 memset(&after_timestamp, 0, sizeof(after_timestamp) );
221 budget.tv_nsec = MINIMUM_BUDGET_FOR_TIMER_USECS * 1000;
224 /* S T A R T M E A S U R I N G H E R E */
225 /*********************************************/
226 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &before_timestamp);
229 /* This is only executed once per thread */
230 if (protection_parameters.initialised == false)
232 PXW( fosa_long_jump_install_handler(&protection_parameters.jump_signal,
233 &protection_parameters.jump_handler_thread) );
235 PXW( fosa_thread_get_cputime_clock( fosa_thread_self(), &protection_parameters.cpu_clock) );
236 protection_parameters.jump_signal_info.sival_ptr = &context;
238 PXW( fosa_timer_create_with_receiver(protection_parameters.cpu_clock,
239 protection_parameters.jump_signal,
240 protection_parameters.jump_signal_info,
241 &protection_parameters.jump_timer,
242 protection_parameters.jump_handler_thread) );
244 protection_parameters.initialised = true;
247 /* We arm the jump_timer */
248 fosa_timer_arm(protection_parameters.jump_timer, false, &budget);
250 /* This is the point where the jump returns */
251 fosa_long_jump_save_context(&context);
253 /* Query if we come from a jump */
254 fosa_long_jump_was_performed(&context, &jumped);
257 /* HERE COMES THE WORK THAT CAN BE INTERRUPTED */
258 work_under_a_interruptible_budget();
259 PERROR_AND_EXIT(FRSH_ERR_INTERNAL_ERROR, "The jump should always prevent us from arriving here\n");
262 /* E N D O F M E A S U R I N G H E R E */
263 /***************************************************/
264 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &after_timestamp);
266 results->number_of_tries++;
267 decr_timespec(&after_timestamp, &before_timestamp);
268 interval_usec = t2d(after_timestamp) * 1000000;
270 /* We remove the 20 ms that we made it wait for */
271 interval_usec -= MINIMUM_BUDGET_FOR_TIMER_USECS;
275 results->first_interval_usec = interval_usec;
280 if (stats_initialised == false)
282 results->max_interval_usec = interval_usec;
283 results->iteration_max_interval = results->number_of_tries;
285 results->min_interval_usec = interval_usec;
286 results->iteration_min_interval = results->number_of_tries;
288 stats_initialised = true;
291 results->total_interval_usec += interval_usec;
293 if (interval_usec > results->max_interval_usec)
295 results->max_interval_usec = interval_usec;
296 results->iteration_max_interval = results->number_of_tries;
299 if (interval_usec < results->min_interval_usec)
301 results->min_interval_usec = interval_usec;
302 results->iteration_min_interval = results->number_of_tries;
307 results->average_interval_usec = results->total_interval_usec / (results->number_of_tries - 1);
309 PXW( fosa_signal_queue(SIGNAL_CALIBRATE_FINISHED, signal_info_to_send, thread_data->parent_tid) );
315 // ------------------------------------------------------------------------------
317 static void work_under_a_interruptible_budget()
319 struct timespec upper_execution_limit = {1, 0};
321 frsh_eat(&upper_execution_limit);
324 // ------------------------------------------------------------------------------
326 static void print_results(individual_results_t results)
329 printf("FIRST interval time: %6.3f usecs. All other stats apply to other invocations\n",
330 results.first_interval_usec);
331 printf("MAX interval time: %6.3f usecs at %d try, MIN interval time: %6.3f usecs at %d try\n",
332 results.max_interval_usec, results.iteration_max_interval,
333 results.min_interval_usec, results.iteration_min_interval);
335 printf("AVERAGE interval time: %6.3f usecs, Number of tries: %d\n",
336 results.average_interval_usec, results.number_of_tries);