]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_marte/tests/test_non_local_jump/testbench_long_jump.c
302ea8fa82884e1657126301823df13493e0e5e2
[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 100
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     int iteration_min_jump_interval;
47     double max_jump_interval_ms;
48     int iteration_max_jump_interval;
49     double total_jump_interval_ms;
50     int  number_of_jumps;
51 } results_t;
52
53 /*************************/
54 /*  P R O T O T Y P E S  */
55 /*************************/
56 static void *periodic_code(void *thread_arg);
57
58 /**********************************/
59 /* S T A T I C  V A R I A B L E S */
60 /**********************************/
61 static fosa_long_jump_context_t context;
62 static void work_under_a_interruptible_budget();
63
64 struct timespec before_jump_timestamp = {-1, -1};
65
66
67 int main()
68 {
69     int terror = -1;
70     frsh_thread_attr_t periodic_attr;
71     frsh_signal_t signal_set[1];
72     frsh_thread_id_t periodic_tid;
73     results_t results;
74
75     memset(&context, 0, sizeof(context) );
76
77     memset(&periodic_attr, 0, sizeof(periodic_attr) );
78     memset(&signal_set, 0, sizeof(signal_set) );
79     memset(&periodic_tid, 0, sizeof(periodic_tid) );
80     memset(&results, 0, sizeof(results) );
81
82     /* We set the signal mask */
83     signal_set[0] = FOSA_LONG_JUMP_SIGNAL;
84     PRW(  fosa_set_accepted_signals(signal_set, 1) );
85
86     /* We create a new thread with a given priority */
87     PRW(  fosa_thread_set_prio(fosa_thread_self(), MAIN_THREAD_PRIORITY) );
88
89     PRW(  frsh_thread_attr_init(&periodic_attr) );
90     PRW(  fosa_thread_attr_set_prio(&periodic_attr, PERIODIC_THREAD_PRIORITY)  );
91     PRW(  fosa_thread_create(&periodic_tid, &periodic_attr, periodic_code, &results) );
92
93     printf("Main waits for the periodic code to finish...\n");
94     pthread_join(periodic_tid, NULL);
95     
96     results.average_jump_interval_ms = results.total_jump_interval_ms/results.number_of_jumps;
97
98     printf("------------  RESULTS -------------\n");
99     printf("First Time:  %6.3f ms\n  Max Time: %6.3f ms   Iteration %d  Min Time: %6.3f ms Iteration %d\n",
100            results.first_jump_interval_ms, results.max_jump_interval_ms, results.iteration_max_jump_interval,
101            results.min_jump_interval_ms, results.iteration_min_jump_interval);
102     printf("Average_time: %6.3f ms   Total jumps: %d\n", results.average_jump_interval_ms, results.number_of_jumps);
103
104     printf("End of test\n");
105     return 0;
106 }
107
108 // ------------------------------------------------------------------------
109
110
111 static void *periodic_code(void *thread_arg)
112 {
113     int terror = -1;
114
115     struct timespec period = {2, 500000000};  // 2.5 secs
116     frsh_thread_id_t jump_handler_thread;
117
118     frsh_signal_t jump_signal;
119     frsh_signal_info_t jump_signal_info;
120
121     fosa_clock_id_t clock_id;
122     fosa_timer_id_t jump_timer;
123
124     /* testbench data */
125     results_t *results;
126     int first_time = 1;
127
128
129     memset(&jump_signal, 0, sizeof(jump_signal) );
130     memset(&jump_signal_info, 0, sizeof(jump_signal_info) );
131     memset(&jump_handler_thread, 0, sizeof(jump_handler_thread) );
132     memset(&clock_id, 0, sizeof(clock_id) );
133     memset(&jump_timer, 0, sizeof(jump_timer) );
134
135     results = (results_t *) thread_arg;
136     
137     /* We install a long jump handler               */
138     /* - This creates the thread that will wait for */
139     /*   FOSA_JUMP_SIGNAL                           */
140     /************************************************/
141     PXW(  fosa_long_jump_install_handler(&jump_signal, &jump_handler_thread) );
142     
143     /* We create a budget timer using the thread's CPU clock */
144     /*                                                       */
145     /* When the timer expires:                               */
146     /* -  Triggers the signal corresponding to signal jump   */
147     /* -  Provides a pointer to the context in siginfo.      */
148     /*                                                       */
149     /* This signal is delivered to the handler thread.       */
150     /*********************************************************/
151     PXW(  fosa_thread_get_cputime_clock( fosa_thread_self(), &clock_id) );
152     jump_signal_info.sival_ptr = &context;
153     PXW(  fosa_timer_create_with_receiver(clock_id, jump_signal, jump_signal_info, 
154                                           &jump_timer, jump_handler_thread)  );
155
156     results->number_of_jumps = 0;
157
158     /* Periodic loop */
159     /*****************/
160     while (results->number_of_jumps < NUMBER_OF_JUMPS)
161     {
162         int jumped = -1;
163         struct timespec budget = {0, 20000000};  // 20 ms
164
165         struct timespec after_jump_timestamp = {-1, -1 };
166         double jump_interval_ms = 0.0;
167
168         
169
170         /* We initialise variables */
171         jumped = 0;
172         memset(&before_jump_timestamp, 0, sizeof(before_jump_timestamp) );
173
174
175         /* Start of the interruptible block */
176         /************************************/
177
178         /* We arm the jump_timer */
179         fosa_timer_arm(jump_timer, false, &budget);
180
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
206                 results->max_jump_interval_ms = jump_interval_ms;
207                 results->iteration_max_jump_interval = results->number_of_jumps;
208
209                 results->min_jump_interval_ms = jump_interval_ms;
210                 results->iteration_min_jump_interval = results->number_of_jumps;
211
212                 first_time = 0;
213             }
214             results->total_jump_interval_ms += jump_interval_ms;
215
216             if (jump_interval_ms > results->max_jump_interval_ms)
217             {
218                 results->max_jump_interval_ms = jump_interval_ms;
219                 results->iteration_max_jump_interval = results->number_of_jumps;
220             }
221
222             if (jump_interval_ms < results->min_jump_interval_ms)
223             {
224                 results->min_jump_interval_ms = jump_interval_ms;
225                 results->iteration_min_jump_interval = results->number_of_jumps;
226             }
227        
228             printf("Jump Iteration: %d\r", results->number_of_jumps);
229         }
230
231         /* End of interruptible work */
232         /*****************************/
233     }
234
235     
236         
237     return NULL;
238 }
239
240
241 // ------------------------------------------------------------------------------
242
243 static void work_under_a_interruptible_budget()
244 {
245     /* This must be measured */
246     while(1)
247     {
248         fosa_clock_get_time(FOSA_CLOCK_REALTIME, &before_jump_timestamp);
249     }
250
251 }