1 #include "fosa_app_def_sched.h"
2 #include "fosa_threads_and_signals.h"
3 #include "fosa_mutexes_and_condvars.h"
4 #include "fosa_clocks_and_timers.h"
5 #include <stdio.h> // for printf
6 #include <string.h> // for strlen, strncpy
7 #include <unistd.h> // for sleep
8 #include <time.h> // for nanosleep
9 #include <misc/load.h> // for adjust, eat
11 // TODO: use #include <misc/assert.h> when it works for all architectures
12 #include <stdlib.h> // for exit in assert
14 static void inline assert(expression)
17 printe(__FILE__":%u: failed assertion.\n", __LINE__);
22 ///////////////////////////////////////////////////////
23 // 0) Function prototypes
24 ///////////////////////////////////////////////////////
26 static void *thread_code(void *arg);
28 static void frsh_callback_init
29 (void *sched_data, void *arg);
31 static void frsh_callback_new_thread
33 frsh_thread_id_t thread,
34 fosa_ads_actions_t *actions,
35 struct timespec *current_time);
37 static void frsh_callback_thread_terminate
39 frsh_thread_id_t thread,
40 fosa_ads_actions_t *actions,
41 struct timespec *current_time);
43 static void frsh_callback_thread_ready
45 frsh_thread_id_t thread,
46 fosa_ads_actions_t *actions,
47 struct timespec *current_time);
49 static void frsh_callback_thread_block
51 frsh_thread_id_t thread,
52 fosa_ads_actions_t *actions,
53 struct timespec *current_time);
55 static void frsh_callback_change_sched_param_thread
57 frsh_thread_id_t thread,
58 fosa_ads_actions_t *actions,
59 struct timespec *current_time);
61 static void frsh_callback_explicit_call_with_data
63 frsh_thread_id_t thread,
68 fosa_ads_actions_t *actions,
69 struct timespec *current_time);
71 static void frsh_callback_notification_for_thread
73 frsh_thread_id_t thread,
74 fosa_clock_id_t clock,
75 fosa_ads_actions_t *actions,
76 struct timespec *current_time);
78 static void frsh_callback_timeout
80 fosa_ads_actions_t *actions,
81 struct timespec *current_time);
83 static void frsh_callback_signal
86 frsh_signal_info_t siginfo,
87 fosa_ads_actions_t *actions,
88 struct timespec *current_time);
90 static void frsh_callback_appsched_error
92 frsh_thread_id_t thread,
93 fosa_ads_error_cause_t cause,
94 fosa_ads_actions_t *actions);
96 ///////////////////////////////////////////////////////
97 // 1) Types, Module variables and Constants
98 ///////////////////////////////////////////////////////
100 static fosa_ads_scheduler_ops_t scheduler_ops = {
101 .init = frsh_callback_init,
102 .new_thread = frsh_callback_new_thread,
103 .thread_terminate = frsh_callback_thread_terminate,
104 .thread_ready = frsh_callback_thread_ready,
105 .thread_block = frsh_callback_thread_block,
106 .change_sched_param_thread = frsh_callback_change_sched_param_thread,
107 .explicit_call_with_data = frsh_callback_explicit_call_with_data,
108 .notification_for_thread = frsh_callback_notification_for_thread,
109 .timeout = frsh_callback_timeout,
110 .signal = frsh_callback_signal,
111 .appsched_error = frsh_callback_appsched_error,
114 static frsh_mutex_t lock;
116 const unsigned int MX_INIT_ARGS_STRING = 30;
117 const unsigned int MX_PRIO = 20;
120 // general control structure for the scheduler
122 fosa_ads_urgency_t array_prio[MX_THREADS];
123 int array_status[MX_THREADS];
127 fosa_ads_urgency_t prio;
136 frsh_thread_id_t thread_id;
140 ///////////////////////////////////////////////////////
142 ///////////////////////////////////////////////////////
147 char init_args_string[MX_INIT_ARGS_STRING + 1];
148 frsh_thread_id_t tid1, tid2, tid3;
149 frsh_thread_attr_t th_attr;
151 appsched_params_t params;
152 frsh_signal_info_t timer_info;
153 fosa_timer_id_t timerid;
154 struct timespec timerval;
155 signal_action_t signal_action;
157 adjust(); // for function eat
159 err = fosa_mutex_init(&lock, MX_PRIO);
160 printf("mutex initialized with ceiling %d. err=%d\n", MX_PRIO, err);
163 //////////////////////////////////
164 // 2a) Create the scheduler
165 //////////////////////////////////
167 printf("--------------------------------------------------\n");
168 printf("2a) Create the scheduler\n");
170 strncpy(init_args_string, "Hello Scheduler!!", MX_INIT_ARGS_STRING);
171 init_args_string[MX_INIT_ARGS_STRING] = '\0';
173 err = fosa_ads_scheduler_create
175 sizeof(frsh_sched_data_t),
176 init_args_string, // INIT IS CALLED INMEDIATELY??!!!
177 strlen(init_args_string) + 1);
178 printf("scheduler created, err=%d\n", err);
181 //////////////////////////////////////////////////////////////
182 // 2b) Create two application scheduled threads
183 //////////////////////////////////////////////////////////////
185 printf("--------------------------------------------------\n");
186 printf("2b) Create two application scheduled threads\n");
188 err = frsh_thread_attr_init(&th_attr);
189 printf("thread attributes object initialized, err=%d\n", err);
192 err = frsh_thread_attr_set_stacksize(&th_attr,40000);
193 printf("thread attr set stack size to 40000, err=%d\n", err);
196 err = fosa_thread_attr_set_prio(&th_attr, MX_PRIO - 1);
197 printf("thread attr set prio to 10, err=%d\n",err);
200 err = fosa_thread_attr_set_appscheduled(&th_attr, true);
201 printf("thread attr set appscheduled, err=%d\n", err);
204 err = fosa_thread_attr_get_appscheduled(&th_attr, &is_appsched);
205 printf("thread attr get appscheduled=%d, err=%d\n",is_appsched, err);
209 err = fosa_thread_attr_set_appsched_params
210 (&th_attr, (void *)¶ms, sizeof(params));
211 printf("thread attr set params prio=%d, err=%d\n", params.prio, err);
215 err = fosa_thread_create (&tid1, &th_attr, thread_code, (void *)1);
216 printf("creating thread 1 with prio=%d, err=%d\n", params.prio, err);
220 err = fosa_thread_attr_set_appsched_params
221 (&th_attr, (void *)¶ms, sizeof(params));
222 printf("thread attr set params prio=%d, err=%d\n", params.prio, err);
226 err = fosa_thread_create (&tid2, &th_attr, thread_code, (void *)2);
227 printf("creating thread 2 with prio=%d, err=%d\n",params.prio, err);
230 err = frsh_thread_attr_destroy(&th_attr);
231 printf("thread attributes object destroyed, err=%d\n",err);
234 // create thread 3 - should be rejected
235 err = fosa_thread_create (&tid3, &th_attr, thread_code, (void *)3);
236 printf("creating thread 3 (rejected=%d), err=%d\n",
237 (err == FOSA_EREJECT), err);
239 err = frsh_thread_attr_destroy(&th_attr);
240 printf("thread attributes object destroyed, err=%d\n",err);
245 //////////////////////////////////////////////////////////////
246 // 2c) Change appsched params
247 //////////////////////////////////////////////////////////////
248 printf("--------------------------------------------------\n");
249 printf("2c) Change appsched params\n");
251 err = fosa_thread_set_prio(tid1,14);
252 printf("priority of thread 1 set to 14, err=%d\n", err);
257 params.prio = MX_PRIO - 5;
258 err = fosa_ads_set_appsched_params(tid2, (void *)¶ms, sizeof(params));
259 printf("urgency of thread 2 set to %d, err=%d\n", params.prio, err);
264 //////////////////////////////////////////////////////////////
265 // 2d) Dettach from application scheduler
266 //////////////////////////////////////////////////////////////
267 printf("--------------------------------------------------\n");
268 printf("2d) Dettach from application scheduler\n");
270 err = fosa_ads_set_appscheduled (tid1, false);
271 printf("dettach thread 1, err=%d\n", err);
274 err = fosa_ads_set_appscheduled (tid2, false);
275 printf("dettach thread 2, err=%d\n", err);
278 err = fosa_ads_get_appscheduled (tid1, &is_appsched);
279 printf("thread 1 is dettached? %d, err=%d\n", is_appsched, err);
282 err = fosa_ads_get_appscheduled (tid2, &is_appsched);
283 printf("thread 2 is dettached? %d, err=%d\n", is_appsched, err);
286 signal_action.command = SUSPEND;
287 signal_action.thread_id = tid1;
288 timer_info.sival_ptr = (void *)&signal_action;
290 err = fosa_timer_create
291 (FOSA_CLOCK_REALTIME, FOSA_SIGNAL_MAX, timer_info, &timerid);
292 printf("timer created, err=%d\n", err);
296 timerval.tv_nsec = 500000000;
298 err=fosa_timer_arm(timerid, false, &timerval);
299 printf("suspend thread 1 in 0.5 secs, err=%d\n", err);
304 signal_action.command = ACTIVATE;
305 err=fosa_timer_arm(timerid, false, &timerval);
306 printf("activate thread 1 in 0.5 secs, err=%d\n", err);
309 fosa_timer_delete(timerid);
315 ///////////////////////////////////////////////////////
317 ///////////////////////////////////////////////////////
319 static void *thread_code (void * arg)
321 struct timespec ts = {2, 0};
323 char whoami[] = "who am i?";
327 printf("Thread %d starts\n", (int)arg);
329 nanosleep (&ts, NULL);
333 err=fosa_mutex_lock(&lock);
334 printf("mutex locked by %d. err=%d\n", (int)arg, err);
339 err=fosa_mutex_unlock(&lock);
340 printf("mutex unlocked %d. err=%d\n", (int)arg, err);
343 err = fosa_ads_invoke_withdata
344 (whoami, sizeof(whoami), (void *)&reply, &reply_size);
345 printf("who am I, correct?: %d, err=%d\n", reply == (int)arg, err);
353 ///////////////////////////////////////////////////////
354 // 4) Implementation of Application Defined Callbacks
355 ///////////////////////////////////////////////////////
356 static void frsh_callback_init
357 (void *sched_data, void *arg)
359 frsh_sched_data_t *frsh = (frsh_sched_data_t *)sched_data;
361 frsh_signal_t sched_signal = FOSA_SIGNAL_MAX; // HOW TO PUT SIGNALS IF IS OPAQUE??
363 printf ("CALLBACK: %s \n", __func__);
364 printf ("Init args string received: %s \n", (char *)arg);
366 err = fosa_ads_set_handled_signal_set(&sched_signal, 1);
367 printf("set signal set, err=%d\n", err);
370 for (i=0; i<MX_THREADS; i++) {
371 frsh->array_prio[i] = 0;
372 frsh->array_status[i] = 0;
376 static void frsh_callback_new_thread
378 frsh_thread_id_t thread,
379 fosa_ads_actions_t *actions,
380 struct timespec *current_time)
383 unsigned int i, index;
384 frsh_sched_data_t *frsh = (frsh_sched_data_t *)sched_data;
385 appsched_params_t params;
388 printf ("CALLBACK: %s \n", __func__);
391 for (i=0; i<MX_THREADS; i++) {
392 if (frsh->array_status[i] == 0) {
398 if (index == MX_THREADS) {
399 err = fosa_adsactions_add_reject(actions, thread);
402 // Get the priority for the new thread
403 size = sizeof(params);
404 err = fosa_ads_get_appsched_params(thread, (void *)¶ms, &size);
407 frsh->array_prio[index] = params.prio;
408 frsh->array_status[index] = 1;
412 static void frsh_callback_thread_terminate
414 frsh_thread_id_t thread,
415 fosa_ads_actions_t *actions,
416 struct timespec *current_time)
418 struct timespec at_time;
421 printf ("CALLBACK: %s \n", __func__);
423 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &at_time);
424 printf("current time sec=%d nsec=%d\n", at_time.tv_sec, at_time.tv_nsec);
425 at_time.tv_sec = at_time.tv_sec + 1;
427 err = fosa_adsactions_add_timeout(actions, FOSA_CLOCK_REALTIME, &at_time);
428 printf("put a timeout of one second, err=%d\n", err);
432 static void frsh_callback_thread_ready
434 frsh_thread_id_t thread,
435 fosa_ads_actions_t *actions,
436 struct timespec *current_time)
438 printf ("CALLBACK: %s \n", __func__);
441 static void frsh_callback_thread_block
443 frsh_thread_id_t thread,
444 fosa_ads_actions_t *actions,
445 struct timespec *current_time)
448 struct timespec at_time;
450 printf ("CALLBACK: %s \n", __func__);
452 fosa_clock_get_time(FOSA_CLOCK_REALTIME, &at_time);
453 printf("current time sec=%d nsec=%d\n", at_time.tv_sec, at_time.tv_nsec);
454 at_time.tv_sec = at_time.tv_sec + 1;
456 err = fosa_adsactions_add_timeout(actions, FOSA_CLOCK_REALTIME, &at_time);
457 printf("put a timeout of one second, err=%d\n", err);
461 static void frsh_callback_change_sched_param_thread
463 frsh_thread_id_t thread,
464 fosa_ads_actions_t *actions,
465 struct timespec *current_time)
467 printf ("CALLBACK: %s \n", __func__);
468 // HOW DO I KNOW THE REASON IS SETPRIO OR SETSCHEDPARAMS????
471 static void frsh_callback_explicit_call_with_data
473 frsh_thread_id_t thread,
478 fosa_ads_actions_t *actions,
479 struct timespec *current_time)
481 printf ("CALLBACK: %s \n", __func__);
482 printf ("received command: %s \n", (char *)msg);
483 *((int *)reply) = (int)thread;
486 static void frsh_callback_notification_for_thread
488 frsh_thread_id_t thread,
489 fosa_clock_id_t clock,
490 fosa_ads_actions_t *actions,
491 struct timespec *current_time)
493 printf ("CALLBACK: %s \n", __func__);
496 static void frsh_callback_timeout // WHY NOT WATCHDOG????
498 fosa_ads_actions_t *actions,
499 struct timespec *current_time) // WHY IS IN OUT and not IN???
501 printf ("CALLBACK: %s \n", __func__);
502 printf("current time sec=%d nsec=%d\n",
503 current_time->tv_sec, current_time->tv_nsec);
506 static void frsh_callback_signal
508 frsh_signal_t signal,
509 frsh_signal_info_t siginfo, // HOW DO I KNOW THE ORIGIN (see signal_info type)
510 fosa_ads_actions_t *actions,
511 struct timespec *current_time)
514 signal_action_t *signal_action = (signal_action_t *)siginfo.sival_ptr;
515 frsh_sched_data_t *frsh = (frsh_sched_data_t *)sched_data;
517 printf ("CALLBACK: %s \n", __func__);
519 if (signal_action->command == SUSPEND) {
520 err = fosa_adsactions_add_suspend(actions, signal_action->thread_id);
521 printf("suspending thread 1 , err=%d\n", err);
524 err = fosa_adsactions_add_activate
525 (actions, signal_action->thread_id, frsh->array_prio[0]);
526 printf("activating thread 1, err=%d\n", err);
531 static void frsh_callback_appsched_error
533 frsh_thread_id_t thread,
534 fosa_ads_error_cause_t cause,
535 fosa_ads_actions_t *actions)
537 printf ("CALLBACK: %s \n", __func__);