]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_marte/tests/test_non_local_jump/testbench_long_jump.c
First running version of FOSA long_jump testbench
[frescor/fosa.git] / src_marte / tests / test_non_local_jump / testbench_long_jump.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   -  Define a pthread_join equivalent in FOSA (and also the detachable
15      argument).
16   -  Define a clock_nanosleep equivalent in FOSA.
17
18 */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <time.h> // For clock_nanosleep
25
26 #include "frsh_error.h"
27 #include "fosa.h"
28 #include "frsh_fosa.h"
29 #include "timespec_operations.h"
30
31
32
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)
38
39 #define NUMBER_OF_JUMPS 5
40
41 typedef struct _results_t
42 {
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;
48     int  number_of_jumps;
49 } results_t;
50
51 /*************************/
52 /*  P R O T O T Y P E S  */
53 /*************************/
54 static void *periodic_code(void *thread_arg);
55
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();
61
62 struct timespec before_jump_timestamp = {-1, -1};
63
64
65 int main()
66 {
67     int terror = -1;
68     frsh_thread_attr_t periodic_attr;
69     frsh_signal_t signal_set[1];
70     frsh_thread_id_t periodic_tid;
71     results_t results;
72
73     memset(&context, 0, sizeof(context) );
74
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) );
79
80     /* We set the signal mask */
81     signal_set[0] = FOSA_LONG_JUMP_SIGNAL;
82     PRW(  fosa_set_accepted_signals(signal_set, 1) );
83
84     /* We create a new thread with a given priority */
85     PRW(  fosa_thread_set_prio(fosa_thread_self(), MAIN_THREAD_PRIORITY) );
86
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) );
90
91     printf("Main waits for the periodic code to finish...\n");
92     pthread_join(periodic_tid, NULL);
93     
94     results.average_jump_interval_ms = results.total_jump_interval_ms/results.number_of_jumps;
95
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);
100
101     printf("End of test\n");
102     return 0;
103 }
104
105 // ------------------------------------------------------------------------
106
107
108 static void *periodic_code(void *thread_arg)
109 {
110     int terror = -1;
111
112     struct timespec period = {2, 500000000};  // 2.5 secs
113     frsh_thread_id_t jump_handler_thread;
114
115     frsh_signal_t jump_signal;
116     frsh_signal_info_t jump_signal_info;
117
118     fosa_clock_id_t clock_id;
119     fosa_timer_id_t jump_timer;
120
121     /* testbench data */
122     results_t *results;
123     int first_time = 1;
124
125
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) );
131
132     results = (results_t *) thread_arg;
133     
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) );
139     
140     /* We create a budget timer using the thread's CPU clock */
141     /*                                                       */
142     /* When the timer expires:                               */
143     /* -  Triggers the signal corresponding to signal jump   */
144     /* -  Provides a pointer to the context in siginfo.      */
145     /*                                                       */
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)  );
152
153     results->number_of_jumps = 0;
154
155     /* Periodic loop */
156     /*****************/
157     while (results->number_of_jumps < NUMBER_OF_JUMPS)
158     {
159         int jumped = -1;
160         struct timespec budget = {1, 400000000};  // 1.4 secs
161
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;
166
167         
168
169         /* We initialise variables */
170         jumped = 0;
171         memset(&before_jump_timestamp, 0, sizeof(before_jump_timestamp) );
172
173         /* For statistical purposes we read the activation time */
174         fosa_clock_get_time(FOSA_CLOCK_REALTIME, &old_activation_timestamp);
175
176         /* Start of the interruptible block */
177         /************************************/
178
179         /* We arm the jump_timer */
180         fosa_timer_arm(jump_timer, false, &budget);
181
182         /* This is the point where the jump returns */
183         fosa_long_jump_save_context(&context);
184
185         /* Query if we come from a jump */
186         fosa_long_jump_was_performed(&context, &jumped);
187         if (!jumped)
188         {
189             /* HERE COMES THE WORK THAT CAN BE INTERRUPTED */
190             work_under_a_interruptible_budget();
191             printf("We should not arrive here \n");
192             exit(1);
193         }
194         else
195         {
196             fosa_clock_get_time(FOSA_CLOCK_REALTIME, &after_jump_timestamp);
197
198             results->number_of_jumps++;
199             decr_timespec(&after_jump_timestamp, &before_jump_timestamp);
200             jump_interval_ms = t2d(after_jump_timestamp) * 1000;
201
202             if (first_time)
203             {
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;
207
208                 first_time = 0;
209             }
210             results->total_jump_interval_ms += jump_interval_ms;
211
212             if (jump_interval_ms > results->max_jump_interval_ms)
213             {
214                 results->max_jump_interval_ms = jump_interval_ms;
215             }
216
217             if (jump_interval_ms < results->min_jump_interval_ms)
218             {
219                 results->min_jump_interval_ms = jump_interval_ms;
220             }
221        
222             printf("Jump Iteration: %d\n", results->number_of_jumps);
223         }
224
225         
226         /* End of interruptible work */
227         /*****************************/
228         printf("After interruptible block\n");
229         
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) );
235     
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);
240     }
241
242     
243         
244     return NULL;
245 }
246
247
248 // ------------------------------------------------------------------------------
249
250 static void work_under_a_interruptible_budget()
251 {
252     struct timespec exec_time = {1, 0};  // 1 seg
253
254     printf("Start regular work\n");
255
256     frsh_eat(&exec_time);
257
258     /* This must be measured */
259     while(1)
260     {
261         fosa_clock_get_time(FOSA_CLOCK_REALTIME, &before_jump_timestamp);
262     }
263
264 }