]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_marte_os/tests/test_fosa_ads/test_fosa_ads.c
Updating header text in FOSA files for the incoming final project
[frescor/fosa.git] / src_marte_os / tests / test_fosa_ads / test_fosa_ads.c
1 // -----------------------------------------------------------------------
2 //  Copyright (C) 2006 - 2009 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 #include <stdio.h>  // for printf
57 #include <string.h> // for strlen, strncpy
58 #include <unistd.h> // for sleep
59 #include <time.h> // for nanosleep
60
61
62 // TODO: use #include <assert.h> when it works for all architectures
63 #include <stdlib.h> // for exit in assert
64
65 #include "fosa.h"
66
67 static void inline assert(expression)
68 {
69     if (!expression) {
70         printe(__FILE__":%u: failed assertion.\n", __LINE__);
71         exit (-1);
72     }
73 }
74
75 ///////////////////////////////////////////////////////
76 //  0) Function prototypes
77 ///////////////////////////////////////////////////////
78
79 static void *thread_code(void *arg);
80
81 static void fosa_callback_init
82                 (void *sched_data, void *arg);
83
84 static void fosa_callback_new_thread
85                 (void *sched_data,
86                  fosa_thread_id_t thread,
87                  fosa_ads_actions_t *actions,
88                  fosa_abs_time_t *current_time);
89
90 static void fosa_callback_thread_terminate
91                 (void *sched_data,
92                  fosa_thread_id_t thread,
93                  fosa_ads_actions_t *actions,
94                  fosa_abs_time_t *current_time);
95
96 static void fosa_callback_thread_ready
97                 (void *sched_data,
98                  fosa_thread_id_t thread,
99                  fosa_ads_actions_t *actions,
100                  fosa_abs_time_t *current_time);
101
102 static void fosa_callback_thread_block
103                 (void *sched_data,
104                  fosa_thread_id_t thread,
105                  fosa_ads_actions_t *actions,
106                  fosa_abs_time_t *current_time);
107
108 static void fosa_callback_change_sched_param_thread
109                 (void *sched_data,
110                  fosa_thread_id_t thread,
111                  fosa_ads_actions_t *actions,
112                  fosa_abs_time_t *current_time);
113
114 static void fosa_callback_explicit_call_with_data
115                 (void *sched_data,
116                  fosa_thread_id_t thread,
117                  const void * msg,
118                  size_t msg_size,
119                  void *reply,
120                  size_t *reply_size,
121                  fosa_ads_actions_t *actions,
122                  fosa_abs_time_t *current_time);
123
124 static void fosa_callback_notification_for_thread
125                 (void *sched_data,
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);
130
131 static void fosa_callback_timeout
132                 (void *sched_data,
133                  fosa_ads_actions_t *actions,
134                  fosa_abs_time_t *current_time);
135
136 static void fosa_callback_signal
137                 (void *sched_data,
138                  fosa_signal_t signal,
139                  fosa_signal_info_t siginfo,
140                  fosa_ads_actions_t *actions,
141                  fosa_abs_time_t *current_time);
142
143 static void fosa_callback_appsched_error
144                 (void *sched_data,
145                  fosa_thread_id_t thread,
146                  fosa_ads_error_cause_t cause,
147                  fosa_ads_actions_t *actions);
148
149 ///////////////////////////////////////////////////////
150 //  1) Types, Module variables and Constants
151 ///////////////////////////////////////////////////////
152
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,
165 };
166
167 static fosa_mutex_t lock;
168
169 const unsigned int MX_INIT_ARGS_STRING = 30;
170 const unsigned int MX_PRIO = 20;
171 #define MX_THREADS  2
172
173 // general control structure for the scheduler
174 typedef struct {
175     fosa_ads_urgency_t array_prio[MX_THREADS];
176     int array_status[MX_THREADS];
177 } fosa_sched_data_t;
178
179 typedef struct {
180     fosa_ads_urgency_t prio;
181 } appsched_params_t;
182
183 typedef enum {
184     ACTIVATE,
185     SUSPEND,
186     CAUSE_ERROR
187 } command_t;
188
189 typedef struct {
190     fosa_thread_id_t thread_id;
191     command_t command;
192 } signal_action_t;
193
194 ///////////////////////////////////////////////////////
195 //  2) Main program
196 ///////////////////////////////////////////////////////
197
198 int main () {
199
200     int err;
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;
204     bool is_appsched;
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;
210
211
212     err = fosa_thread_set_prio (fosa_thread_self(), MX_PRIO + 1);
213     printf("set main to highest priority, err=%d\n", err);
214     assert(err == 0);
215
216     err = fosa_mutex_init(&lock, MX_PRIO);
217     printf("mutex initialized with ceiling %d. err=%d\n", MX_PRIO, err);
218     assert(err == 0);
219
220     //////////////////////////////////
221     //  2a) Create the scheduler
222     //////////////////////////////////
223
224     printf("--------------------------------------------------\n");
225     printf("2a) Create the scheduler\n");
226
227     strncpy(init_args_string, "Hello Scheduler!!", MX_INIT_ARGS_STRING);
228     init_args_string[MX_INIT_ARGS_STRING] = '\0';
229
230     err = fosa_ads_scheduler_create
231             (&scheduler_ops,
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);
236     assert(err == 0);
237
238     //////////////////////////////////////////////////////////////
239     //  2b) Create two application scheduled threads
240     //////////////////////////////////////////////////////////////
241
242     printf("--------------------------------------------------\n");
243     printf("2b) Create two application scheduled threads\n");
244
245     err = fosa_thread_attr_init(&th_attr);
246     printf("thread attributes object initialized, err=%d\n", err);
247     assert(err == 0);
248
249     err = fosa_thread_attr_set_stacksize(&th_attr,40000);
250     printf("thread attr set stack size to 40000, err=%d\n", err);
251     assert(err == 0);
252
253     err = fosa_thread_attr_set_prio(&th_attr, MX_PRIO - 1);
254     printf("thread attr set prio to 10, err=%d\n",err);
255     assert(err == 0);
256
257     err = fosa_thread_attr_set_appscheduled(&th_attr, true);
258     printf("thread attr set appscheduled, err=%d\n", err);
259     assert(err == 0);
260
261     err = fosa_thread_attr_get_appscheduled(&th_attr, &is_appsched);
262     printf("thread attr get appscheduled=%d, err=%d\n",is_appsched, err);
263     assert(err == 0);
264
265     params.prio = 10;
266     err = fosa_thread_attr_set_appsched_params
267             (&th_attr, (void *)&params, sizeof(params));
268     printf("thread attr set params prio=%d, err=%d\n", params.prio, err);
269     assert(err == 0);
270
271     // create thread 1
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);
274     assert(err == 0);
275
276     params.prio = 15;
277     err = fosa_thread_attr_set_appsched_params
278             (&th_attr, (void *)&params, sizeof(params));
279     printf("thread attr set params prio=%d, err=%d\n", params.prio, err);
280     assert(err == 0);
281
282     // create thread 2
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);
285     assert(err == 0);
286
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);
291
292     err = fosa_thread_attr_destroy(&th_attr);
293     printf("thread attributes object destroyed, err=%d\n",err);
294     assert(err == 0);
295
296     sleep (5);
297
298     //////////////////////////////////////////////////////////////
299     //  2c) Change appsched params
300     //////////////////////////////////////////////////////////////
301     printf("--------------------------------------------------\n");
302     printf("2c) Change appsched params\n");
303
304     err = fosa_thread_set_prio(tid1,14);
305     printf("priority of thread 1 set to 14, err=%d\n", err);
306     assert(err == 0);
307
308     sleep (1);
309
310     params.prio = MX_PRIO - 5;
311     err = fosa_ads_set_appsched_params(tid2, (void *)&params, sizeof(params));
312     printf("urgency of thread 2 set to %d, err=%d\n", params.prio, err);
313     assert(err == 0);
314
315     sleep (3);
316
317     //////////////////////////////////////////////////////////////
318     //  2d) Signals
319     //////////////////////////////////////////////////////////////
320     printf("--------------------------------------------------\n");
321     printf("2d) Signals\n");
322
323     signal_action.command = SUSPEND;
324     signal_action.thread_id = tid1;
325     timer_info.sival_ptr = (void *)&signal_action;
326
327     err = fosa_timer_create
328           (FOSA_CLOCK_REALTIME, FOSA_SIGNAL_MAX, timer_info, &timerid);
329     printf("timer created, err=%d\n", err);
330     assert(err == 0);
331
332     timerval = fosa_msec_to_rel_time(500);
333
334     err=fosa_rel_timer_arm(timerid, &timerval);
335     printf("suspend thread 1 in 0.5 secs, err=%d\n", err);
336     assert(err == 0);
337
338     sleep (5);
339
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);
343     assert(err == 0);
344
345     sleep (3);
346
347     //////////////////////////////////////////////////////////////
348     //  2e) Cause error
349     //////////////////////////////////////////////////////////////
350     printf("--------------------------------------------------\n");
351     printf("2e) Cause error\n");
352
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);
356     assert(err == 0);
357
358     sleep (3);
359
360     //////////////////////////////////////////////////////////////
361     //  2f) Dettach from application scheduler
362     //////////////////////////////////////////////////////////////
363     printf("--------------------------------------------------\n");
364     printf("2f) Dettach from application scheduler\n");
365
366     err = fosa_ads_set_appscheduled (tid1, false);
367     printf("dettach thread 1, err=%d\n", err);
368     assert(err == 0);
369
370     err = fosa_ads_get_appscheduled (tid1, &is_appsched);
371     printf("thread 1 is dettached? %d, err=%d\n", !is_appsched, err);
372     assert(err == 0);
373
374     err = fosa_ads_get_appscheduled (tid2, &is_appsched);
375     printf("thread 2 is dettached? %d, err=%d\n", !is_appsched, err);
376     assert(err == 0);
377
378     fosa_timer_delete(timerid);
379
380     sleep(1000);
381     return 0;
382 }
383
384 ///////////////////////////////////////////////////////
385 // 3) Threads Code
386 ///////////////////////////////////////////////////////
387
388 static void *thread_code (void * arg)
389 {
390     struct timespec ts = {2, 0};
391     int err, i;
392     char whoami[] = "who am i?";
393     int reply;
394     size_t reply_size;
395     fosa_rel_time_t one_second = fosa_msec_to_rel_time(1000);
396
397     printf("THREAD %d - starts\n", (int)arg);
398     for (i=1;i<50;i++) {
399         nanosleep (&ts, NULL);
400
401         printf("THREAD %d - locking mutex\n", (int)arg);
402         err=fosa_mutex_lock(&lock);
403         assert(err == 0);
404
405         fosa_eat (&one_second);
406
407         printf("THREAD %d - unlocking mutex\n", (int)arg);
408         err=fosa_mutex_unlock(&lock);
409         assert(err == 0);
410
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);
416         if (err != 0) {
417             printf("THREAD %d - bye bye!!\n", (int)arg);
418             pthread_exit (NULL);
419         }
420
421     }
422     return NULL;
423 }
424
425 ///////////////////////////////////////////////////////
426 // 4) Implementation of Application Defined Callbacks
427 ///////////////////////////////////////////////////////
428 static void fosa_callback_init
429         (void *sched_data, void *arg)
430 {
431     fosa_sched_data_t *frsh = (fosa_sched_data_t *)sched_data;
432     int i, err;
433     fosa_signal_t sched_signal = FOSA_SIGNAL_MAX; // HOW TO PUT SIGNALS IF IS OPAQUE??
434
435     printf ("BEGIN CALLBACK: %s \n", __func__);
436     printf ("init args string received: %s \n", (char *)arg);
437
438     err = fosa_ads_set_handled_signal_set(&sched_signal, 1);
439     printf("set signal set, err=%d\n", err);
440     assert(err == 0);
441
442     for (i=0; i<MX_THREADS; i++) {
443         frsh->array_prio[i] = 0;
444         frsh->array_status[i] = 0;
445     }
446     printf ("END CALLBACK: %s \n", __func__);
447 }
448
449 static void fosa_callback_new_thread
450         (void *sched_data,
451          fosa_thread_id_t thread,
452          fosa_ads_actions_t *actions,
453          fosa_abs_time_t *current_time)
454 {
455     int err;
456     unsigned int i, index;
457     fosa_sched_data_t *frsh = (fosa_sched_data_t *)sched_data;
458     appsched_params_t params;
459     size_t size;
460
461     printf ("BEGIN CALLBACK: %s \n", __func__);
462
463     index = MX_THREADS;
464     for (i=0; i<MX_THREADS; i++) {
465         if (frsh->array_status[i] == 0) {
466             index = i;
467             break;
468         }
469     }
470
471     if (index == MX_THREADS) {
472         err = fosa_adsactions_add_reject(actions, thread);
473         assert(err == 0);
474     } else {
475         // Get the priority for the new thread
476         size = sizeof(params);
477         err = fosa_ads_get_appsched_params(thread, (void *)&params, &size);
478         assert(err == 0);
479
480         frsh->array_prio[index] = params.prio;
481         frsh->array_status[index] = 1;
482     }
483     printf ("END CALLBACK: %s \n", __func__);
484 }
485
486 static void fosa_callback_thread_terminate
487         (void *sched_data,
488          fosa_thread_id_t thread,
489          fosa_ads_actions_t *actions,
490          fosa_abs_time_t *current_time)
491 {
492     fosa_abs_time_t at_time;
493     int err;
494
495     printf ("BEGIN CALLBACK: %s \n", __func__);
496
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) );
500
501
502     err = fosa_adsactions_add_timeout(actions, FOSA_CLOCK_REALTIME, &at_time);
503     printf("put a timeout of one second, err=%d\n", err);
504     assert(err == 0);
505     printf ("END CALLBACK: %s \n", __func__);
506 }
507
508 static void fosa_callback_thread_ready
509         (void *sched_data,
510          fosa_thread_id_t thread,
511          fosa_ads_actions_t *actions,
512          fosa_abs_time_t *current_time)
513 {
514     printf ("BEGIN CALLBACK: %s \n", __func__);
515     printf ("END CALLBACK: %s \n", __func__);
516 }
517
518 static void fosa_callback_thread_block
519         (void *sched_data,
520          fosa_thread_id_t thread,
521          fosa_ads_actions_t *actions,
522          fosa_abs_time_t *current_time)
523 {
524     int err;
525     fosa_abs_time_t at_time;
526
527     printf ("BEGIN CALLBACK: %s \n", __func__);
528
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) );
532
533     err = fosa_adsactions_add_timeout(actions, FOSA_CLOCK_REALTIME, &at_time);
534     printf("put a timeout of one second, err=%d\n", err);
535     assert(err == 0);
536     printf ("END CALLBACK: %s \n", __func__);
537 }
538
539 static void fosa_callback_change_sched_param_thread
540         (void *sched_data,
541          fosa_thread_id_t thread,
542          fosa_ads_actions_t *actions,
543          fosa_abs_time_t *current_time)
544 {
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__);
548 }
549
550 static void fosa_callback_explicit_call_with_data
551         (void *sched_data,
552          fosa_thread_id_t thread,
553          const void * msg,
554          size_t msg_size,
555          void *reply,
556          size_t *reply_size,
557          fosa_ads_actions_t *actions,
558          fosa_abs_time_t *current_time)
559 {
560     printf ("BEGIN CALLBACK: %s \n", __func__);
561     *((int *)reply) = (int)thread;
562     printf ("received command: %s , answer %d \n", (char *)msg,
563       *((int *)reply));
564     printf ("END CALLBACK: %s \n", __func__);
565 }
566
567 static void fosa_callback_notification_for_thread
568         (void *sched_data,
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)
573 {
574     printf ("BEGIN CALLBACK: %s \n", __func__);
575     printf ("END CALLBACK: %s \n", __func__);
576 }
577
578 static void fosa_callback_timeout // WHY NOT WATCHDOG????
579         (void *sched_data,
580          fosa_ads_actions_t *actions,
581          fosa_abs_time_t  *current_time) // WHY IS IN OUT and not IN???
582 {
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__);
586 }
587
588 static void fosa_callback_signal
589         (void *sched_data,
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)
594 {
595     int err;
596     signal_action_t *signal_action = (signal_action_t *)siginfo.sival_ptr;
597     fosa_sched_data_t *frsh = (fosa_sched_data_t *)sched_data;
598
599     printf ("BEGIN CALLBACK: %s \n", __func__);
600
601     switch (signal_action->command) {
602         case SUSPEND:
603             err=fosa_adsactions_add_suspend(actions, signal_action->thread_id);
604             printf("suspending thread 1 , err=%d\n", err);
605             assert(err == 0);
606             break;
607         case ACTIVATE:
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);
611             assert(err == 0);
612             break;
613         case CAUSE_ERROR:
614             // cause an error by overwriting actions with 666 ;D
615             *(int *)actions = 666;
616             err = 666;
617             printf("causing an error, err=%d\n", err);
618             break;
619     }
620     printf ("END CALLBACK: %s \n", __func__);
621 }
622
623 static void fosa_callback_appsched_error
624         (void *sched_data,
625          fosa_thread_id_t thread,
626          fosa_ads_error_cause_t cause,
627          fosa_ads_actions_t *actions)
628 {
629     printf ("BEGIN CALLBACK: %s \n", __func__);
630     printf ("END CALLBACK: %s \n", __func__);
631 }