]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_marte_os/tests/test_non_local_jump/testbench_long_jump.c
Makefile: Add missing header file
[frescor/fosa.git] / src_marte_os / tests / test_non_local_jump / testbench_long_jump.c
1 // -----------------------------------------------------------------------
2 //  Copyright (C) 2006 - 2009 FRESCOR consortium partners:
3 //
4 //    Universidad de Cantabria,              SPAIN
5 //    University of York,                    UK
6 //    Scuola Superiore Sant'Anna,            ITALY
7 //    Kaiserslautern University,             GERMANY
8 //    Univ. Politécnica  Valencia,           SPAIN
9 //    Czech Technical University in Prague,  CZECH REPUBLIC
10 //    ENEA                                   SWEDEN
11 //    Thales Communication S.A.              FRANCE
12 //    Visual Tools S.A.                      SPAIN
13 //    Rapita Systems Ltd                     UK
14 //    Evidence                               ITALY
15 //
16 //    See http://www.frescor.org for a link to partners' websites
17 //
18 //           FRESCOR project (FP6/2005/IST/5-034026) is funded
19 //        in part by the European Union Sixth Framework Programme
20 //        The European Union is not liable of any use that may be
21 //        made of this code.
22 //
23 //
24 //  based on previous work (FSF) done in the FIRST project
25 //
26 //   Copyright (C) 2005  Mälardalen University, SWEDEN
27 //                       Scuola Superiore S.Anna, ITALY
28 //                       Universidad de Cantabria, SPAIN
29 //                       University of York, UK
30 //
31 //   FSF API web pages: http://marte.unican.es/fsf/docs
32 //                      http://shark.sssup.it/contrib/first/docs/
33 //
34 //   This file is part of FOSA (Frsh Operating System Adaption)
35 //
36 //  FOSA is free software; you can redistribute it and/or modify it
37 //  under terms of the GNU General Public License as published by the
38 //  Free Software Foundation; either version 2, or (at your option) any
39 //  later version.  FOSA is distributed in the hope that it will be
40 //  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
41 //  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42 //  General Public License for more details. You should have received a
43 //  copy of the GNU General Public License along with FOSA; see file
44 //  COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
45 //  Cambridge, MA 02139, USA.
46 //
47 //  As a special exception, including FOSA header files in a file,
48 //  instantiating FOSA generics or templates, or linking other files
49 //  with FOSA objects to produce an executable application, does not
50 //  by itself cause the resulting executable application to be covered
51 //  by the GNU General Public License. This exception does not
52 //  however invalidate any other reasons why the executable file might be
53 //  covered by the GNU Public License.
54 // -----------------------------------------------------------------------
55
56 /*
57   TO DO:
58
59   -  Define a pthread_join equivalent in FOSA (and also the detachable
60      argument).
61   -  Define a clock_nanosleep equivalent in FOSA.
62
63 */
64
65 #include <stdio.h>
66 #include <string.h>
67 #include <stdlib.h>
68 #include <unistd.h>
69 #include <time.h> // For clock_nanosleep
70
71 #include "fosa.h"
72
73 #include <misc/error_checks.h>
74
75
76 /*************************/
77 /* D E F I N I T I O N S */
78 /*************************/
79 #define PERIODIC_THREAD_PRIORITY (fosa_get_priority_min() + 5)
80 #define MAIN_THREAD_PRIORITY (fosa_get_priority_min() + 3)
81
82 #define NUMBER_OF_JUMPS 100
83
84 typedef struct _results_t
85 {
86     double first_jump_interval_ms;
87     double average_jump_interval_ms;
88     double min_jump_interval_ms;
89     int iteration_min_jump_interval;
90     double max_jump_interval_ms;
91     int iteration_max_jump_interval;
92     double total_jump_interval_ms;
93     int  number_of_jumps;
94 } results_t;
95
96 /*************************/
97 /*  P R O T O T Y P E S  */
98 /*************************/
99 static void *periodic_code(void *thread_arg);
100
101 /**********************************/
102 /* S T A T I C  V A R I A B L E S */
103 /**********************************/
104 static fosa_long_jump_context_t context;
105 static void work_under_an_interruptible_budget();
106
107 fosa_abs_time_t before_jump_timestamp;
108
109
110 int main()
111 {
112     fosa_thread_attr_t periodic_attr;
113     fosa_signal_t signal_set[1];
114     fosa_thread_id_t periodic_tid;
115     results_t results;
116     
117     // Display a header text
118     printf("\n");
119     printf("This test measures the time of a long jump\n");
120     printf("It displays elapsed time for execution of an operation with a budget of 20ms\n");
121     printf("\n");
122
123     memset(&context, 0, sizeof(context) );
124
125
126     /* We set the signal mask */
127     signal_set[0] = FOSA_LONG_JUMP_SIGNAL;
128     CHK(  fosa_set_accepted_signals(signal_set, 1) );
129
130     /* We create a new thread with a given priority */
131     CHK(  fosa_thread_set_prio(fosa_thread_self(), MAIN_THREAD_PRIORITY) );
132
133     CHK(  fosa_thread_attr_init(&periodic_attr) );
134     CHK(  fosa_thread_attr_set_prio
135           (&periodic_attr, PERIODIC_THREAD_PRIORITY)  );
136     CHK(  fosa_thread_create
137           (&periodic_tid, &periodic_attr, periodic_code, &results) );
138
139     printf("Main waits for the periodic code to finish...\n");
140     pthread_join(periodic_tid, NULL);
141
142     results.average_jump_interval_ms = 
143       results.total_jump_interval_ms/results.number_of_jumps;
144
145     printf("------------  RESULTS -------------\n");
146     printf("First Time:  %6.3f ms\n  Max Time: %6.3f ms   Iteration %d  Min Time: %6.3f ms Iteration %d\n",
147            results.first_jump_interval_ms, results.max_jump_interval_ms, 
148            results.iteration_max_jump_interval,
149            results.min_jump_interval_ms, results.iteration_min_jump_interval);
150     printf("Average_time: %6.3f ms   Total jumps: %d\n", 
151            results.average_jump_interval_ms, results.number_of_jumps);
152
153     printf("End of test\n");
154     return 0;
155 }
156
157 // ------------------------------------------------------------------------
158
159
160 static void *periodic_code(void *thread_arg)
161 {
162     fosa_thread_id_t jump_handler_thread;
163
164     fosa_signal_t jump_signal;
165     fosa_signal_info_t jump_signal_info;
166
167     fosa_clock_id_t clock_id;
168     fosa_timer_id_t jump_timer;
169
170     /* testbench data */
171     results_t *results;
172     int first_time = 1;
173
174
175     results = (results_t *) thread_arg;
176
177     /* We install a long jump handler               */
178     /* - This creates the thread that will wait for */
179     /*   FOSA_JUMP_SIGNAL                           */
180     /************************************************/
181     CHK(  fosa_long_jump_install_handler(&jump_signal, &jump_handler_thread) );
182
183     /* We create a budget timer using the thread's CPU clock */
184     /*                                                       */
185     /* When the timer expires:                               */
186     /* -  Triggers the signal corresponding to signal jump   */
187     /* -  Provides a pointer to the context in siginfo.      */
188     /*                                                       */
189     /* This signal is delivered to the handler thread.       */
190     /*********************************************************/
191     CHK(  fosa_thread_get_cputime_clock( fosa_thread_self(), &clock_id) );
192     jump_signal_info.sival_ptr = &context;
193     CHK(  fosa_timer_create_with_receiver
194           (clock_id, jump_signal, jump_signal_info,
195            &jump_timer, jump_handler_thread)  );
196
197     results->number_of_jumps = 0;
198
199     /* Periodic loop */
200     /*****************/
201     while (results->number_of_jumps < NUMBER_OF_JUMPS)
202     {
203         int jumped = -1;
204         fosa_rel_time_t budget = fosa_msec_to_rel_time(20);  // 20 ms
205
206         fosa_abs_time_t after_jump_timestamp;
207         fosa_rel_time_t jump_interval;
208         double jump_interval_ms = 0.0;
209
210
211
212         /* We initialise variables */
213         jumped = 0;
214         memset(&before_jump_timestamp, 0, sizeof(before_jump_timestamp) );
215
216
217         /* Start of the interruptible block */
218         /************************************/
219
220         /* We arm the jump_timer */
221         fosa_rel_timer_arm(jump_timer, &budget);
222
223
224         /* This is the point where the jump returns */
225         fosa_long_jump_save_context(&context);
226
227         /* Query if we come from a jump */
228         fosa_long_jump_was_performed(&context, &jumped);
229         if (!jumped)
230         {
231             /* HERE COMES THE WORK THAT CAN BE INTERRUPTED */
232             work_under_an_interruptible_budget();
233             printf("We should not arrive here \n");
234             exit(1);
235         }
236         else
237         {
238             fosa_clock_get_time(FOSA_CLOCK_REALTIME, &after_jump_timestamp);
239
240             results->number_of_jumps++;
241             jump_interval = fosa_abs_time_extract_interval
242               (before_jump_timestamp, after_jump_timestamp);
243             jump_interval_ms = fosa_rel_time_to_double(jump_interval)*1.0e6;
244
245             if (first_time)
246             {
247                 results->first_jump_interval_ms = jump_interval_ms;
248
249                 results->max_jump_interval_ms = jump_interval_ms;
250                 results->iteration_max_jump_interval = results->number_of_jumps;
251
252                 results->min_jump_interval_ms = jump_interval_ms;
253                 results->iteration_min_jump_interval = results->number_of_jumps;
254
255                 first_time = 0;
256             }
257             results->total_jump_interval_ms += jump_interval_ms;
258
259             if (jump_interval_ms > results->max_jump_interval_ms)
260             {
261                 results->max_jump_interval_ms = jump_interval_ms;
262                 results->iteration_max_jump_interval = results->number_of_jumps;
263             }
264
265             if (jump_interval_ms < results->min_jump_interval_ms)
266             {
267                 results->min_jump_interval_ms = jump_interval_ms;
268                 results->iteration_min_jump_interval = results->number_of_jumps;
269             }
270
271             printf("Jump Iteration: %d\r", results->number_of_jumps);
272         }
273
274         /* End of interruptible work */
275         /*****************************/
276     }
277
278
279
280     return NULL;
281 }
282
283
284 // ----------------------------------------------------------------------------
285
286 static void work_under_an_interruptible_budget()
287 {
288     /* This must be measured */
289     while(1)
290     {
291         fosa_clock_get_time(FOSA_CLOCK_REALTIME, &before_jump_timestamp);
292     }
293
294 }