1 //----------------------------------------------------------------------
2 // Copyright (C) 2006 - 2007 by the FRESCOR consortium:
4 // Universidad de Cantabria, SPAIN
5 // University of York, UK
6 // Scuola Superiore Sant'Anna, ITALY
7 // Kaiserslautern University, GERMANY
8 // Univ. Politecnica 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
18 // The 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 // This file is part of FOSA (Frsh Operating System Abstraction)
33 // FOSA is free software; you can redistribute it and/or modify it
34 // under terms of the GNU General Public License as published by the
35 // Free Software Foundation; either version 2, or (at your option) any
36 // later version. FOSA is distributed in the hope that it will be
37 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
38 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39 // General Public License for more details. You should have received a
40 // copy of the GNU General Public License along with FOSA; see file
41 // COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
42 // Cambridge, MA 02139, USA.
44 // As a special exception, including FOSA header files in a file,
45 // instantiating FOSA generics or templates, or linking other files
46 // with FOSA objects to produce an executable application, does not
47 // by itself cause the resulting executable application to be covered
48 // by the GNU General Public License. This exception does not
49 // however invalidate any other reasons why the executable file might be
50 // covered by the GNU Public License.
51 // -----------------------------------------------------------------------
53 #include "fosa_app_def_sched.h"
54 #include "fosa_threads_and_signals.h"
55 #include "fosa_mutexes_and_condvars.h"
56 #include "fosa_clocks_and_timers.h"
57 #include <stdio.h> // for printf
58 #include <string.h> // for strlen, strncpy
59 #include <unistd.h> // for sleep
60 #include <time.h> // for nanosleep
61 #include <misc/load.h> // for adjust, eat
63 // TODO: use #include <assert.h> when it works for all architectures
64 #include <stdlib.h> // for exit in assert
66 static void inline assert(expression)
69 printe(__FILE__":%u: failed assertion.\n", __LINE__);
74 ///////////////////////////////////////////////////////
75 // 0) Function prototypes
76 ///////////////////////////////////////////////////////
78 static void *thread_code(void *arg);
80 static void frsh_callback_init
81 (void *sched_data, void *arg);
83 static void frsh_callback_new_thread
85 frsh_thread_id_t thread,
86 fosa_ads_actions_t *actions,
87 struct timespec *current_time);
89 static void frsh_callback_thread_terminate
91 frsh_thread_id_t thread,
92 fosa_ads_actions_t *actions,
93 struct timespec *current_time);
95 static void frsh_callback_thread_ready
97 frsh_thread_id_t thread,
98 fosa_ads_actions_t *actions,
99 struct timespec *current_time);
101 static void frsh_callback_thread_block
103 frsh_thread_id_t thread,
104 fosa_ads_actions_t *actions,
105 struct timespec *current_time);
107 static void frsh_callback_change_sched_param_thread
109 frsh_thread_id_t thread,
110 fosa_ads_actions_t *actions,
111 struct timespec *current_time);
113 static void frsh_callback_explicit_call_with_data
115 frsh_thread_id_t thread,
120 fosa_ads_actions_t *actions,
121 struct timespec *current_time);
123 static void frsh_callback_notification_for_thread
125 frsh_thread_id_t thread,
126 fosa_clock_id_t clock,
127 fosa_ads_actions_t *actions,
128 struct timespec *current_time);
130 static void frsh_callback_timeout
132 fosa_ads_actions_t *actions,
133 struct timespec *current_time);
135 static void frsh_callback_signal
137 frsh_signal_t signal,
138 frsh_signal_info_t siginfo,
139 fosa_ads_actions_t *actions,
140 struct timespec *current_time);
142 static void frsh_callback_appsched_error
144 frsh_thread_id_t thread,
145 fosa_ads_error_cause_t cause,
146 fosa_ads_actions_t *actions);
148 ///////////////////////////////////////////////////////
149 // 1) Types, Module variables and Constants
150 ///////////////////////////////////////////////////////
152 static fosa_ads_scheduler_ops_t scheduler_ops = {
153 .init = frsh_callback_init,
154 .new_thread = frsh_callback_new_thread,
155 .thread_terminate = frsh_callback_thread_terminate,
156 .thread_ready = frsh_callback_thread_ready,
157 .thread_block = frsh_callback_thread_block,
158 .change_sched_param_thread = frsh_callback_change_sched_param_thread,
159 .explicit_call_with_data = frsh_callback_explicit_call_with_data,
160 .notification_for_thread = frsh_callback_notification_for_thread,
161 .timeout = frsh_callback_timeout,
162 .signal = frsh_callback_signal,
163 .appsched_error = frsh_callback_appsched_error,
166 static frsh_mutex_t lock;
168 const unsigned int MX_INIT_ARGS_STRING = 30;
169 const unsigned int MX_PRIO = 20;
172 // general control structure for the scheduler
174 fosa_ads_urgency_t array_prio[MX_THREADS];
175 int array_status[MX_THREADS];
179 fosa_ads_urgency_t prio;
189 frsh_thread_id_t thread_id;
193 ///////////////////////////////////////////////////////
195 ///////////////////////////////////////////////////////
200 char init_args_string[MX_INIT_ARGS_STRING + 1];
201 frsh_thread_id_t tid1, tid2, tid3;
202 frsh_thread_attr_t th_attr;
204 appsched_params_t params;
205 frsh_signal_info_t timer_info;
206 fosa_timer_id_t timerid;
207 struct timespec timerval;
208 signal_action_t signal_action;
210 adjust(); // for function eat
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(frsh_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 = frsh_thread_attr_init(&th_attr);
246 printf("thread attributes object initialized, err=%d\n", err);
249 err = frsh_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 = frsh_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);
333 timerval.tv_nsec = 500000000;
335 err=fosa_timer_arm(timerid, false, &timerval);
336 printf("suspend thread 1 in 0.5 secs, err=%d\n", err);
341 signal_action.command = ACTIVATE;
342 err=fosa_timer_arm(timerid, false, &timerval);
343 printf("activate thread 1 in 0.5 secs, err=%d\n", err);
348 //////////////////////////////////////////////////////////////
350 //////////////////////////////////////////////////////////////
351 printf("--------------------------------------------------\n");
352 printf("2e) Cause error\n");
354 signal_action.command = CAUSE_ERROR;
355 err=fosa_timer_arm(timerid, false, &timerval);
356 printf("causing an ERROR callback in 0.5 secs, err=%d\n", err);
361 //////////////////////////////////////////////////////////////
362 // 2f) Dettach from application scheduler
363 //////////////////////////////////////////////////////////////
364 printf("--------------------------------------------------\n");
365 printf("2f) Dettach from application scheduler\n");
367 err = fosa_ads_set_appscheduled (tid1, false);
368 printf("dettach thread 1, err=%d\n", err);
371 err = fosa_ads_get_appscheduled (tid1, &is_appsched);
372 printf("thread 1 is dettached? %d, err=%d\n", !is_appsched, err);
375 err = fosa_ads_get_appscheduled (tid2, &is_appsched);
376 printf("thread 2 is dettached? %d, err=%d\n", !is_appsched, err);
379 fosa_timer_delete(timerid);
385 ///////////////////////////////////////////////////////
387 ///////////////////////////////////////////////////////
389 static void *thread_code (void * arg)
391 struct timespec ts = {2, 0};
393 char whoami[] = "who am i?";
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);
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 frsh_callback_init
429 (void *sched_data, void *arg)
431 frsh_sched_data_t *frsh = (frsh_sched_data_t *)sched_data;
433 frsh_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 frsh_callback_new_thread
451 frsh_thread_id_t thread,
452 fosa_ads_actions_t *actions,
453 struct timespec *current_time)
456 unsigned int i, index;
457 frsh_sched_data_t *frsh = (frsh_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 frsh_callback_thread_terminate
488 frsh_thread_id_t thread,
489 fosa_ads_actions_t *actions,
490 struct timespec *current_time)
492 struct timespec at_time;
495 printf ("BEGIN CALLBACK: %s \n", __func__);
497 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &at_time);
498 printf("current time sec=%d nsec=%d\n", at_time.tv_sec, at_time.tv_nsec);
499 at_time.tv_sec = at_time.tv_sec + 1;
501 err = fosa_adsactions_add_timeout(actions, FOSA_CLOCK_REALTIME, &at_time);
502 printf("put a timeout of one second, err=%d\n", err);
504 printf ("END CALLBACK: %s \n", __func__);
507 static void frsh_callback_thread_ready
509 frsh_thread_id_t thread,
510 fosa_ads_actions_t *actions,
511 struct timespec *current_time)
513 printf ("BEGIN CALLBACK: %s \n", __func__);
514 printf ("END CALLBACK: %s \n", __func__);
517 static void frsh_callback_thread_block
519 frsh_thread_id_t thread,
520 fosa_ads_actions_t *actions,
521 struct timespec *current_time)
524 struct timespec at_time;
526 printf ("BEGIN CALLBACK: %s \n", __func__);
528 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &at_time);
529 printf("current time sec=%d nsec=%d\n", at_time.tv_sec, at_time.tv_nsec);
530 at_time.tv_sec = at_time.tv_sec + 1;
532 err = fosa_adsactions_add_timeout(actions, FOSA_CLOCK_REALTIME, &at_time);
533 printf("put a timeout of one second, err=%d\n", err);
535 printf ("END CALLBACK: %s \n", __func__);
538 static void frsh_callback_change_sched_param_thread
540 frsh_thread_id_t thread,
541 fosa_ads_actions_t *actions,
542 struct timespec *current_time)
544 printf ("BEGIN CALLBACK: %s \n", __func__);
545 // HOW DO I KNOW THE REASON IS SETPRIO OR SETSCHEDPARAMS????
546 printf ("END CALLBACK: %s \n", __func__);
549 static void frsh_callback_explicit_call_with_data
551 frsh_thread_id_t thread,
556 fosa_ads_actions_t *actions,
557 struct timespec *current_time)
559 printf ("BEGIN CALLBACK: %s \n", __func__);
560 *((int *)reply) = (int)thread;
561 printf ("received command: %s , answer %d \n", (char *)msg,
563 printf ("END CALLBACK: %s \n", __func__);
566 static void frsh_callback_notification_for_thread
568 frsh_thread_id_t thread,
569 fosa_clock_id_t clock,
570 fosa_ads_actions_t *actions,
571 struct timespec *current_time)
573 printf ("BEGIN CALLBACK: %s \n", __func__);
574 printf ("END CALLBACK: %s \n", __func__);
577 static void frsh_callback_timeout // WHY NOT WATCHDOG????
579 fosa_ads_actions_t *actions,
580 struct timespec *current_time) // WHY IS IN OUT and not IN???
582 printf ("BEGIN CALLBACK: %s \n", __func__);
583 printf("current time sec=%d nsec=%d\n",
584 current_time->tv_sec, current_time->tv_nsec);
585 printf ("END CALLBACK: %s \n", __func__);
588 static void frsh_callback_signal
590 frsh_signal_t signal,
591 frsh_signal_info_t siginfo, // HOW DO I KNOW THE ORIGIN (see signal_info type)
592 fosa_ads_actions_t *actions,
593 struct timespec *current_time)
596 signal_action_t *signal_action = (signal_action_t *)siginfo.sival_ptr;
597 frsh_sched_data_t *frsh = (frsh_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;
616 printf("causing an error, err=%d\n", err);
619 printf ("END CALLBACK: %s \n", __func__);
622 static void frsh_callback_appsched_error
624 frsh_thread_id_t thread,
625 fosa_ads_error_cause_t cause,
626 fosa_ads_actions_t *actions)
628 printf ("BEGIN CALLBACK: %s \n", __func__);
629 printf ("END CALLBACK: %s \n", __func__);