]> rtime.felk.cvut.cz Git - frescor/fosa.git/blobdiff - src_marte_os/tests/test_fosa_ads/test_fosa_ads.c
Renaming fosa/src_marte to fosa/src_marte_os
[frescor/fosa.git] / src_marte_os / tests / test_fosa_ads / test_fosa_ads.c
diff --git a/src_marte_os/tests/test_fosa_ads/test_fosa_ads.c b/src_marte_os/tests/test_fosa_ads/test_fosa_ads.c
new file mode 100644 (file)
index 0000000..6a5940f
--- /dev/null
@@ -0,0 +1,631 @@
+// -----------------------------------------------------------------------
+//  Copyright (C) 2006 - 2008 FRESCOR consortium partners:
+//
+//    Universidad de Cantabria,              SPAIN
+//    University of York,                    UK
+//    Scuola Superiore Sant'Anna,            ITALY
+//    Kaiserslautern University,             GERMANY
+//    Univ. Politécnica  Valencia,           SPAIN
+//    Czech Technical University in Prague,  CZECH REPUBLIC
+//    ENEA                                   SWEDEN
+//    Thales Communication S.A.              FRANCE
+//    Visual Tools S.A.                      SPAIN
+//    Rapita Systems Ltd                     UK
+//    Evidence                               ITALY
+//
+//    See http://www.frescor.org for a link to partners' websites
+//
+//           FRESCOR project (FP6/2005/IST/5-034026) is funded
+//        in part by the European Union Sixth Framework Programme
+//        The European Union is not liable of any use that may be
+//        made of this code.
+//
+//
+//  based on previous work (FSF) done in the FIRST project
+//
+//   Copyright (C) 2005  Mälardalen University, SWEDEN
+//                       Scuola Superiore S.Anna, ITALY
+//                       Universidad de Cantabria, SPAIN
+//                       University of York, UK
+//
+//   FSF API web pages: http://marte.unican.es/fsf/docs
+//                      http://shark.sssup.it/contrib/first/docs/
+//
+//   This file is part of FOSA (Frsh Operating System Adaption)
+//
+//  FOSA is free software; you can redistribute it and/or modify it
+//  under terms of the GNU General Public License as published by the
+//  Free Software Foundation; either version 2, or (at your option) any
+//  later version.  FOSA is distributed in the hope that it will be
+//  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+//  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+//  General Public License for more details. You should have received a
+//  copy of the GNU General Public License along with FOSA; see file
+//  COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
+//  Cambridge, MA 02139, USA.
+//
+//  As a special exception, including FOSA header files in a file,
+//  instantiating FOSA generics or templates, or linking other files
+//  with FOSA objects to produce an executable application, does not
+//  by itself cause the resulting executable application to be covered
+//  by the GNU General Public License. This exception does not
+//  however invalidate any other reasons why the executable file might be
+//  covered by the GNU Public License.
+// -----------------------------------------------------------------------
+
+#include <stdio.h>  // for printf
+#include <string.h> // for strlen, strncpy
+#include <unistd.h> // for sleep
+#include <time.h> // for nanosleep
+
+
+// TODO: use #include <assert.h> when it works for all architectures
+#include <stdlib.h> // for exit in assert
+
+#include "fosa.h"
+
+static void inline assert(expression)
+{
+    if (!expression) {
+        printe(__FILE__":%u: failed assertion.\n", __LINE__);
+        exit (-1);
+    }
+}
+
+///////////////////////////////////////////////////////
+//  0) Function prototypes
+///////////////////////////////////////////////////////
+
+static void *thread_code(void *arg);
+
+static void fosa_callback_init
+                (void *sched_data, void *arg);
+
+static void fosa_callback_new_thread
+                (void *sched_data,
+                 fosa_thread_id_t thread,
+                 fosa_ads_actions_t *actions,
+                 fosa_abs_time_t *current_time);
+
+static void fosa_callback_thread_terminate
+                (void *sched_data,
+                 fosa_thread_id_t thread,
+                 fosa_ads_actions_t *actions,
+                 fosa_abs_time_t *current_time);
+
+static void fosa_callback_thread_ready
+                (void *sched_data,
+                 fosa_thread_id_t thread,
+                 fosa_ads_actions_t *actions,
+                 fosa_abs_time_t *current_time);
+
+static void fosa_callback_thread_block
+                (void *sched_data,
+                 fosa_thread_id_t thread,
+                 fosa_ads_actions_t *actions,
+                 fosa_abs_time_t *current_time);
+
+static void fosa_callback_change_sched_param_thread
+                (void *sched_data,
+                 fosa_thread_id_t thread,
+                 fosa_ads_actions_t *actions,
+                 fosa_abs_time_t *current_time);
+
+static void fosa_callback_explicit_call_with_data
+                (void *sched_data,
+                 fosa_thread_id_t thread,
+                 const void * msg,
+                 size_t msg_size,
+                 void *reply,
+                 size_t *reply_size,
+                 fosa_ads_actions_t *actions,
+                 fosa_abs_time_t *current_time);
+
+static void fosa_callback_notification_for_thread
+                (void *sched_data,
+                 fosa_thread_id_t thread,
+                 fosa_clock_id_t clock,
+                 fosa_ads_actions_t *actions,
+                 fosa_abs_time_t *current_time);
+
+static void fosa_callback_timeout
+                (void *sched_data,
+                 fosa_ads_actions_t *actions,
+                 fosa_abs_time_t *current_time);
+
+static void fosa_callback_signal
+                (void *sched_data,
+                 fosa_signal_t signal,
+                 fosa_signal_info_t siginfo,
+                 fosa_ads_actions_t *actions,
+                 fosa_abs_time_t *current_time);
+
+static void fosa_callback_appsched_error
+                (void *sched_data,
+                 fosa_thread_id_t thread,
+                 fosa_ads_error_cause_t cause,
+                 fosa_ads_actions_t *actions);
+
+///////////////////////////////////////////////////////
+//  1) Types, Module variables and Constants
+///////////////////////////////////////////////////////
+
+static fosa_ads_scheduler_ops_t scheduler_ops = {
+    .init = fosa_callback_init,
+    .new_thread = fosa_callback_new_thread,
+    .thread_terminate = fosa_callback_thread_terminate,
+    .thread_ready = fosa_callback_thread_ready,
+    .thread_block = fosa_callback_thread_block,
+    .change_sched_param_thread = fosa_callback_change_sched_param_thread,
+    .explicit_call_with_data = fosa_callback_explicit_call_with_data,
+    .notification_for_thread = fosa_callback_notification_for_thread,
+    .timeout = fosa_callback_timeout,
+    .signal = fosa_callback_signal,
+    .appsched_error = fosa_callback_appsched_error,
+};
+
+static fosa_mutex_t lock;
+
+const unsigned int MX_INIT_ARGS_STRING = 30;
+const unsigned int MX_PRIO = 20;
+#define MX_THREADS  2
+
+// general control structure for the scheduler
+typedef struct {
+    fosa_ads_urgency_t array_prio[MX_THREADS];
+    int array_status[MX_THREADS];
+} fosa_sched_data_t;
+
+typedef struct {
+    fosa_ads_urgency_t prio;
+} appsched_params_t;
+
+typedef enum {
+    ACTIVATE,
+    SUSPEND,
+    CAUSE_ERROR
+} command_t;
+
+typedef struct {
+    fosa_thread_id_t thread_id;
+    command_t command;
+} signal_action_t;
+
+///////////////////////////////////////////////////////
+//  2) Main program
+///////////////////////////////////////////////////////
+
+int main () {
+
+    int err;
+    char init_args_string[MX_INIT_ARGS_STRING + 1];
+    fosa_thread_id_t tid1, tid2, tid3;
+    fosa_thread_attr_t th_attr;
+    bool is_appsched;
+    appsched_params_t params;
+    fosa_signal_info_t timer_info;
+    fosa_timer_id_t timerid;
+    fosa_rel_time_t timerval;
+    signal_action_t signal_action;
+
+
+    err = fosa_thread_set_prio (fosa_thread_self(), MX_PRIO + 1);
+    printf("set main to highest priority, err=%d\n", err);
+    assert(err == 0);
+
+    err = fosa_mutex_init(&lock, MX_PRIO);
+    printf("mutex initialized with ceiling %d. err=%d\n", MX_PRIO, err);
+    assert(err == 0);
+
+    //////////////////////////////////
+    //  2a) Create the scheduler
+    //////////////////////////////////
+
+    printf("--------------------------------------------------\n");
+    printf("2a) Create the scheduler\n");
+
+    strncpy(init_args_string, "Hello Scheduler!!", MX_INIT_ARGS_STRING);
+    init_args_string[MX_INIT_ARGS_STRING] = '\0';
+
+    err = fosa_ads_scheduler_create
+            (&scheduler_ops,
+             sizeof(fosa_sched_data_t),
+             init_args_string, // INIT IS CALLED INMEDIATELY??!!!
+             strlen(init_args_string) + 1);
+    printf("scheduler created, err=%d\n", err);
+    assert(err == 0);
+
+    //////////////////////////////////////////////////////////////
+    //  2b) Create two application scheduled threads
+    //////////////////////////////////////////////////////////////
+
+    printf("--------------------------------------------------\n");
+    printf("2b) Create two application scheduled threads\n");
+
+    err = fosa_thread_attr_init(&th_attr);
+    printf("thread attributes object initialized, err=%d\n", err);
+    assert(err == 0);
+
+    err = fosa_thread_attr_set_stacksize(&th_attr,40000);
+    printf("thread attr set stack size to 40000, err=%d\n", err);
+    assert(err == 0);
+
+    err = fosa_thread_attr_set_prio(&th_attr, MX_PRIO - 1);
+    printf("thread attr set prio to 10, err=%d\n",err);
+    assert(err == 0);
+
+    err = fosa_thread_attr_set_appscheduled(&th_attr, true);
+    printf("thread attr set appscheduled, err=%d\n", err);
+    assert(err == 0);
+
+    err = fosa_thread_attr_get_appscheduled(&th_attr, &is_appsched);
+    printf("thread attr get appscheduled=%d, err=%d\n",is_appsched, err);
+    assert(err == 0);
+
+    params.prio = 10;
+    err = fosa_thread_attr_set_appsched_params
+            (&th_attr, (void *)&params, sizeof(params));
+    printf("thread attr set params prio=%d, err=%d\n", params.prio, err);
+    assert(err == 0);
+
+    // create thread 1
+    err = fosa_thread_create (&tid1, &th_attr, thread_code, (void *)1);
+    printf("created thread 1 with prio=%d, err=%d\n", params.prio, err);
+    assert(err == 0);
+
+    params.prio = 15;
+    err = fosa_thread_attr_set_appsched_params
+            (&th_attr, (void *)&params, sizeof(params));
+    printf("thread attr set params prio=%d, err=%d\n", params.prio, err);
+    assert(err == 0);
+
+    // create thread 2
+    err = fosa_thread_create (&tid2, &th_attr, thread_code, (void *)2);
+    printf("created thread 2 with prio=%d, err=%d\n",params.prio, err);
+    assert(err == 0);
+
+    // create thread 3 - should be rejected
+    err = fosa_thread_create (&tid3, &th_attr, thread_code, (void *)3);
+    printf("created thread 3 (rejected=%d), err=%d\n",
+            (err == FOSA_EREJECT), err);
+
+    err = fosa_thread_attr_destroy(&th_attr);
+    printf("thread attributes object destroyed, err=%d\n",err);
+    assert(err == 0);
+
+    sleep (5);
+
+    //////////////////////////////////////////////////////////////
+    //  2c) Change appsched params
+    //////////////////////////////////////////////////////////////
+    printf("--------------------------------------------------\n");
+    printf("2c) Change appsched params\n");
+
+    err = fosa_thread_set_prio(tid1,14);
+    printf("priority of thread 1 set to 14, err=%d\n", err);
+    assert(err == 0);
+
+    sleep (1);
+
+    params.prio = MX_PRIO - 5;
+    err = fosa_ads_set_appsched_params(tid2, (void *)&params, sizeof(params));
+    printf("urgency of thread 2 set to %d, err=%d\n", params.prio, err);
+    assert(err == 0);
+
+    sleep (3);
+
+    //////////////////////////////////////////////////////////////
+    //  2d) Signals
+    //////////////////////////////////////////////////////////////
+    printf("--------------------------------------------------\n");
+    printf("2d) Signals\n");
+
+    signal_action.command = SUSPEND;
+    signal_action.thread_id = tid1;
+    timer_info.sival_ptr = (void *)&signal_action;
+
+    err = fosa_timer_create
+          (FOSA_CLOCK_REALTIME, FOSA_SIGNAL_MAX, timer_info, &timerid);
+    printf("timer created, err=%d\n", err);
+    assert(err == 0);
+
+    timerval = fosa_msec_to_rel_time(500);
+
+    err=fosa_rel_timer_arm(timerid, &timerval);
+    printf("suspend thread 1 in 0.5 secs, err=%d\n", err);
+    assert(err == 0);
+
+    sleep (5);
+
+    signal_action.command = ACTIVATE;
+    err=fosa_rel_timer_arm(timerid, &timerval);
+    printf("activate thread 1 in 0.5 secs, err=%d\n", err);
+    assert(err == 0);
+
+    sleep (3);
+
+    //////////////////////////////////////////////////////////////
+    //  2e) Cause error
+    //////////////////////////////////////////////////////////////
+    printf("--------------------------------------------------\n");
+    printf("2e) Cause error\n");
+
+    signal_action.command = CAUSE_ERROR;
+    err=fosa_rel_timer_arm(timerid, &timerval);
+    printf("causing an ERROR callback in 0.5 secs, err=%d\n", err);
+    assert(err == 0);
+
+    sleep (3);
+
+    //////////////////////////////////////////////////////////////
+    //  2f) Dettach from application scheduler
+    //////////////////////////////////////////////////////////////
+    printf("--------------------------------------------------\n");
+    printf("2f) Dettach from application scheduler\n");
+
+    err = fosa_ads_set_appscheduled (tid1, false);
+    printf("dettach thread 1, err=%d\n", err);
+    assert(err == 0);
+
+    err = fosa_ads_get_appscheduled (tid1, &is_appsched);
+    printf("thread 1 is dettached? %d, err=%d\n", !is_appsched, err);
+    assert(err == 0);
+
+    err = fosa_ads_get_appscheduled (tid2, &is_appsched);
+    printf("thread 2 is dettached? %d, err=%d\n", !is_appsched, err);
+    assert(err == 0);
+
+    fosa_timer_delete(timerid);
+
+    sleep(1000);
+    return 0;
+}
+
+///////////////////////////////////////////////////////
+// 3) Threads Code
+///////////////////////////////////////////////////////
+
+static void *thread_code (void * arg)
+{
+    struct timespec ts = {2, 0};
+    int err, i;
+    char whoami[] = "who am i?";
+    int reply;
+    size_t reply_size;
+    fosa_rel_time_t one_second = fosa_msec_to_rel_time(1000);
+
+    printf("THREAD %d - starts\n", (int)arg);
+    for (i=1;i<50;i++) {
+        nanosleep (&ts, NULL);
+
+        printf("THREAD %d - locking mutex\n", (int)arg);
+        err=fosa_mutex_lock(&lock);
+        assert(err == 0);
+
+        fosa_eat (&one_second);
+
+        printf("THREAD %d - unlocking mutex\n", (int)arg);
+        err=fosa_mutex_unlock(&lock);
+        assert(err == 0);
+
+        printf("THREAD %d - asking with invoke_withdata\n", (int)arg);
+        err = fosa_ads_invoke_withdata
+                (whoami, sizeof(whoami), (void *)&reply, &reply_size);
+        printf("THREAD %d - received reply, correct?: %d, err=%d\n", (int)arg,
+               reply == (int)fosa_thread_self(), err);
+        if (err != 0) {
+            printf("THREAD %d - bye bye!!\n", (int)arg);
+            pthread_exit (NULL);
+        }
+
+    }
+    return NULL;
+}
+
+///////////////////////////////////////////////////////
+// 4) Implementation of Application Defined Callbacks
+///////////////////////////////////////////////////////
+static void fosa_callback_init
+        (void *sched_data, void *arg)
+{
+    fosa_sched_data_t *frsh = (fosa_sched_data_t *)sched_data;
+    int i, err;
+    fosa_signal_t sched_signal = FOSA_SIGNAL_MAX; // HOW TO PUT SIGNALS IF IS OPAQUE??
+
+    printf ("BEGIN CALLBACK: %s \n", __func__);
+    printf ("init args string received: %s \n", (char *)arg);
+
+    err = fosa_ads_set_handled_signal_set(&sched_signal, 1);
+    printf("set signal set, err=%d\n", err);
+    assert(err == 0);
+
+    for (i=0; i<MX_THREADS; i++) {
+        frsh->array_prio[i] = 0;
+        frsh->array_status[i] = 0;
+    }
+    printf ("END CALLBACK: %s \n", __func__);
+}
+
+static void fosa_callback_new_thread
+        (void *sched_data,
+         fosa_thread_id_t thread,
+         fosa_ads_actions_t *actions,
+         fosa_abs_time_t *current_time)
+{
+    int err;
+    unsigned int i, index;
+    fosa_sched_data_t *frsh = (fosa_sched_data_t *)sched_data;
+    appsched_params_t params;
+    size_t size;
+
+    printf ("BEGIN CALLBACK: %s \n", __func__);
+
+    index = MX_THREADS;
+    for (i=0; i<MX_THREADS; i++) {
+        if (frsh->array_status[i] == 0) {
+            index = i;
+            break;
+        }
+    }
+
+    if (index == MX_THREADS) {
+        err = fosa_adsactions_add_reject(actions, thread);
+        assert(err == 0);
+    } else {
+        // Get the priority for the new thread
+        size = sizeof(params);
+        err = fosa_ads_get_appsched_params(thread, (void *)&params, &size);
+        assert(err == 0);
+
+        frsh->array_prio[index] = params.prio;
+        frsh->array_status[index] = 1;
+    }
+    printf ("END CALLBACK: %s \n", __func__);
+}
+
+static void fosa_callback_thread_terminate
+        (void *sched_data,
+         fosa_thread_id_t thread,
+         fosa_ads_actions_t *actions,
+         fosa_abs_time_t *current_time)
+{
+    fosa_abs_time_t at_time;
+    int err;
+
+    printf ("BEGIN CALLBACK: %s \n", __func__);
+
+    fosa_clock_get_time(FOSA_CLOCK_REALTIME, &at_time);
+    printf("current time %ld msec\n", fosa_abs_time_to_msec(at_time) );
+    at_time = fosa_abs_time_incr(at_time, fosa_msec_to_rel_time(1000) );
+
+
+    err = fosa_adsactions_add_timeout(actions, FOSA_CLOCK_REALTIME, &at_time);
+    printf("put a timeout of one second, err=%d\n", err);
+    assert(err == 0);
+    printf ("END CALLBACK: %s \n", __func__);
+}
+
+static void fosa_callback_thread_ready
+        (void *sched_data,
+         fosa_thread_id_t thread,
+         fosa_ads_actions_t *actions,
+         fosa_abs_time_t *current_time)
+{
+    printf ("BEGIN CALLBACK: %s \n", __func__);
+    printf ("END CALLBACK: %s \n", __func__);
+}
+
+static void fosa_callback_thread_block
+        (void *sched_data,
+         fosa_thread_id_t thread,
+         fosa_ads_actions_t *actions,
+         fosa_abs_time_t *current_time)
+{
+    int err;
+    fosa_abs_time_t at_time;
+
+    printf ("BEGIN CALLBACK: %s \n", __func__);
+
+    fosa_clock_get_time(FOSA_CLOCK_REALTIME, &at_time);
+    printf("current time %ld msec\n", fosa_abs_time_to_msec(at_time) );
+    at_time = fosa_abs_time_incr(at_time, fosa_msec_to_rel_time(1000) );
+
+    err = fosa_adsactions_add_timeout(actions, FOSA_CLOCK_REALTIME, &at_time);
+    printf("put a timeout of one second, err=%d\n", err);
+    assert(err == 0);
+    printf ("END CALLBACK: %s \n", __func__);
+}
+
+static void fosa_callback_change_sched_param_thread
+        (void *sched_data,
+         fosa_thread_id_t thread,
+         fosa_ads_actions_t *actions,
+         fosa_abs_time_t *current_time)
+{
+    printf ("BEGIN CALLBACK: %s \n", __func__);
+    // HOW DO I KNOW THE REASON IS SETPRIO OR SETSCHEDPARAMS????
+    printf ("END CALLBACK: %s \n", __func__);
+}
+
+static void fosa_callback_explicit_call_with_data
+        (void *sched_data,
+         fosa_thread_id_t thread,
+         const void * msg,
+         size_t msg_size,
+         void *reply,
+         size_t *reply_size,
+         fosa_ads_actions_t *actions,
+         fosa_abs_time_t *current_time)
+{
+    printf ("BEGIN CALLBACK: %s \n", __func__);
+    *((int *)reply) = (int)thread;
+    printf ("received command: %s , answer %d \n", (char *)msg,
+      *((int *)reply));
+    printf ("END CALLBACK: %s \n", __func__);
+}
+
+static void fosa_callback_notification_for_thread
+        (void *sched_data,
+         fosa_thread_id_t thread,
+         fosa_clock_id_t clock,
+         fosa_ads_actions_t *actions,
+         fosa_abs_time_t *current_time)
+{
+    printf ("BEGIN CALLBACK: %s \n", __func__);
+    printf ("END CALLBACK: %s \n", __func__);
+}
+
+static void fosa_callback_timeout // WHY NOT WATCHDOG????
+        (void *sched_data,
+         fosa_ads_actions_t *actions,
+         fosa_abs_time_t  *current_time) // WHY IS IN OUT and not IN???
+{
+    printf ("BEGIN CALLBACK: %s \n", __func__);
+    printf("current time %ld msec", fosa_abs_time_to_msec(*current_time) );
+    printf ("END CALLBACK: %s \n", __func__);
+}
+
+static void fosa_callback_signal
+        (void *sched_data,
+         fosa_signal_t signal,
+         fosa_signal_info_t siginfo, // HOW DO I KNOW THE ORIGIN (see signal_info type)
+         fosa_ads_actions_t *actions,
+         fosa_abs_time_t *current_time)
+{
+    int err;
+    signal_action_t *signal_action = (signal_action_t *)siginfo.sival_ptr;
+    fosa_sched_data_t *frsh = (fosa_sched_data_t *)sched_data;
+
+    printf ("BEGIN CALLBACK: %s \n", __func__);
+
+    switch (signal_action->command) {
+        case SUSPEND:
+            err=fosa_adsactions_add_suspend(actions, signal_action->thread_id);
+            printf("suspending thread 1 , err=%d\n", err);
+            assert(err == 0);
+            break;
+        case ACTIVATE:
+            err = fosa_adsactions_add_activate
+                    (actions, signal_action->thread_id, frsh->array_prio[0]);
+            printf("activating thread 1, err=%d\n", err);
+            assert(err == 0);
+            break;
+        case CAUSE_ERROR:
+            // cause an error by overwriting actions with 666 ;D
+            *(int *)actions = 666;
+            err = 666;
+            printf("causing an error, err=%d\n", err);
+            break;
+    }
+    printf ("END CALLBACK: %s \n", __func__);
+}
+
+static void fosa_callback_appsched_error
+        (void *sched_data,
+         fosa_thread_id_t thread,
+         fosa_ads_error_cause_t cause,
+         fosa_ads_actions_t *actions)
+{
+    printf ("BEGIN CALLBACK: %s \n", __func__);
+    printf ("END CALLBACK: %s \n", __func__);
+}