]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_marte/tests/test_fosa_ads/test_fosa_ads.c
Reorganizing tests files in FOSA
[frescor/fosa.git] / src_marte / tests / test_fosa_ads / test_fosa_ads.c
1 //----------------------------------------------------------------------
2 //  Copyright (C) 2006 - 2007 by the FRESCOR consortium:
3 //
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
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
17 //
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
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 // This file is part of FOSA (Frsh Operating System Abstraction)
32 //
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.
43 //
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 // -----------------------------------------------------------------------
52
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
62
63 // TODO: use #include <assert.h> when it works for all architectures
64 #include <stdlib.h> // for exit in assert
65
66 static void inline assert(expression)
67 {
68     if (!expression) {
69         printe(__FILE__":%u: failed assertion.\n", __LINE__);
70         exit (-1);
71     }
72 }
73
74 ///////////////////////////////////////////////////////
75 //  0) Function prototypes
76 ///////////////////////////////////////////////////////
77
78 static void *thread_code(void *arg);
79
80 static void frsh_callback_init
81                 (void *sched_data, void *arg);
82
83 static void frsh_callback_new_thread
84                 (void *sched_data,
85                  frsh_thread_id_t thread,
86                  fosa_ads_actions_t *actions,
87                  struct timespec *current_time);
88
89 static void frsh_callback_thread_terminate
90                 (void *sched_data,
91                  frsh_thread_id_t thread,
92                  fosa_ads_actions_t *actions,
93                  struct timespec *current_time);
94
95 static void frsh_callback_thread_ready
96                 (void *sched_data,
97                  frsh_thread_id_t thread,
98                  fosa_ads_actions_t *actions,
99                  struct timespec *current_time);
100
101 static void frsh_callback_thread_block
102                 (void *sched_data,
103                  frsh_thread_id_t thread,
104                  fosa_ads_actions_t *actions,
105                  struct timespec *current_time);
106
107 static void frsh_callback_change_sched_param_thread
108                 (void *sched_data,
109                  frsh_thread_id_t thread,
110                  fosa_ads_actions_t *actions,
111                  struct timespec *current_time);
112
113 static void frsh_callback_explicit_call_with_data
114                 (void *sched_data,
115                  frsh_thread_id_t thread,
116                  const void * msg,
117                  size_t msg_size,
118                  void *reply,
119                  size_t *reply_size,
120                  fosa_ads_actions_t *actions,
121                  struct timespec *current_time);
122
123 static void frsh_callback_notification_for_thread
124                 (void *sched_data,
125                  frsh_thread_id_t thread,
126                  fosa_clock_id_t clock,
127                  fosa_ads_actions_t *actions,
128                  struct timespec *current_time);
129
130 static void frsh_callback_timeout
131                 (void *sched_data,
132                  fosa_ads_actions_t *actions,
133                  struct timespec *current_time);
134
135 static void frsh_callback_signal
136                 (void *sched_data,
137                  frsh_signal_t signal,
138                  frsh_signal_info_t siginfo,
139                  fosa_ads_actions_t *actions,
140                  struct timespec *current_time);
141
142 static void frsh_callback_appsched_error
143                 (void *sched_data,
144                  frsh_thread_id_t thread,
145                  fosa_ads_error_cause_t cause,
146                  fosa_ads_actions_t *actions);
147
148 ///////////////////////////////////////////////////////
149 //  1) Types, Module variables and Constants
150 ///////////////////////////////////////////////////////
151
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,
164 };
165
166 static frsh_mutex_t lock;
167
168 const unsigned int MX_INIT_ARGS_STRING = 30;
169 const unsigned int MX_PRIO = 20;
170 #define MX_THREADS  2
171
172 // general control structure for the scheduler
173 typedef struct {
174     fosa_ads_urgency_t array_prio[MX_THREADS];
175     int array_status[MX_THREADS];
176 } frsh_sched_data_t;
177
178 typedef struct {
179     fosa_ads_urgency_t prio;
180 } appsched_params_t;
181
182 typedef enum {
183     ACTIVATE,
184     SUSPEND,
185     CAUSE_ERROR
186 } command_t;
187
188 typedef struct {
189     frsh_thread_id_t thread_id;
190     command_t command;
191 } signal_action_t;
192
193 ///////////////////////////////////////////////////////
194 //  2) Main program
195 ///////////////////////////////////////////////////////
196
197 int main () {
198
199     int err;
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;
203     bool is_appsched;
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;
209
210     adjust(); // for function eat
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(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);
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 = frsh_thread_attr_init(&th_attr);
246     printf("thread attributes object initialized, err=%d\n", err);
247     assert(err == 0);
248
249     err = frsh_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 = frsh_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.tv_sec = 0;
333     timerval.tv_nsec = 500000000;
334
335     err=fosa_timer_arm(timerid, false, &timerval);
336     printf("suspend thread 1 in 0.5 secs, err=%d\n", err);
337     assert(err == 0);
338
339     sleep (5);
340
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);
344     assert(err == 0);
345
346     sleep (3);
347
348     //////////////////////////////////////////////////////////////
349     //  2e) Cause error
350     //////////////////////////////////////////////////////////////
351     printf("--------------------------------------------------\n");
352     printf("2e) Cause error\n");
353
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);
357     assert(err == 0);
358
359     sleep (3);
360
361     //////////////////////////////////////////////////////////////
362     //  2f) Dettach from application scheduler
363     //////////////////////////////////////////////////////////////
364     printf("--------------------------------------------------\n");
365     printf("2f) Dettach from application scheduler\n");
366
367     err = fosa_ads_set_appscheduled (tid1, false);
368     printf("dettach thread 1, err=%d\n", err);
369     assert(err == 0);
370
371     err = fosa_ads_get_appscheduled (tid1, &is_appsched);
372     printf("thread 1 is dettached? %d, err=%d\n", !is_appsched, err);
373     assert(err == 0);
374
375     err = fosa_ads_get_appscheduled (tid2, &is_appsched);
376     printf("thread 2 is dettached? %d, err=%d\n", !is_appsched, err);
377     assert(err == 0);
378
379     fosa_timer_delete(timerid);
380
381     sleep(1000);
382     return 0;
383 }
384
385 ///////////////////////////////////////////////////////
386 // 3) Threads Code
387 ///////////////////////////////////////////////////////
388
389 static void *thread_code (void * arg)
390 {
391     struct timespec ts = {2, 0};
392     int err, i;
393     char whoami[] = "who am i?";
394     int reply;
395     size_t reply_size;
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         eat (1.0);
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 frsh_callback_init
429         (void *sched_data, void *arg)
430 {
431     frsh_sched_data_t *frsh = (frsh_sched_data_t *)sched_data;
432     int i, err;
433     frsh_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 frsh_callback_new_thread
450         (void *sched_data,
451          frsh_thread_id_t thread,
452          fosa_ads_actions_t *actions,
453          struct timespec *current_time)
454 {
455     int err;
456     unsigned int i, index;
457     frsh_sched_data_t *frsh = (frsh_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 frsh_callback_thread_terminate
487         (void *sched_data,
488          frsh_thread_id_t thread,
489          fosa_ads_actions_t *actions,
490          struct timespec *current_time)
491 {
492     struct timespec 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 sec=%d nsec=%d\n", at_time.tv_sec, at_time.tv_nsec);
499     at_time.tv_sec = at_time.tv_sec + 1;
500
501     err = fosa_adsactions_add_timeout(actions, FOSA_CLOCK_REALTIME, &at_time);
502     printf("put a timeout of one second, err=%d\n", err);
503     assert(err == 0);
504     printf ("END CALLBACK: %s \n", __func__);
505 }
506
507 static void frsh_callback_thread_ready
508         (void *sched_data,
509          frsh_thread_id_t thread,
510          fosa_ads_actions_t *actions,
511          struct timespec *current_time)
512 {
513     printf ("BEGIN CALLBACK: %s \n", __func__);
514     printf ("END CALLBACK: %s \n", __func__);
515 }
516
517 static void frsh_callback_thread_block
518         (void *sched_data,
519          frsh_thread_id_t thread,
520          fosa_ads_actions_t *actions,
521          struct timespec *current_time)
522 {
523     int err;
524     struct timespec at_time;
525
526     printf ("BEGIN CALLBACK: %s \n", __func__);
527
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;
531
532     err = fosa_adsactions_add_timeout(actions, FOSA_CLOCK_REALTIME, &at_time);
533     printf("put a timeout of one second, err=%d\n", err);
534     assert(err == 0);
535     printf ("END CALLBACK: %s \n", __func__);
536 }
537
538 static void frsh_callback_change_sched_param_thread
539         (void *sched_data,
540          frsh_thread_id_t thread,
541          fosa_ads_actions_t *actions,
542          struct timespec *current_time)
543 {
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__);
547 }
548
549 static void frsh_callback_explicit_call_with_data
550         (void *sched_data,
551          frsh_thread_id_t thread,
552          const void * msg,
553          size_t msg_size,
554          void *reply,
555          size_t *reply_size,
556          fosa_ads_actions_t *actions,
557          struct timespec *current_time)
558 {
559     printf ("BEGIN CALLBACK: %s \n", __func__);
560     *((int *)reply) = (int)thread;
561     printf ("received command: %s , answer %d \n", (char *)msg,
562       *((int *)reply));
563     printf ("END CALLBACK: %s \n", __func__);
564 }
565
566 static void frsh_callback_notification_for_thread
567         (void *sched_data,
568          frsh_thread_id_t thread,
569          fosa_clock_id_t clock,
570          fosa_ads_actions_t *actions,
571          struct timespec *current_time)
572 {
573     printf ("BEGIN CALLBACK: %s \n", __func__);
574     printf ("END CALLBACK: %s \n", __func__);
575 }
576
577 static void frsh_callback_timeout // WHY NOT WATCHDOG????
578         (void *sched_data,
579          fosa_ads_actions_t *actions,
580          struct timespec *current_time) // WHY IS IN OUT and not IN???
581 {
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__);
586 }
587
588 static void frsh_callback_signal
589         (void *sched_data,
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)
594 {
595     int err;
596     signal_action_t *signal_action = (signal_action_t *)siginfo.sival_ptr;
597     frsh_sched_data_t *frsh = (frsh_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             printf("causing an error, err=%d\n", err);
617             break;
618     }
619     printf ("END CALLBACK: %s \n", __func__);
620 }
621
622 static void frsh_callback_appsched_error
623         (void *sched_data,
624          frsh_thread_id_t thread,
625          fosa_ads_error_cause_t cause,
626          fosa_ads_actions_t *actions)
627 {
628     printf ("BEGIN CALLBACK: %s \n", __func__);
629     printf ("END CALLBACK: %s \n", __func__);
630 }