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 // -----------------------------------------------------------------------
61 #include <stdlib.h> // for exit in assert
62 #include <string.h> // for memset
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
72 #define SIGNAL_TIMER (FOSA_SIGNAL_MAX - 1)
74 #define SIGNAL_A (FOSA_SIGNAL_MAX - 2)
75 #define SIGNAL_KILL_A (FOSA_SIGNAL_MAX - 3)
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)
87 #define PRIO_CATCHER 8
90 typedef struct _my_signal_info_t
92 fosa_rel_time_t eat_time;
95 typedef struct _my_thread_arg_t
99 fosa_signal_t sigkill;
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);
111 static void create_thread(fosa_thread_code_t thread_code,
114 fosa_thread_id_t *tid);
116 static void time_printf(const char *format, ...);
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;
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;
135 fosa_thread_group_id_t thread_group_id;
136 fosa_clock_id_t group_clock_id;
137 fosa_timer_id_t group_timer;
139 /* Initialize base time and thread arguments */
140 /*********************************************/
141 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &start_time);
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;
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;
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;
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);
165 printf("MAIN: Error %d with setting main priority\n", err);
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);
173 create_thread(catcher_thread, NULL, PRIO_CATCHER, &tid_catcher);
176 /* We create the thread group, get its clock and create a timer */
177 /****************************************************************/
178 err = fosa_thread_group_create(&thread_group_id);
181 printf("MAIN: Error %d creating thread_group\n", err);
185 err = fosa_get_groupcpu_clock(thread_group_id, &group_clock_id);
188 printf("MAIN: Error %d obtaining group clock\n", err);
192 err = fosa_timer_create(group_clock_id, SIGNAL_TIMER, siginfo_timer, &group_timer);
195 printf("MAIN: Error %d obtaining group CPU timer\n", err);
199 /* We add the 3 threads to the group */
200 /*************************************/
201 err = fosa_thread_group_add(thread_group_id, tid_A);
204 printf("MAIN: Error %d adding thread to thread group\n", err);
208 err = fosa_thread_group_add(thread_group_id, tid_B);
211 printf("MAIN: Error %d adding thread to thread group\n", err);
215 err = fosa_thread_group_add(thread_group_id, tid_C);
218 printf("MAIN: Error %d adding thread to thread group\n", err);
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);
230 group_time = fosa_msec_to_rel_time(5000);
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);
237 printf("MAIN: Error %d queueing signal\n", err);
241 err = fosa_signal_queue(SIGNAL_A, siginfo_A, (fosa_thread_id_t) 0);
244 printf("MAIN: Error %d queueing signal\n", err);
248 err = fosa_signal_queue(SIGNAL_B, siginfo_B, (fosa_thread_id_t) 0);
251 printf("MAIN: Error %d queueing signal\n", err);
255 err = fosa_signal_queue(SIGNAL_C, siginfo_C, (fosa_thread_id_t) 0);
258 printf("MAIN: Error %d queueing signal\n", err);
262 time_printf("MAIN: Back after all threads\n");
264 assert(timer_expired);
271 // ----------------------------------------------------------------
274 * This is a controlled thread. It stays waiting for a signal and
275 * then eats the requested time sent in the signal info.
277 static void *controlled_thread(void *arg)
280 fosa_signal_t signal_set[2];
283 my_thread_arg_t *thread_arg = (my_thread_arg_t *) arg;
285 time_printf("%s: Initializing\n", thread_arg->identifier);
287 signal_set[0] = thread_arg->signum;
288 signal_set[1] = thread_arg->sigkill;
289 err = fosa_set_accepted_signals(signal_set, 2);
292 printf ("%s: Error %d while setting the signal mask\n", thread_arg->identifier, err);
299 fosa_signal_t signal_received;
300 fosa_signal_info_t info_received;
301 my_signal_info_t *signal_info;
303 err = fosa_signal_wait(signal_set, 2, &signal_received, &info_received);
306 printf("%s: Error %d while waiting for signal\n", thread_arg->identifier, err);
310 if (signal_received == thread_arg->sigkill)
312 time_printf("%s: Terminating\n", thread_arg->identifier);
316 signal_info = (my_signal_info_t *) info_received.sival_ptr;
318 time_printf("%s: about to eat %ld msec\n", thread_arg->identifier, fosa_rel_time_to_msec(signal_info->eat_time) );
320 fosa_eat(&signal_info->eat_time);
326 // ------------------------------------------------------------------
328 static void *catcher_thread(void *arg)
331 fosa_signal_t signal_set[1];
333 time_printf("CATCHER: Initializing\n");
335 signal_set[0] = SIGNAL_TIMER;
336 err = fosa_set_accepted_signals(signal_set, 1);
339 printf ("CATCHER: Error %d while setting the signal mask\n", err);
345 fosa_signal_t signal_received;
346 fosa_signal_info_t info_received;
348 err = fosa_signal_wait(signal_set, 1, &signal_received, &info_received);
351 printf("CATCHER: Error %d while waiting for signal\n", err);
355 time_printf("CATCHER: Group timer expired!!!\n");
356 timer_expired = true;
363 // ------------------------------------------------------------------------
365 static void create_thread(fosa_thread_code_t thread_code,
368 fosa_thread_id_t *tid)
370 fosa_thread_attr_t attr;
373 err = fosa_thread_attr_init(&attr);
375 printf("Error %d while initializing the attr\n", err);
379 err = fosa_thread_attr_set_prio(&attr, fosa_get_priority_min() + priority);
381 printf("Error %d while setting priority\n", err);
385 err = fosa_thread_create(tid, &attr, thread_code, arg);
387 printf("Error %d in fosa_thread_create\n", err);
394 // ------------------------------------------------------------------------
397 static void time_printf(const char *format, ...)
401 fosa_abs_time_t current_time;
402 fosa_rel_time_t interval;
404 fosa_clock_get_time(FOSA_CLOCK_REALTIME, ¤t_time);
405 interval = fosa_abs_time_extract_interval(start_time, current_time);
407 printf("%ld:", fosa_rel_time_to_msec(interval));
409 va_start(args, format);
410 vprintf(format, args);