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 - Define a pthread_join equivalent in FOSA (and also the detachable
16 - Define a clock_nanosleep equivalent in FOSA.
24 #include <time.h> // For clock_nanosleep
26 #include "frsh_error.h"
28 #include "frsh_fosa.h"
29 #include "timespec_operations.h"
33 /*************************/
34 /* D E F I N I T I O N S */
35 /*************************/
36 #define PERIODIC_THREAD_PRIORITY (fosa_get_priority_min() + 5)
37 #define MAIN_THREAD_PRIORITY (fosa_get_priority_min() + 3)
39 #define NUMBER_OF_JUMPS 5
41 typedef struct _results_t
43 double first_jump_interval_ms;
44 double average_jump_interval_ms;
45 double min_jump_interval_ms;
46 double max_jump_interval_ms;
47 double total_jump_interval_ms;
51 /*************************/
52 /* P R O T O T Y P E S */
53 /*************************/
54 static void *periodic_code(void *thread_arg);
56 /**********************************/
57 /* S T A T I C V A R I A B L E S */
58 /**********************************/
59 static fosa_long_jump_context_t context;
60 static void work_under_a_interruptible_budget();
62 struct timespec before_jump_timestamp = {-1, -1};
68 frsh_thread_attr_t periodic_attr;
69 frsh_signal_t signal_set[1];
70 frsh_thread_id_t periodic_tid;
73 memset(&context, 0, sizeof(context) );
75 memset(&periodic_attr, 0, sizeof(periodic_attr) );
76 memset(&signal_set, 0, sizeof(signal_set) );
77 memset(&periodic_tid, 0, sizeof(periodic_tid) );
78 memset(&results, 0, sizeof(results) );
80 /* We set the signal mask */
81 signal_set[0] = FOSA_LONG_JUMP_SIGNAL;
82 PRW( fosa_set_accepted_signals(signal_set, 1) );
84 /* We create a new thread with a given priority */
85 PRW( fosa_thread_set_prio(fosa_thread_self(), MAIN_THREAD_PRIORITY) );
87 PRW( frsh_thread_attr_init(&periodic_attr) );
88 PRW( fosa_thread_attr_set_prio(&periodic_attr, PERIODIC_THREAD_PRIORITY) );
89 PRW( fosa_thread_create(&periodic_tid, &periodic_attr, periodic_code, &results) );
91 printf("Main waits for the periodic code to finish...\n");
92 pthread_join(periodic_tid, NULL);
94 results.average_jump_interval_ms = results.total_jump_interval_ms/results.number_of_jumps;
96 printf("------------ RESULTS -------------\n");
97 printf("First Time: %6.3f ms Max Time: %6.3f ms Min Time: %6.3f ms\n",
98 results.first_jump_interval_ms, results.max_jump_interval_ms, results.min_jump_interval_ms);
99 printf("Average_time: %6.3f ms Total jumps: %d\n", results.average_jump_interval_ms, results.number_of_jumps);
101 printf("End of test\n");
105 // ------------------------------------------------------------------------
108 static void *periodic_code(void *thread_arg)
112 struct timespec period = {2, 500000000}; // 2.5 secs
113 frsh_thread_id_t jump_handler_thread;
115 frsh_signal_t jump_signal;
116 frsh_signal_info_t jump_signal_info;
118 fosa_clock_id_t clock_id;
119 fosa_timer_id_t jump_timer;
126 memset(&jump_signal, 0, sizeof(jump_signal) );
127 memset(&jump_signal_info, 0, sizeof(jump_signal_info) );
128 memset(&jump_handler_thread, 0, sizeof(jump_handler_thread) );
129 memset(&clock_id, 0, sizeof(clock_id) );
130 memset(&jump_timer, 0, sizeof(jump_timer) );
132 results = (results_t *) thread_arg;
134 /* We install a long jump handler */
135 /* - This creates the thread that will wait for */
136 /* FOSA_JUMP_SIGNAL */
137 /************************************************/
138 PXW( fosa_long_jump_install_handler(&jump_signal, &jump_handler_thread) );
140 /* We create a budget timer using the thread's CPU clock */
142 /* When the timer expires: */
143 /* - Triggers the signal corresponding to signal jump */
144 /* - Provides a pointer to the context in siginfo. */
146 /* This signal is delivered to the handler thread. */
147 /*********************************************************/
148 PXW( fosa_thread_get_cputime_clock( fosa_thread_self(), &clock_id) );
149 jump_signal_info.sival_ptr = &context;
150 PXW( fosa_timer_create_with_receiver(clock_id, jump_signal, jump_signal_info,
151 &jump_timer, jump_handler_thread) );
153 results->number_of_jumps = 0;
157 while (results->number_of_jumps < NUMBER_OF_JUMPS)
160 struct timespec budget = {1, 400000000}; // 1.4 secs
162 struct timespec old_activation_timestamp = {-1, -1};
163 struct timespec activation_timestamp = {-1, -1};
164 struct timespec after_jump_timestamp = {-1, -1 };
165 double jump_interval_ms = 0.0;
169 /* We initialise variables */
171 memset(&before_jump_timestamp, 0, sizeof(before_jump_timestamp) );
173 /* For statistical purposes we read the activation time */
174 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &old_activation_timestamp);
176 /* Start of the interruptible block */
177 /************************************/
179 /* We arm the jump_timer */
180 fosa_timer_arm(jump_timer, false, &budget);
182 /* This is the point where the jump returns */
183 fosa_long_jump_save_context(&context);
185 /* Query if we come from a jump */
186 fosa_long_jump_was_performed(&context, &jumped);
189 /* HERE COMES THE WORK THAT CAN BE INTERRUPTED */
190 work_under_a_interruptible_budget();
191 printf("We should not arrive here \n");
196 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &after_jump_timestamp);
198 results->number_of_jumps++;
199 decr_timespec(&after_jump_timestamp, &before_jump_timestamp);
200 jump_interval_ms = t2d(after_jump_timestamp) * 1000;
204 results->first_jump_interval_ms = jump_interval_ms;
205 results->max_jump_interval_ms = jump_interval_ms;
206 results->min_jump_interval_ms = jump_interval_ms;
210 results->total_jump_interval_ms += jump_interval_ms;
212 if (jump_interval_ms > results->max_jump_interval_ms)
214 results->max_jump_interval_ms = jump_interval_ms;
217 if (jump_interval_ms < results->min_jump_interval_ms)
219 results->min_jump_interval_ms = jump_interval_ms;
222 printf("Jump Iteration: %d\n", results->number_of_jumps);
226 /* End of interruptible work */
227 /*****************************/
228 printf("After interruptible block\n");
230 /* Now we measure the time duration of the block */
231 /*************************************************/
232 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &activation_timestamp);
233 decr_timespec(&activation_timestamp, &old_activation_timestamp);
234 printf("Execution time: %6.3f\n", t2d(activation_timestamp) );
236 /* And we program the next loop */
237 incr_timespec(&old_activation_timestamp, &period);
238 clock_nanosleep(FOSA_CLOCK_REALTIME, TIMER_ABSTIME, &activation_timestamp,
239 &old_activation_timestamp);
248 // ------------------------------------------------------------------------------
250 static void work_under_a_interruptible_budget()
252 struct timespec exec_time = {1, 0}; // 1 seg
254 printf("Start regular work\n");
256 frsh_eat(&exec_time);
258 /* This must be measured */
261 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &before_jump_timestamp);