]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_marte_os/tests/test_group_clocks/test_group_clocks.c
Updating header text in FOSA files for the incoming final project
[frescor/fosa.git] / src_marte_os / tests / test_group_clocks / test_group_clocks.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 #include <unistd.h>
58 #include <stdio.h>
59
60 #include <assert.h>
61 #include <stdlib.h> // for exit in assert
62 #include <string.h> // for memset
63
64 #include "fosa.h"
65
66 /*****************************/
67 /*   D E F I N I T I O N S   */
68 /*****************************/
69 #define RT_ERROR_SIGWAIT -2
70 #define RT_ERROR_TIMER   -3
71
72 #define SIGNAL_TIMER         (FOSA_SIGNAL_MAX - 1)
73
74 #define SIGNAL_A             (FOSA_SIGNAL_MAX - 2)
75 #define SIGNAL_KILL_A        (FOSA_SIGNAL_MAX - 3)
76
77 #define SIGNAL_B             (FOSA_SIGNAL_MAX - 4)
78 #define SIGNAL_KILL_B        (FOSA_SIGNAL_MAX - 5) 
79 #define SIGNAL_C             (FOSA_SIGNAL_MAX - 6)
80 #define SIGNAL_KILL_C        (FOSA_SIGNAL_MAX - 7)
81
82
83 #define PRIO_MAIN 4
84 #define PRIO_A 5
85 #define PRIO_B 6
86 #define PRIO_C 7
87 #define PRIO_CATCHER 8
88
89
90 typedef struct _my_signal_info_t
91 {
92     fosa_rel_time_t eat_time;
93 } my_signal_info_t;
94
95 typedef struct _my_thread_arg_t
96 {
97     char identifier[100];
98     fosa_signal_t signum;
99     fosa_signal_t sigkill;
100 } my_thread_arg_t;
101
102
103
104
105 /***************************/
106 /*   P R O T O T Y P E S   */
107 /***************************/
108 static void *controlled_thread(void *thread_arg);
109 static void *catcher_thread(void *arg);
110
111 static void create_thread(fosa_thread_code_t thread_code,  
112                           void *arg, 
113                           int priority, 
114                           fosa_thread_id_t *tid);
115
116 static void time_printf(const char *format, ...);
117
118
119 /***************************/
120 /*  S T A T I C   D A T A  */
121 /***************************/
122 static fosa_abs_time_t start_time;
123 static bool timer_expired;
124
125
126 int main ()
127 {
128     int err = -1;
129
130     fosa_thread_id_t tid_A, tid_B, tid_C, tid_catcher;
131     my_thread_arg_t thread_arg_A, thread_arg_B, thread_arg_C;
132     fosa_rel_time_t eat_time_A, eat_time_B, eat_time_C, group_time;
133     fosa_signal_info_t siginfo_A, siginfo_B, siginfo_C, siginfo_timer;
134     
135     fosa_thread_set_id_t thread_set_id;
136     fosa_clock_id_t group_clock_id;
137     fosa_timer_id_t group_timer;
138
139     /* Initialize base time and thread arguments */
140     /*********************************************/
141     fosa_clock_get_time(FOSA_CLOCK_REALTIME, &start_time);
142
143     strcpy(thread_arg_A.identifier, "THREAD A");
144     thread_arg_A.signum = SIGNAL_A;
145     thread_arg_A.sigkill = SIGNAL_KILL_A;
146     siginfo_A.sival_ptr = &eat_time_A;
147
148     strcpy(thread_arg_B.identifier, "THREAD B");
149     thread_arg_B.signum = SIGNAL_B;
150     thread_arg_B.sigkill = SIGNAL_KILL_B;
151     siginfo_B.sival_ptr = &eat_time_B;
152
153     strcpy(thread_arg_C.identifier, "THREAD C");
154     thread_arg_C.signum = SIGNAL_C;
155     thread_arg_C.sigkill = SIGNAL_KILL_C;
156     siginfo_C.sival_ptr = &eat_time_C;
157
158     
159     /* We set our priority and create the threads.  The threads */
160     /* will be blocked waiting for the signal.                  */
161     /************************************************************/
162     err = fosa_thread_set_prio(fosa_thread_self(), fosa_get_priority_min() + PRIO_MAIN);
163     if (err != 0)
164     {
165         printf("MAIN:  Error %d with setting main priority\n", err);
166         exit(1);
167     }
168
169     create_thread(controlled_thread, &thread_arg_A, PRIO_A, &tid_A);
170     create_thread(controlled_thread, &thread_arg_B, PRIO_B, &tid_B);
171     create_thread(controlled_thread, &thread_arg_C, PRIO_C, &tid_C);
172
173     create_thread(catcher_thread, NULL, PRIO_CATCHER, &tid_catcher);
174     
175
176     /* We create the thread set, get its clock and create a timer */
177     /****************************************************************/
178     err = fosa_thread_set_create(&thread_set_id);
179     if (err != 0)
180     {
181         printf("MAIN: Error %d creating thread_set\n", err);
182         exit(1);
183     }
184
185     err = fosa_get_groupcpu_clock(thread_set_id, &group_clock_id);
186     if (err != 0)
187     {
188         printf("MAIN: Error %d obtaining group clock\n", err);
189         exit(1);
190     }
191     
192     err = fosa_timer_create(group_clock_id, SIGNAL_TIMER, siginfo_timer, &group_timer);
193     if (err != 0)
194     {
195         printf("MAIN: Error %d obtaining group CPU timer\n", err);
196         exit(1);
197     }
198
199     /* We add the 3 threads to the set */
200     /*************************************/
201     err = fosa_thread_set_add(thread_set_id, tid_A);
202     if (err != 0)
203     {
204         printf("MAIN: Error %d adding thread to thread set\n", err);
205         exit(1);
206     }
207
208     err = fosa_thread_set_add(thread_set_id, tid_B);
209     if (err != 0)
210     {
211         printf("MAIN: Error %d adding thread to thread set\n", err);
212         exit(1);
213     }
214
215     err = fosa_thread_set_add(thread_set_id, tid_C);
216     if (err != 0)
217     {
218         printf("MAIN: Error %d adding thread to thread set\n", err);
219         exit(1);
220     }
221
222
223     /* First experiment:  We arm the group CPU timer with 5 sec and */
224     /* make each thread execute two seconds each.                   */
225     /****************************************************************/
226     eat_time_A = fosa_msec_to_rel_time(2000);
227     eat_time_B = fosa_msec_to_rel_time(2000);
228     eat_time_C = fosa_msec_to_rel_time(2000);
229
230     group_time = fosa_msec_to_rel_time(5000);
231
232     timer_expired = false;
233     time_printf("MAIN:  Arming group timer for 5 seconds\n");
234     err = fosa_rel_timer_arm(group_timer, &group_time);
235     if (err != 0)
236     {
237         printf("MAIN: Error %d queueing signal\n", err);
238         exit(1);
239     }
240
241     err = fosa_signal_queue(SIGNAL_A, siginfo_A, (fosa_thread_id_t) 0);
242     if (err != 0)
243     {
244         printf("MAIN: Error %d queueing signal\n", err);
245         exit(1);
246     }
247
248     err = fosa_signal_queue(SIGNAL_B, siginfo_B, (fosa_thread_id_t) 0);
249     if (err != 0)
250     {
251         printf("MAIN: Error %d queueing signal\n", err);
252         exit(1);
253     }
254
255     err = fosa_signal_queue(SIGNAL_C, siginfo_C, (fosa_thread_id_t) 0);
256     if (err != 0)
257     {
258         printf("MAIN: Error %d queueing signal\n", err);
259         exit(1);
260     }
261
262     time_printf("MAIN:  Back after all threads\n");
263
264     assert(timer_expired);
265
266
267     return 0;
268 }
269
270
271 // ----------------------------------------------------------------
272
273 /**
274  *  This is a controlled thread.  It stays waiting for a signal and
275  *  then eats the requested time sent in the signal info.
276  **/
277 static void *controlled_thread(void *arg)
278 {
279
280     fosa_signal_t signal_set[2];
281     int err;
282
283     my_thread_arg_t *thread_arg = (my_thread_arg_t *) arg;
284
285     time_printf("%s: Initializing\n", thread_arg->identifier);
286
287     signal_set[0] = thread_arg->signum;
288     signal_set[1] = thread_arg->sigkill;
289     err = fosa_set_accepted_signals(signal_set, 2);
290     if (err !=0)
291     {
292         printf ("%s: Error %d while setting the signal mask\n", thread_arg->identifier, err);
293         exit (1);
294     }
295
296
297     while(1)
298     {
299         fosa_signal_t signal_received;
300         fosa_signal_info_t info_received;
301         my_signal_info_t *signal_info;
302
303         err = fosa_signal_wait(signal_set, 2, &signal_received, &info_received);
304         if ( err != 0)
305         {
306             printf("%s:  Error %d while waiting for signal\n", thread_arg->identifier, err);
307             exit(1);
308         }
309
310         if (signal_received == thread_arg->sigkill)
311         {
312             time_printf("%s: Terminating\n", thread_arg->identifier);
313             break;
314         }
315
316         signal_info = (my_signal_info_t *) info_received.sival_ptr;
317
318         time_printf("%s: about to eat %ld msec\n", thread_arg->identifier, fosa_rel_time_to_msec(signal_info->eat_time) );
319
320         fosa_eat(&signal_info->eat_time);
321     }
322         
323     return NULL;
324 }
325
326 // ------------------------------------------------------------------
327
328 static void *catcher_thread(void *arg)
329 {
330     int err = -1;
331     fosa_signal_t signal_set[1];
332
333     time_printf("CATCHER:  Initializing\n");
334
335     signal_set[0] = SIGNAL_TIMER;
336     err = fosa_set_accepted_signals(signal_set, 1);
337     if (err !=0)
338     {
339         printf ("CATCHER: Error %d while setting the signal mask\n", err);
340         exit (1);
341     }
342
343     while(1)
344     {
345         fosa_signal_t signal_received;
346         fosa_signal_info_t info_received;
347
348         err = fosa_signal_wait(signal_set, 1, &signal_received, &info_received);
349         if ( err != 0)
350         {
351             printf("CATCHER:  Error %d while waiting for signal\n", err);
352             exit(1);
353         }
354
355         time_printf("CATCHER:  Group timer expired!!!\n");
356         timer_expired = true;
357     }
358
359     return NULL;
360 }
361
362
363 // ------------------------------------------------------------------------
364
365 static void create_thread(fosa_thread_code_t thread_code,  
366                           void *arg, 
367                           int priority, 
368                           fosa_thread_id_t *tid)
369 {
370     fosa_thread_attr_t attr;
371     int err;
372
373     err = fosa_thread_attr_init(&attr);
374     if (err != 0) {
375         printf("Error %d while initializing the attr\n", err);
376         exit(1);
377     }
378
379     err = fosa_thread_attr_set_prio(&attr, fosa_get_priority_min() + priority);
380     if (err != 0) {
381         printf("Error %d while setting priority\n", err);
382         exit(1);
383     }
384
385     err = fosa_thread_create(tid, &attr, thread_code, arg);
386     if (err) {
387         printf("Error %d in fosa_thread_create\n", err);
388         exit(1);
389     }
390 }
391
392
393
394 // ------------------------------------------------------------------------
395
396
397 static void time_printf(const char *format, ...)
398 {
399     va_list args;
400
401     fosa_abs_time_t current_time;
402     fosa_rel_time_t interval;
403
404     fosa_clock_get_time(FOSA_CLOCK_REALTIME, &current_time);
405     interval = fosa_abs_time_extract_interval(start_time, current_time);
406
407     printf("%ld:", fosa_rel_time_to_msec(interval));
408
409     va_start(args, format);
410     vprintf(format, args);
411     va_end(args);
412 }