1 // -----------------------------------------------------------------------
2 // Copyright (C) 2006 - 2008 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 // -----------------------------------------------------------------------
59 This test verifies that the remaining budget of an execution-time
60 clock decreases in a monotonic way with execution time.
62 Some traces in a FRSH demo with Thales made us believe that
63 sometimes this does not happen.
65 The test consists in creating a monitored thread that execute very
66 small time slots and remain blocked for most of the time. In each
67 block-unblock period the cpu clock is read, the timer is disarmed
70 We verify that the remaining time obtained when disarming the
71 timer is equal or less than the time used to arm the timer
78 #include <time.h> // for nanosleep
81 #include <stdlib.h> // for exit in assert
82 #include <string.h> // for memset
85 #include <misc/error_checks.h>
86 #include <drivers/console_switcher.h>
88 /*****************************/
89 /* D E F I N I T I O N S */
90 /*****************************/
91 #define NUMBER_OF_TRIES 25
92 #define SLEEP_TIME_MSECS 5
93 #define ARMED_BUDGET_MSECS 2000
96 #define MUTEX_CEILING 5
97 #define MONITORED_THREAD_PRIO 5
99 #define TIMER_SIGNAL (FOSA_SIGNAL_MAX - 1)
102 typedef struct _thread_arg_t
104 fosa_cond_t *conditional_variable;
105 fosa_mutex_t *sync_mutex;
110 /***************************/
111 /* P R O T O T Y P E S */
112 /***************************/
113 static void *monitored_thread_body(void *arg);
118 SERIAL_CONSOLE_INIT();
121 fosa_thread_attr_t monitored_attr;
122 fosa_thread_id_t monitored_tid;
124 fosa_cond_t conditional_variable;
125 fosa_mutex_t sync_mutex;
128 fosa_clock_id_t monitored_clock;
129 fosa_timer_id_t monitored_timer;
131 fosa_signal_t signal_set[1];
132 fosa_signal_info_t signal_info_to_send;
134 fosa_rel_time_t remaining_time = fosa_msec_to_rel_time(ARMED_BUDGET_MSECS);
135 fosa_rel_time_t interval_to_sleep = fosa_msec_to_rel_time(SLEEP_TIME_MSECS);
139 thread_arg_t thread_arg;
141 /* Set the process-wide signal mask */
142 /************************************/
143 signal_set[0] = TIMER_SIGNAL;
144 CHK( fosa_set_accepted_signals(signal_set, 1) );
145 CHK( fosa_thread_set_prio(fosa_thread_self(), fosa_get_priority_min() + MAIN_PRIO) );
148 /* We initializa the condvar the mutex and */
149 /* set the predicate to false */
150 /*******************************************/
151 CHK( fosa_cond_init(&conditional_variable) );
152 CHK( fosa_mutex_init(&sync_mutex, fosa_get_priority_min() + MUTEX_CEILING) );
156 thread_arg.conditional_variable = &conditional_variable;
157 thread_arg.sync_mutex = &sync_mutex;
158 thread_arg.slave_can_run = &slave_can_run;
160 /* We create the monitored thread that will stop in the */
161 /* conditional variable wait. */
162 /********************************************************/
163 thread_arg.conditional_variable = &conditional_variable;
164 thread_arg.sync_mutex = &sync_mutex;
166 CHK( fosa_thread_attr_init(&monitored_attr) );
167 CHK( fosa_thread_attr_set_prio(&monitored_attr, fosa_get_priority_min() + MONITORED_THREAD_PRIO) );
169 CHK( fosa_thread_create(&monitored_tid, &monitored_attr, monitored_thread_body, &thread_arg) );
171 /* We create the CPU timer for the monitored thread */
172 /* and program it for a long expiration period. */
173 /****************************************************/
174 signal_info_to_send.sival_int = 42;
175 CHK( fosa_thread_get_cputime_clock(monitored_tid, &monitored_clock) );
176 CHK( fosa_timer_create(monitored_clock, TIMER_SIGNAL, signal_info_to_send, &monitored_timer) );
179 for (i = 0; i < NUMBER_OF_TRIES; i++)
181 long int msecs_armed_after_activation;
182 long int msecs_disarmed_after_blocking;
183 fosa_abs_time_t current_time;
184 fosa_abs_time_t awakening_time;
185 struct timespec awakening_time_tspec;
187 /* We first unblock the thread by signalling the condition var */
188 CHK( fosa_mutex_lock(&sync_mutex) );
189 assert(slave_can_run == 0);
191 CHK( fosa_cond_signal(&conditional_variable) );
192 CHK( fosa_mutex_unlock(&sync_mutex) );
194 printf("MAIN: Slave activation # %d\n", i);
195 /* Since we have the lock, we have a higher priority */
196 /* due to the priority ceiling of the mutex. */
197 /****************************************************/
200 msecs_armed_after_activation = fosa_rel_time_to_msec(remaining_time);
201 printf("MAIN: Timer armed with: %ld msec\n", msecs_armed_after_activation);
202 CHK( fosa_rel_timer_arm(monitored_timer, &remaining_time) );
205 // We let the thread execute something (short) and then block
207 CHK( fosa_clock_get_time(FOSA_CLOCK_REALTIME, ¤t_time) );
208 printf("MAIN: SLEEPING\n");
209 awakening_time = fosa_abs_time_incr(current_time, interval_to_sleep);
210 awakening_time_tspec = fosa_abs_time_to_timespec(awakening_time);
213 CHK( clock_nanosleep(FOSA_CLOCK_REALTIME, TIMER_ABSTIME, &awakening_time_tspec, NULL) );
216 // We disarm the timer and release the mutex
217 CHK( fosa_timer_disarm(monitored_timer, &remaining_time) );
218 msecs_disarmed_after_blocking = fosa_rel_time_to_msec(remaining_time);
220 printf("MAIN: Timer disarmed with %ld msec\n", msecs_disarmed_after_blocking);
222 if (msecs_disarmed_after_blocking > msecs_armed_after_activation)
224 printf("MAIN: BINGOO Bug reproduced!!!\n");
233 // -----------------------------------------------------------
235 static void *monitored_thread_body(void *arg)
237 thread_arg_t *thread_args = (thread_arg_t *) arg;
239 int nr_activation = 0;
243 printf("SLAVE about to block\n");
244 CHK( fosa_mutex_lock(thread_args->sync_mutex) );
246 while (!*(thread_args->slave_can_run))
248 CHK( fosa_cond_wait(thread_args->conditional_variable,
249 thread_args->sync_mutex) );
252 printf("This comes second\n");
254 printf("SLAVE: Activation nr: %d\n", nr_activation);
257 *(thread_args->slave_can_run) = 0;
258 CHK( fosa_mutex_unlock(thread_args->sync_mutex) );