]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_marte/tests/test_non_local_jump/fosa_long_jump_calibrate.c
Correcting a bug when printing results in fosa_long_jump_calibrate
[frescor/fosa.git] / src_marte / tests / test_non_local_jump / fosa_long_jump_calibrate.c
1 /*
2 ** testbench_long_jump.c
3 ** 
4 ** Made by (Miguel marciano)
5 ** Login   <miguel@namir.ctr.unican.es>
6 ** 
7 ** Started on  Fri Nov 23 11:42:09 2007 Miguel marciano
8 ** Last update Sun May 12 01:17:25 2002 Speed Blue
9 */
10
11 /*
12   TO DO:
13
14   Objective:  To get the following overhead:
15
16   -  fixed_abort_ovhd:  install handler (only for worst case)
17                         save context
18                         jumped return
19                         fosa_long_jump_was_performed
20
21   -  fixed_memory_copy_ovhd:  Copying memory areas of 0 bytes
22   -  memory_copy_per_byte_ovhd:  Variable copying memory areas per byte.
23
24   NOTES:  I don't take the mutex
25
26 */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <time.h> // For clock_nanosleep
33
34 #include "frsh_error.h"
35 #include "fosa.h"
36 #include "frsh_fosa.h"
37 #include "timespec_operations.h"
38
39
40
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
46
47 #define CALIBRATE_THREAD_PRIORITY (fosa_get_priority_min() + 4)
48 #define MAIN_THREAD_PRIORITY (fosa_get_priority_min() + 3)
49
50
51
52 #define SIGNAL_CALIBRATE_FINISHED (FRSH_SIGNAL_MIN + 6)
53
54 typedef struct _individual_results_t
55 {
56     double first_interval_usec;
57     
58     /* The rest of min, max and average are taken over the REST of the
59        tests */
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;
66     int  number_of_tries;
67
68 } individual_results_t;
69
70 typedef struct _thread_data_t
71 {
72     individual_results_t *results;
73     frsh_thread_id_t parent_tid;
74 } thread_data_t;
75
76 typedef struct _measurements
77 {
78     individual_results_t fixed_abort_ovhd;
79     individual_results_t fixed_memory_copy_ovhd;
80     individual_results_t memory_copy_per_byte_ovhd;
81 } measurements_t;
82
83
84 /*************************/
85 /*  P R O T O T Y P E S  */
86 /*************************/
87 static void work_under_a_interruptible_budget();
88
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);
92
93
94 int main()
95 {
96     int terror = -1;
97     measurements_t measurements;
98     
99     memset(&measurements, 0, sizeof(measurements) );
100
101     /* We set the signal mask */
102
103     PRW(  frsh_sharedobj_calibrate(&measurements) );
104
105     /* Print info here */
106     printf("FIXED ABORT OVHD:\n");
107     print_results(measurements.fixed_abort_ovhd);
108
109     printf("End of test\n");
110     return 0;
111 }
112
113 // -----------------------------------------------------------------
114     
115 static int frsh_sharedobj_calibrate(measurements_t *measurements)
116 {
117     int terror = -1;
118
119     frsh_signal_t signal_set[1];
120     thread_data_t thread_data;
121
122     frsh_thread_attr_t calibrate_thread_attr;
123     frsh_thread_id_t calibrate_tid;
124
125     frsh_signal_t signal_received;
126     frsh_signal_info_t signal_info_received;
127     
128
129     memset(&signal_set, 0, sizeof(signal_set) );
130     memset(&thread_data, 0, sizeof(thread_data) );
131
132     memset(&calibrate_thread_attr, 0, sizeof(calibrate_thread_attr) );
133     memset(&calibrate_tid, 0, sizeof(calibrate_tid) );
134
135     memset(&signal_received, 0, sizeof(signal_received) );
136     memset(&signal_info_received, 0, sizeof(signal_info_received) );
137
138     
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)  );
144
145     /* We measure the fixed_abort_ovhd */
146     /***********************************/
147     thread_data.results = &measurements->fixed_abort_ovhd;
148     thread_data.parent_tid = pthread_self();
149
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, 
153                              &thread_data ) );
154
155     printf("Main waits for the calibrate code to finish...\n");
156     PRW(  fosa_signal_wait(signal_set, 1, &signal_received, &signal_info_received) );
157     
158     return 0;
159 }
160
161
162 // ------------------------------------------------------------------------
163
164 typedef struct _protection_parameters
165 {
166     bool initialised;
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;
173
174 // ------------------------------------------------------------------------
175
176 static void *calibrate_thread_code(void *thread_arg)
177 {
178     int terror = -1;
179
180     thread_data_t *thread_data = NULL;
181     individual_results_t *results = NULL;
182
183     bool first_time = false;
184     bool stats_initialised = false;
185     protection_parameters_t protection_parameters;
186
187     frsh_signal_info_t signal_info_to_send;
188
189     memset(&protection_parameters, 0, sizeof(protection_parameters) );
190     memset(&signal_info_to_send, 0, sizeof(signal_info_to_send) );
191     
192
193     thread_data = (thread_data_t *) thread_arg;
194     results = thread_data->results;
195     
196
197     /* Periodic loop */
198     /*****************/
199     first_time = true;
200     stats_initialised = false;  // For the second time onwards
201     protection_parameters.initialised = false;
202
203     results->number_of_tries = 0;
204     while (results->number_of_tries < NUMBER_OF_TESTS)
205     {
206         int jumped = -1;
207         struct timespec budget = {-1, -1};
208         static fosa_long_jump_context_t context;
209
210         struct timespec before_timestamp = {-1, -1 };
211         struct timespec after_timestamp = {-1, -1 };
212         double interval_usec = 0.0;
213
214         
215         /* We initialise variables */
216         jumped = 0;
217         memset(&before_timestamp, 0, sizeof(before_timestamp) );
218         memset(&after_timestamp, 0, sizeof(after_timestamp) );
219
220         budget.tv_sec = 0;
221         budget.tv_nsec = MINIMUM_BUDGET_FOR_TIMER_USECS * 1000;
222         
223
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);
227         
228
229         /* This is only executed once per thread */
230         if (protection_parameters.initialised == false)
231         {
232             PXW(  fosa_long_jump_install_handler(&protection_parameters.jump_signal, 
233                                            &protection_parameters.jump_handler_thread) );
234
235             PXW(  fosa_thread_get_cputime_clock( fosa_thread_self(), &protection_parameters.cpu_clock) );
236             protection_parameters.jump_signal_info.sival_ptr = &context;
237             
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)  );
243
244             protection_parameters.initialised = true;
245         }
246
247         /* We arm the jump_timer */
248         fosa_timer_arm(protection_parameters.jump_timer, false, &budget);
249         
250         /* This is the point where the jump returns */
251         fosa_long_jump_save_context(&context);
252
253         /* Query if we come from a jump */
254         fosa_long_jump_was_performed(&context, &jumped);
255         if (!jumped)
256         {
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");
260         }
261
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);
265
266         results->number_of_tries++;
267         decr_timespec(&after_timestamp, &before_timestamp);
268         interval_usec = t2d(after_timestamp) * 1000000;
269
270         /* We remove the 20 ms that we made it wait for */
271         interval_usec -= MINIMUM_BUDGET_FOR_TIMER_USECS;
272
273         if (first_time)
274         {
275             results->first_interval_usec = interval_usec;
276             first_time = false;
277         }
278         else
279         {
280             if (stats_initialised == false)
281             {
282                 results->max_interval_usec = interval_usec;
283                 results->iteration_max_interval = results->number_of_tries;
284             
285                 results->min_interval_usec = interval_usec;
286                 results->iteration_min_interval = results->number_of_tries;
287             
288                 stats_initialised = true;
289             }
290         
291             results->total_interval_usec += interval_usec;
292
293             if (interval_usec > results->max_interval_usec)
294             {
295                 results->max_interval_usec = interval_usec;
296                 results->iteration_max_interval = results->number_of_tries;
297             }
298             
299             if (interval_usec < results->min_interval_usec)
300             {
301                 results->min_interval_usec = interval_usec;
302                 results->iteration_min_interval = results->number_of_tries;
303             }
304         }
305     }
306
307     results->average_interval_usec = results->total_interval_usec / (results->number_of_tries - 1);
308
309     PXW(  fosa_signal_queue(SIGNAL_CALIBRATE_FINISHED, signal_info_to_send, thread_data->parent_tid) );
310
311     return NULL;
312 }
313
314
315 // ------------------------------------------------------------------------------
316
317 static void work_under_a_interruptible_budget()
318 {
319     struct timespec upper_execution_limit = {1, 0};
320
321     frsh_eat(&upper_execution_limit);
322 }
323
324 // ------------------------------------------------------------------------------
325
326 static void print_results(individual_results_t results)
327 {
328     
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);
334
335     printf("AVERAGE interval time:  %6.3f usecs, Number of tries: %d\n",
336            results.average_interval_usec, results.number_of_tries);
337 }