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 // -----------------------------------------------------------------------
56 #include <stdio.h> // for printf
57 #include <string.h> // for strlen, strncpy
58 #include <unistd.h> // for sleep
59 #include <time.h> // for nanosleep
62 // TODO: use #include <assert.h> when it works for all architectures
63 #include <stdlib.h> // for exit in assert
67 static void inline assert(expression)
70 printe(__FILE__":%u: failed assertion.\n", __LINE__);
75 ///////////////////////////////////////////////////////
76 // 0) Function prototypes
77 ///////////////////////////////////////////////////////
79 static void *thread_code(void *arg);
81 static void fosa_callback_init
82 (void *sched_data, void *arg);
84 static void fosa_callback_new_thread
86 fosa_thread_id_t thread,
87 fosa_ads_actions_t *actions,
88 fosa_abs_time_t *current_time);
90 static void fosa_callback_thread_terminate
92 fosa_thread_id_t thread,
93 fosa_ads_actions_t *actions,
94 fosa_abs_time_t *current_time);
96 static void fosa_callback_thread_ready
98 fosa_thread_id_t thread,
99 fosa_ads_actions_t *actions,
100 fosa_abs_time_t *current_time);
102 static void fosa_callback_thread_block
104 fosa_thread_id_t thread,
105 fosa_ads_actions_t *actions,
106 fosa_abs_time_t *current_time);
108 static void fosa_callback_change_sched_param_thread
110 fosa_thread_id_t thread,
111 fosa_ads_actions_t *actions,
112 fosa_abs_time_t *current_time);
114 static void fosa_callback_explicit_call_with_data
116 fosa_thread_id_t thread,
121 fosa_ads_actions_t *actions,
122 fosa_abs_time_t *current_time);
124 static void fosa_callback_notification_for_thread
126 fosa_thread_id_t thread,
127 fosa_clock_id_t clock,
128 fosa_ads_actions_t *actions,
129 fosa_abs_time_t *current_time);
131 static void fosa_callback_timeout
133 fosa_ads_actions_t *actions,
134 fosa_abs_time_t *current_time);
136 static void fosa_callback_signal
138 fosa_signal_t signal,
139 fosa_signal_info_t siginfo,
140 fosa_ads_actions_t *actions,
141 fosa_abs_time_t *current_time);
143 static void fosa_callback_appsched_error
145 fosa_thread_id_t thread,
146 fosa_ads_error_cause_t cause,
147 fosa_ads_actions_t *actions);
149 ///////////////////////////////////////////////////////
150 // 1) Types, Module variables and Constants
151 ///////////////////////////////////////////////////////
153 static fosa_ads_scheduler_ops_t scheduler_ops = {
154 .init = fosa_callback_init,
155 .new_thread = fosa_callback_new_thread,
156 .thread_terminate = fosa_callback_thread_terminate,
157 .thread_ready = fosa_callback_thread_ready,
158 .thread_block = fosa_callback_thread_block,
159 .change_sched_param_thread = fosa_callback_change_sched_param_thread,
160 .explicit_call_with_data = fosa_callback_explicit_call_with_data,
161 .notification_for_thread = fosa_callback_notification_for_thread,
162 .timeout = fosa_callback_timeout,
163 .signal = fosa_callback_signal,
164 .appsched_error = fosa_callback_appsched_error,
167 static fosa_mutex_t lock;
169 const unsigned int MX_INIT_ARGS_STRING = 30;
170 const unsigned int MX_PRIO = 20;
173 // general control structure for the scheduler
175 fosa_ads_urgency_t array_prio[MX_THREADS];
176 int array_status[MX_THREADS];
180 fosa_ads_urgency_t prio;
190 fosa_thread_id_t thread_id;
194 ///////////////////////////////////////////////////////
196 ///////////////////////////////////////////////////////
201 char init_args_string[MX_INIT_ARGS_STRING + 1];
202 fosa_thread_id_t tid1, tid2, tid3;
203 fosa_thread_attr_t th_attr;
205 appsched_params_t params;
206 fosa_signal_info_t timer_info;
207 fosa_timer_id_t timerid;
208 fosa_rel_time_t timerval;
209 signal_action_t signal_action;
212 err = fosa_thread_set_prio (fosa_thread_self(), MX_PRIO + 1);
213 printf("set main to highest priority, err=%d\n", err);
216 err = fosa_mutex_init(&lock, MX_PRIO);
217 printf("mutex initialized with ceiling %d. err=%d\n", MX_PRIO, err);
220 //////////////////////////////////
221 // 2a) Create the scheduler
222 //////////////////////////////////
224 printf("--------------------------------------------------\n");
225 printf("2a) Create the scheduler\n");
227 strncpy(init_args_string, "Hello Scheduler!!", MX_INIT_ARGS_STRING);
228 init_args_string[MX_INIT_ARGS_STRING] = '\0';
230 err = fosa_ads_scheduler_create
232 sizeof(fosa_sched_data_t),
233 init_args_string, // INIT IS CALLED INMEDIATELY??!!!
234 strlen(init_args_string) + 1);
235 printf("scheduler created, err=%d\n", err);
238 //////////////////////////////////////////////////////////////
239 // 2b) Create two application scheduled threads
240 //////////////////////////////////////////////////////////////
242 printf("--------------------------------------------------\n");
243 printf("2b) Create two application scheduled threads\n");
245 err = fosa_thread_attr_init(&th_attr);
246 printf("thread attributes object initialized, err=%d\n", err);
249 err = fosa_thread_attr_set_stacksize(&th_attr,40000);
250 printf("thread attr set stack size to 40000, err=%d\n", err);
253 err = fosa_thread_attr_set_prio(&th_attr, MX_PRIO - 1);
254 printf("thread attr set prio to 10, err=%d\n",err);
257 err = fosa_thread_attr_set_appscheduled(&th_attr, true);
258 printf("thread attr set appscheduled, err=%d\n", err);
261 err = fosa_thread_attr_get_appscheduled(&th_attr, &is_appsched);
262 printf("thread attr get appscheduled=%d, err=%d\n",is_appsched, err);
266 err = fosa_thread_attr_set_appsched_params
267 (&th_attr, (void *)¶ms, sizeof(params));
268 printf("thread attr set params prio=%d, err=%d\n", params.prio, err);
272 err = fosa_thread_create (&tid1, &th_attr, thread_code, (void *)1);
273 printf("created thread 1 with prio=%d, err=%d\n", params.prio, err);
277 err = fosa_thread_attr_set_appsched_params
278 (&th_attr, (void *)¶ms, sizeof(params));
279 printf("thread attr set params prio=%d, err=%d\n", params.prio, err);
283 err = fosa_thread_create (&tid2, &th_attr, thread_code, (void *)2);
284 printf("created thread 2 with prio=%d, err=%d\n",params.prio, err);
287 // create thread 3 - should be rejected
288 err = fosa_thread_create (&tid3, &th_attr, thread_code, (void *)3);
289 printf("created thread 3 (rejected=%d), err=%d\n",
290 (err == FOSA_EREJECT), err);
292 err = fosa_thread_attr_destroy(&th_attr);
293 printf("thread attributes object destroyed, err=%d\n",err);
298 //////////////////////////////////////////////////////////////
299 // 2c) Change appsched params
300 //////////////////////////////////////////////////////////////
301 printf("--------------------------------------------------\n");
302 printf("2c) Change appsched params\n");
304 err = fosa_thread_set_prio(tid1,14);
305 printf("priority of thread 1 set to 14, err=%d\n", err);
310 params.prio = MX_PRIO - 5;
311 err = fosa_ads_set_appsched_params(tid2, (void *)¶ms, sizeof(params));
312 printf("urgency of thread 2 set to %d, err=%d\n", params.prio, err);
317 //////////////////////////////////////////////////////////////
319 //////////////////////////////////////////////////////////////
320 printf("--------------------------------------------------\n");
321 printf("2d) Signals\n");
323 signal_action.command = SUSPEND;
324 signal_action.thread_id = tid1;
325 timer_info.sival_ptr = (void *)&signal_action;
327 err = fosa_timer_create
328 (FOSA_CLOCK_REALTIME, FOSA_SIGNAL_MAX, timer_info, &timerid);
329 printf("timer created, err=%d\n", err);
332 timerval = fosa_msec_to_rel_time(500);
334 err=fosa_rel_timer_arm(timerid, &timerval);
335 printf("suspend thread 1 in 0.5 secs, err=%d\n", err);
340 signal_action.command = ACTIVATE;
341 err=fosa_rel_timer_arm(timerid, &timerval);
342 printf("activate thread 1 in 0.5 secs, err=%d\n", err);
347 //////////////////////////////////////////////////////////////
349 //////////////////////////////////////////////////////////////
350 printf("--------------------------------------------------\n");
351 printf("2e) Cause error\n");
353 signal_action.command = CAUSE_ERROR;
354 err=fosa_rel_timer_arm(timerid, &timerval);
355 printf("causing an ERROR callback in 0.5 secs, err=%d\n", err);
360 //////////////////////////////////////////////////////////////
361 // 2f) Dettach from application scheduler
362 //////////////////////////////////////////////////////////////
363 printf("--------------------------------------------------\n");
364 printf("2f) Dettach from application scheduler\n");
366 err = fosa_ads_set_appscheduled (tid1, false);
367 printf("dettach thread 1, err=%d\n", err);
370 err = fosa_ads_get_appscheduled (tid1, &is_appsched);
371 printf("thread 1 is dettached? %d, err=%d\n", !is_appsched, err);
374 err = fosa_ads_get_appscheduled (tid2, &is_appsched);
375 printf("thread 2 is dettached? %d, err=%d\n", !is_appsched, err);
378 fosa_timer_delete(timerid);
384 ///////////////////////////////////////////////////////
386 ///////////////////////////////////////////////////////
388 static void *thread_code (void * arg)
390 struct timespec ts = {2, 0};
392 char whoami[] = "who am i?";
395 fosa_rel_time_t one_second = fosa_msec_to_rel_time(1000);
397 printf("THREAD %d - starts\n", (int)arg);
399 nanosleep (&ts, NULL);
401 printf("THREAD %d - locking mutex\n", (int)arg);
402 err=fosa_mutex_lock(&lock);
405 fosa_eat (&one_second);
407 printf("THREAD %d - unlocking mutex\n", (int)arg);
408 err=fosa_mutex_unlock(&lock);
411 printf("THREAD %d - asking with invoke_withdata\n", (int)arg);
412 err = fosa_ads_invoke_withdata
413 (whoami, sizeof(whoami), (void *)&reply, &reply_size);
414 printf("THREAD %d - received reply, correct?: %d, err=%d\n", (int)arg,
415 reply == (int)fosa_thread_self(), err);
417 printf("THREAD %d - bye bye!!\n", (int)arg);
425 ///////////////////////////////////////////////////////
426 // 4) Implementation of Application Defined Callbacks
427 ///////////////////////////////////////////////////////
428 static void fosa_callback_init
429 (void *sched_data, void *arg)
431 fosa_sched_data_t *frsh = (fosa_sched_data_t *)sched_data;
433 fosa_signal_t sched_signal = FOSA_SIGNAL_MAX; // HOW TO PUT SIGNALS IF IS OPAQUE??
435 printf ("BEGIN CALLBACK: %s \n", __func__);
436 printf ("init args string received: %s \n", (char *)arg);
438 err = fosa_ads_set_handled_signal_set(&sched_signal, 1);
439 printf("set signal set, err=%d\n", err);
442 for (i=0; i<MX_THREADS; i++) {
443 frsh->array_prio[i] = 0;
444 frsh->array_status[i] = 0;
446 printf ("END CALLBACK: %s \n", __func__);
449 static void fosa_callback_new_thread
451 fosa_thread_id_t thread,
452 fosa_ads_actions_t *actions,
453 fosa_abs_time_t *current_time)
456 unsigned int i, index;
457 fosa_sched_data_t *frsh = (fosa_sched_data_t *)sched_data;
458 appsched_params_t params;
461 printf ("BEGIN CALLBACK: %s \n", __func__);
464 for (i=0; i<MX_THREADS; i++) {
465 if (frsh->array_status[i] == 0) {
471 if (index == MX_THREADS) {
472 err = fosa_adsactions_add_reject(actions, thread);
475 // Get the priority for the new thread
476 size = sizeof(params);
477 err = fosa_ads_get_appsched_params(thread, (void *)¶ms, &size);
480 frsh->array_prio[index] = params.prio;
481 frsh->array_status[index] = 1;
483 printf ("END CALLBACK: %s \n", __func__);
486 static void fosa_callback_thread_terminate
488 fosa_thread_id_t thread,
489 fosa_ads_actions_t *actions,
490 fosa_abs_time_t *current_time)
492 fosa_abs_time_t at_time;
495 printf ("BEGIN CALLBACK: %s \n", __func__);
497 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &at_time);
498 printf("current time %ld msec\n", fosa_abs_time_to_msec(at_time) );
499 at_time = fosa_abs_time_incr(at_time, fosa_msec_to_rel_time(1000) );
502 err = fosa_adsactions_add_timeout(actions, FOSA_CLOCK_REALTIME, &at_time);
503 printf("put a timeout of one second, err=%d\n", err);
505 printf ("END CALLBACK: %s \n", __func__);
508 static void fosa_callback_thread_ready
510 fosa_thread_id_t thread,
511 fosa_ads_actions_t *actions,
512 fosa_abs_time_t *current_time)
514 printf ("BEGIN CALLBACK: %s \n", __func__);
515 printf ("END CALLBACK: %s \n", __func__);
518 static void fosa_callback_thread_block
520 fosa_thread_id_t thread,
521 fosa_ads_actions_t *actions,
522 fosa_abs_time_t *current_time)
525 fosa_abs_time_t at_time;
527 printf ("BEGIN CALLBACK: %s \n", __func__);
529 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &at_time);
530 printf("current time %ld msec\n", fosa_abs_time_to_msec(at_time) );
531 at_time = fosa_abs_time_incr(at_time, fosa_msec_to_rel_time(1000) );
533 err = fosa_adsactions_add_timeout(actions, FOSA_CLOCK_REALTIME, &at_time);
534 printf("put a timeout of one second, err=%d\n", err);
536 printf ("END CALLBACK: %s \n", __func__);
539 static void fosa_callback_change_sched_param_thread
541 fosa_thread_id_t thread,
542 fosa_ads_actions_t *actions,
543 fosa_abs_time_t *current_time)
545 printf ("BEGIN CALLBACK: %s \n", __func__);
546 // HOW DO I KNOW THE REASON IS SETPRIO OR SETSCHEDPARAMS????
547 printf ("END CALLBACK: %s \n", __func__);
550 static void fosa_callback_explicit_call_with_data
552 fosa_thread_id_t thread,
557 fosa_ads_actions_t *actions,
558 fosa_abs_time_t *current_time)
560 printf ("BEGIN CALLBACK: %s \n", __func__);
561 *((int *)reply) = (int)thread;
562 printf ("received command: %s , answer %d \n", (char *)msg,
564 printf ("END CALLBACK: %s \n", __func__);
567 static void fosa_callback_notification_for_thread
569 fosa_thread_id_t thread,
570 fosa_clock_id_t clock,
571 fosa_ads_actions_t *actions,
572 fosa_abs_time_t *current_time)
574 printf ("BEGIN CALLBACK: %s \n", __func__);
575 printf ("END CALLBACK: %s \n", __func__);
578 static void fosa_callback_timeout // WHY NOT WATCHDOG????
580 fosa_ads_actions_t *actions,
581 fosa_abs_time_t *current_time) // WHY IS IN OUT and not IN???
583 printf ("BEGIN CALLBACK: %s \n", __func__);
584 printf("current time %ld msec", fosa_abs_time_to_msec(*current_time) );
585 printf ("END CALLBACK: %s \n", __func__);
588 static void fosa_callback_signal
590 fosa_signal_t signal,
591 fosa_signal_info_t siginfo, // HOW DO I KNOW THE ORIGIN (see signal_info type)
592 fosa_ads_actions_t *actions,
593 fosa_abs_time_t *current_time)
596 signal_action_t *signal_action = (signal_action_t *)siginfo.sival_ptr;
597 fosa_sched_data_t *frsh = (fosa_sched_data_t *)sched_data;
599 printf ("BEGIN CALLBACK: %s \n", __func__);
601 switch (signal_action->command) {
603 err=fosa_adsactions_add_suspend(actions, signal_action->thread_id);
604 printf("suspending thread 1 , err=%d\n", err);
608 err = fosa_adsactions_add_activate
609 (actions, signal_action->thread_id, frsh->array_prio[0]);
610 printf("activating thread 1, err=%d\n", err);
614 // cause an error by overwriting actions with 666 ;D
615 *(int *)actions = 666;
617 printf("causing an error, err=%d\n", err);
620 printf ("END CALLBACK: %s \n", __func__);
623 static void fosa_callback_appsched_error
625 fosa_thread_id_t thread,
626 fosa_ads_error_cause_t cause,
627 fosa_ads_actions_t *actions)
629 printf ("BEGIN CALLBACK: %s \n", __func__);
630 printf ("END CALLBACK: %s \n", __func__);