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