]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_marte_os/tests/test_monotonic_cpuclock_consumption/test_monotonic_cpuclock_consumption.c
Adding a FOSA test to find a bug manifested in Thales demo
[frescor/fosa.git] / src_marte_os / tests / test_monotonic_cpuclock_consumption / test_monotonic_cpuclock_consumption.c
1 // -----------------------------------------------------------------------
2 //  Copyright (C) 2006 - 2008 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     Idea of the test:
58
59     This test verifies that the remaining budget of an execution-time
60     clock decreases in a monotonic way with execution time.
61
62     Some traces in a FRSH demo with Thales made us believe that
63     sometimes this does not happen.
64
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
68     and armed again. 
69
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
72     initially.
73
74 */
75
76 #include <unistd.h>
77 #include <stdio.h>
78 #include <time.h> // for nanosleep
79
80 #include <assert.h>
81 #include <stdlib.h> // for exit in assert
82 #include <string.h> // for memset
83
84 #include "fosa.h"
85 #include <misc/error_checks.h>
86 #include <drivers/console_switcher.h>
87
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
94
95 #define MAIN_PRIO 5
96 #define MUTEX_CEILING 5
97 #define MONITORED_THREAD_PRIO 5
98
99 #define TIMER_SIGNAL (FOSA_SIGNAL_MAX - 1)
100
101
102 typedef struct _thread_arg_t
103 {
104     fosa_cond_t *conditional_variable;
105     fosa_mutex_t *sync_mutex;
106     int *slave_can_run;
107 } thread_arg_t;
108
109
110 /***************************/
111 /*   P R O T O T Y P E S   */
112 /***************************/
113 static void *monitored_thread_body(void *arg);
114
115
116 int main ()
117 {
118     SERIAL_CONSOLE_INIT();
119
120
121     fosa_thread_attr_t monitored_attr;
122     fosa_thread_id_t monitored_tid;
123
124     fosa_cond_t conditional_variable;
125     fosa_mutex_t sync_mutex;
126     int slave_can_run;
127
128     fosa_clock_id_t monitored_clock;
129     fosa_timer_id_t monitored_timer;
130
131     fosa_signal_t signal_set[1];
132     fosa_signal_info_t signal_info_to_send;
133
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);
136     int i;
137
138
139     thread_arg_t thread_arg;
140
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) );
146
147
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) );
153     slave_can_run = 0;
154
155     
156     thread_arg.conditional_variable = &conditional_variable;
157     thread_arg.sync_mutex = &sync_mutex;
158     thread_arg.slave_can_run = &slave_can_run;
159
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;
165    
166     CHK(  fosa_thread_attr_init(&monitored_attr) );
167     CHK(  fosa_thread_attr_set_prio(&monitored_attr, fosa_get_priority_min() + MONITORED_THREAD_PRIO) );
168     
169     CHK(  fosa_thread_create(&monitored_tid, &monitored_attr, monitored_thread_body, &thread_arg) );
170
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) );
177
178
179     for (i = 0; i < NUMBER_OF_TRIES; i++)
180     {
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;
186
187         /* We first unblock the thread by signalling the condition var */
188         CHK(  fosa_mutex_lock(&sync_mutex) );
189         assert(slave_can_run == 0);
190         slave_can_run = 1;
191         CHK(  fosa_cond_signal(&conditional_variable) );
192         CHK(  fosa_mutex_unlock(&sync_mutex) );
193
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         /****************************************************/
198
199         // We arm the timer
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) );
203
204         
205         // We let the thread execute something (short) and then block
206         // itself again
207         CHK(  fosa_clock_get_time(FOSA_CLOCK_REALTIME, &current_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);
211
212
213         CHK(  clock_nanosleep(FOSA_CLOCK_REALTIME, TIMER_ABSTIME, &awakening_time_tspec, NULL) );
214
215
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);
219
220         printf("MAIN:  Timer disarmed with %ld msec\n", msecs_disarmed_after_blocking);
221
222         if (msecs_disarmed_after_blocking > msecs_armed_after_activation)
223         {
224             printf("MAIN: BINGOO  Bug reproduced!!!\n");
225             exit(1);
226         }
227
228     }
229         
230     return 0;
231 }
232
233 // -----------------------------------------------------------
234
235 static void *monitored_thread_body(void *arg)
236 {
237     thread_arg_t *thread_args = (thread_arg_t *) arg;
238
239     int nr_activation = 0;
240
241     while(1)
242     {
243         printf("SLAVE about to block\n");
244         CHK(  fosa_mutex_lock(thread_args->sync_mutex) );
245
246         while (!*(thread_args->slave_can_run))
247         {
248             CHK(  fosa_cond_wait(thread_args->conditional_variable,
249                                  thread_args->sync_mutex) );
250         }
251
252         printf("This comes second\n");
253
254         printf("SLAVE: Activation nr: %d\n", nr_activation);
255         nr_activation++;
256
257         *(thread_args->slave_can_run) = 0;
258         CHK(  fosa_mutex_unlock(thread_args->sync_mutex) );
259
260     }
261 }
262
263