1 // -----------------------------------------------------------------------
2 // Copyright (C) 2006 - 2009 FRESCOR consortium partners:
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
11 // Thales Communication S.A. FRANCE
12 // Visual Tools S.A. SPAIN
13 // Rapita Systems Ltd UK
16 // See http://www.frescor.org for a link to partners' websites
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
24 // based on previous work (FSF) done in the FIRST project
26 // Copyright (C) 2005 Mälardalen University, SWEDEN
27 // Scuola Superiore S.Anna, ITALY
28 // Universidad de Cantabria, SPAIN
29 // University of York, UK
31 // FSF API web pages: http://marte.unican.es/fsf/docs
32 // http://shark.sssup.it/contrib/first/docs/
34 // This file is part of FOSA (Frsh Operating System Adaption)
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.
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 // -----------------------------------------------------------------------
60 #include <time.h> // For clock_nanosleep
64 #include <misc/error_checks.h>
68 /*************************/
69 /* D E F I N I T I O N S */
70 /*************************/
71 #define PERIODIC_THREAD_PRIORITY (fosa_get_priority_min() + 3)
72 #define MAIN_THREAD_PRIORITY (fosa_get_priority_min() + 5)
75 /*************************/
76 /* P R O T O T Y P E S */
77 /*************************/
78 static void *periodic_code(void *thread_arg);
80 /**********************************/
81 /* S T A T I C V A R I A B L E S */
82 /**********************************/
83 static fosa_long_jump_context_t context;
84 static void work_under_an_interruptible_budget();
89 fosa_thread_attr_t periodic_attr;
90 fosa_signal_t signal_set[1];
91 fosa_thread_id_t periodic_tid;
95 printf("This test checks the ability to make long jumps in FOSA\n");
96 printf("A periodic workload consumes 1ms or 7ms (every 5 iterations)\n");
97 printf("The budget is set to 1.4ms; when exceeded, the operation is aborted\n");
100 memset(&context, 0, sizeof(context) );
102 memset(&periodic_attr, 0, sizeof(periodic_attr) );
103 memset(&signal_set, 0, sizeof(signal_set) );
104 memset(&periodic_tid, 0, sizeof(periodic_tid) );
107 /* We set the signal mask */
108 signal_set[0] = FOSA_LONG_JUMP_SIGNAL;
110 CHK( fosa_set_accepted_signals(signal_set, 1) );
112 /* We create a new thread with a given priority */
113 CHK( fosa_thread_attr_init(&periodic_attr) );
114 CHK( fosa_thread_attr_set_prio
115 (&periodic_attr, PERIODIC_THREAD_PRIORITY) );
116 CHK( fosa_thread_create
117 (&periodic_tid, &periodic_attr, periodic_code, NULL) );
119 printf("Main goes to sleep...\n");
126 // ------------------------------------------------------------------------
129 static void *periodic_code(void *thread_arg)
131 fosa_rel_time_t period = fosa_msec_to_rel_time(2500);
133 fosa_thread_id_t jump_handler_thread;
135 fosa_signal_t jump_signal;
136 fosa_signal_info_t jump_signal_info;
138 fosa_clock_id_t clock_id;
139 fosa_timer_id_t jump_timer;
141 memset(&jump_signal, 0, sizeof(jump_signal) );
142 memset(&jump_signal_info, 0, sizeof(jump_signal_info) );
143 memset(&jump_handler_thread, 0, sizeof(jump_handler_thread) );
144 memset(&clock_id, 0, sizeof(clock_id) );
145 memset(&jump_timer, 0, sizeof(jump_timer) );
148 /* We install a long jump handler */
149 /* - This creates the thread that will wait for */
150 /* FOSA_JUMP_SIGNAL */
151 /************************************************/
152 CHK( fosa_long_jump_install_handler(&jump_signal, &jump_handler_thread) );
154 /* We create a budget timer using the thread's CPU clock */
156 /* When the timer expires: */
157 /* - Triggers the signal corresponding to signal jump */
158 /* - Provides a pointer to the context in siginfo. */
160 /* This signal is delivered to the handler thread. */
161 /*********************************************************/
162 CHK( fosa_thread_get_cputime_clock( fosa_thread_self(), &clock_id) );
163 jump_signal_info.sival_ptr = &context;
164 CHK( fosa_timer_create_with_receiver
165 (clock_id, jump_signal, jump_signal_info,
166 &jump_timer, jump_handler_thread) );
169 printf("Start periodic work with budget=1400ms\n");
176 fosa_rel_time_t budget = fosa_msec_to_rel_time(1400);
177 fosa_abs_time_t activation_time;
178 struct timespec activation_time_tspec;
179 fosa_abs_time_t after_activation_time;
180 fosa_rel_time_t elapsed_time;
184 /* For statistical purposes we read the activation time */
185 CHK( fosa_clock_get_time(FOSA_CLOCK_REALTIME, &activation_time) );
189 /* Start of the interruptible block */
190 /************************************/
192 /* We arm the jump_timer */
193 CHK( fosa_rel_timer_arm(jump_timer, &budget) );
195 /* This is the point where the jump returns */
196 CHK( fosa_long_jump_save_context(&context) );
198 /* Query if we come from a jump */
199 CHK( fosa_long_jump_was_performed(&context, &jumped) );
202 /* HERE COMES THE WORK THAT CAN BE INTERRUPTED */
203 work_under_an_interruptible_budget();
204 CHK( fosa_timer_disarm(jump_timer, NULL) );
205 printf("NOT JUMPPED\n");
209 printf("JUMPPPPPEEED\n");
213 /* End of interruptible work */
214 /*****************************/
216 printf("After interruptible block\n");
218 /* Now we measure the time duration of the block */
219 /*************************************************/
220 CHK( fosa_clock_get_time(FOSA_CLOCK_REALTIME, &after_activation_time) );
221 elapsed_time = fosa_abs_time_extract_interval
222 (activation_time, after_activation_time);
223 printf("Execution time: %ld msec\n",
224 fosa_rel_time_to_msec(elapsed_time) );
226 /* And we program the next loop */
227 activation_time = fosa_abs_time_incr(activation_time, period);
228 activation_time_tspec = fosa_abs_time_to_timespec(activation_time);
229 clock_nanosleep(FOSA_CLOCK_REALTIME, TIMER_ABSTIME,
230 &activation_time_tspec,NULL);
237 // ------------------------------------------------------------------------------
239 static void work_under_an_interruptible_budget()
242 fosa_rel_time_t exec_time = fosa_msec_to_rel_time(1000); // 1 sec
245 printf("Start regular work (eat 1s)\n");
247 fosa_eat(&exec_time);
249 /* Once in every 5 executions we work over the budget */
252 printf("Eat additional time (6s more) \n");
253 fosa_eat(&exec_time);
254 fosa_eat(&exec_time);
255 fosa_eat(&exec_time);
256 fosa_eat(&exec_time);
257 fosa_eat(&exec_time);
258 fosa_eat(&exec_time);
261 printf("End regular work\n");