From afc763496b07b75edd4e83eba93435c58d124d65 Mon Sep 17 00:00:00 2001 From: telleriam Date: Wed, 5 Nov 2008 08:35:40 +0000 Subject: [PATCH] Adding FOSA thread groups git-svn-id: http://www.frescor.org/private/svn/frescor/fosa/trunk@1364 35b4ef3e-fd22-0410-ab77-dab3279adceb --- include/fosa.h | 1 + include/fosa_configuration_parameters.h | 7 + include/fosa_opaque_types.h | 17 + include/fosa_thread_groups.h | 208 +++++++++ include/fosa_types.h | 14 + src_marte_os/fosa_thread_groups.c | 216 +++++++++ .../test_clock_and_timers.c | 3 +- .../tests/test_thread_groups/Makefile | 12 + .../test_thread_groups/test_thread_groups.c | 412 ++++++++++++++++++ 9 files changed, 889 insertions(+), 1 deletion(-) create mode 100644 include/fosa_thread_groups.h create mode 100644 src_marte_os/fosa_thread_groups.c create mode 100644 src_marte_os/tests/test_thread_groups/Makefile create mode 100644 src_marte_os/tests/test_thread_groups/test_thread_groups.c diff --git a/include/fosa.h b/include/fosa.h index c508f9e..418bad6 100644 --- a/include/fosa.h +++ b/include/fosa.h @@ -81,6 +81,7 @@ #include "fosa_long_jump.h" #include "fosa_time.h" #include "fosa_platform_values.h" +#include "fosa_thread_groups.h" /** * @defgroup fosa FOSA Private Interfaces diff --git a/include/fosa_configuration_parameters.h b/include/fosa_configuration_parameters.h index 3a1e103..d1f3b0c 100644 --- a/include/fosa_configuration_parameters.h +++ b/include/fosa_configuration_parameters.h @@ -111,6 +111,13 @@ FOSA_CPP_BEGIN_DECLS // The preemption level of the ADS scheduler thread #define FOSA_ADS_SCHEDULER_LEVEL 0xffff + +/****************** + * THREAD GROUPS + ******************/ +#define FOSA_MAX_THREADS_PER_GROUP 5 + + FOSA_CPP_END_DECLS #endif // _FOSA_CONFIG_PARAM_H_ diff --git a/include/fosa_opaque_types.h b/include/fosa_opaque_types.h index 6a0a8d6..a658d5e 100644 --- a/include/fosa_opaque_types.h +++ b/include/fosa_opaque_types.h @@ -138,6 +138,13 @@ typedef pthread_cond_t FOSA_COND_T_OPAQUE; } +/* Thread groups */ +/*****************/ +typedef marte_thread_set_t FOSA_THREAD_GROUP_ID_T_OPAQUE; + +#define FOSA_NULL_THREAD_GROUP_ID_OPAQUE 0 /* In MaRTE-OS thread_set_t are + * pointers */ + /* FOSA errors */ /***************/ /** Not enough memory available **/ @@ -160,6 +167,10 @@ typedef pthread_cond_t FOSA_COND_T_OPAQUE; #define FOSA_ETIMEDOUT ETIMEDOUT +/* Not found in search (non existing thread, thread_group...) */ +#define FOSA_ESRCH ESRCH +#define FOSA_ENOTSUP ENOTSUP + #endif /////////////////////// End of MARTE_OS ///////////////////////////// @@ -204,6 +215,9 @@ typedef int FOSA_SIGNAL_T_OPAQUE; typedef pthread_mutex_t FOSA_MUTEX_T_OPAQUE; #define FOSA_COND_T_OPAQUE pthread_cond_t +/* Thread groups */ +/*****************/ +typedef int FOSA_THREAD_GROUP_ID_T_OPAQUE /* FOSA Errors */ /***************/ @@ -386,6 +400,9 @@ enum _fosa_errors_e { FOSA_ENOMEM = ENOMEM, }; + + + #endif /////////////////////////////////// PARTIKLE END ////////////////////////////////////// diff --git a/include/fosa_thread_groups.h b/include/fosa_thread_groups.h new file mode 100644 index 0000000..05a233b --- /dev/null +++ b/include/fosa_thread_groups.h @@ -0,0 +1,208 @@ +// ----------------------------------------------------------------------- +// 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. +// ----------------------------------------------------------------------- +//fosa_thread_groups.h +//============================================== +// ******** ****** ******** ********** +// **///// /** ** **////// /** /** +// ** /** ** /** /** /** +// ******* /** ** /********* /********** +// **//// /** ** ////////** /**//////** +// ** /** ** /** /** /** +// ** /** ** ******** /** /** +// // /******/ //////// // // +// +// FOSA(Frescor Operating System Adaptation layer) +//================================================ + +#ifndef _FOSA_THREAD_GROUPS_H +#define _FOSA_THREAD_GROUPS_H + +#include "fosa_types.h" +#include "fosa_configuration_parameters.h" + +FOSA_CPP_BEGIN_DECLS + +/** + * @defgroup threadgroups Thread Groups + * @ingroup fosa + * + * This module defines the types and functions to manage thread groups + * and execution clocks attached to them. These functions are used + * for the hierarchical scheduling module of FRSH + * + * @{ + **/ + + + +/** + * fosa_thread_group_create() + * + * Create an empty thread group and return an identifier + * + * This function stores in the variable pointed to by group the + * identifier of a thread group that is created by the function. + * + * Returns 0 if successful; otherwise it returns an error code: + * FOSA_EAGAIN: no resources are currently available to create the + * thread group + * + * Alternatively, in case of error the implementation is allowed to + * notify it to the system console and then terminate the FRSH + * implementation and dependant applications + **/ + +int fosa_thread_group_create(fosa_thread_group_id_t *group); + + +/** + * fosa_thread_group_destroy() + * + * Destroy a thread group + * + * This function destroys the thread group identified by group. The + * threads that were in the group are detached from the group. It is + * an error to use the identifier after this call. The effects of + * using a CPU-time clock associated with the destroyed thread are + * undefined. + * + * Returns 0 if successful; otherwise it returns an error code: + * FOSA_EINVAL: group is invalid + * + * Alternatively, in case of error the implementation is allowed to + * notify it to the system console and then terminate the FRSH + * implementation and dependant applications + **/ + +int fosa_thread_group_destroy(fosa_thread_group_id_t group); + + +/** + * fosa_thread_group_add() + * + * Add a thread to a thread group + * + * This function adds the thread identified with thread_id to the + * thread group identified by group. + * + * Returns 0 if successful; otherwise it returns an error code: + * FOSA_EINVAL: group is invalid + * FOSA_ENOTSUP: thread already a member of some other group + * FOSA_EAGAIN: no resources available to add the new thread + * FOSA_ESRCH: thread_id doesn't identify a valid thread + * + * Alternatively, in case of error the implementation is allowed to + * notify it to the system console and then terminate the FRSH + * implementation and dependant applications + **/ + +int fosa_thread_group_add(fosa_thread_group_id_t group, + fosa_thread_id_t thread_id); + + +/** + * fosa_thread_group_del() + * + * Delete a thread from a thread group + * + * This function deletes the thread identified with thread_id from + * the thread group identified by group. + * + * Returns 0 if successful; otherwise it returns an error code: + * FOSA_EINVAL: group is invalid + * FOSA_EINVAL: thread is not a member of the group + * FOSA_ESRCH: thread_id doesn't identify a valid thread + * + * Alternatively, in case of error the implementation is allowed to + * notify it to the system console and then terminate the FRSH + * implementation and dependant applications + **/ + +int fosa_thread_group_del(fosa_thread_group_id_t group, + fosa_thread_id_t thread_id); + + +/** + * fosa_get_groupcpu_clock() + * + * Get the identifier of a cpu-time clock associated to a thread + * group + * + * This function stores in the variable pointed to by clockid the + * identifier of a cpu-time clock for the thread group specified + * by group. + * + * Returns 0 if successful; otherwise it returns an error code: + * FOSA_EINVAL: the group is invalid + * FOSA_EINVAL: clock_id is a null pointer + * + * Alternatively, in case of error the implementation is allowed to + * notify it to the system console and then terminate the FRSH + * implementation and dependant applications + **/ + +int fosa_get_groupcpu_clock(const fosa_thread_group_id_t group, + fosa_clock_id_t *clock_id); + + + +/*@}*/ + +FOSA_CPP_END_DECLS + + + +#endif + diff --git a/include/fosa_types.h b/include/fosa_types.h index 0ebbe0e..cb7a599 100644 --- a/include/fosa_types.h +++ b/include/fosa_types.h @@ -413,6 +413,20 @@ typedef struct { typedef FOSA_LONG_JUMP_CONTEXT_T_OPAQUE fosa_long_jump_context_t; +/********************* + * THREAD GROUPS + *********************/ +/** + * @addtogroup threadgroups + * + * @{ + **/ +typedef FOSA_THREAD_GROUP_ID_T_OPAQUE fosa_thread_group_id_t; + +//#define FOSA_NULL_THREAD_GROUP_ID FOSA_NULL_THREAD_GROUP_ID_OPAQUE + +/*@}*/ + FOSA_CPP_END_DECLS diff --git a/src_marte_os/fosa_thread_groups.c b/src_marte_os/fosa_thread_groups.c new file mode 100644 index 0000000..68b300a --- /dev/null +++ b/src_marte_os/fosa_thread_groups.c @@ -0,0 +1,216 @@ +// ----------------------------------------------------------------------- +// 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. +// ----------------------------------------------------------------------- +//fosa_thread_groups.c +//============================================== +// ******** ****** ******** ********** +// **///// /** ** **////// /** /** +// ** /** ** /** /** /** +// ******* /** ** /********* /********** +// **//// /** ** ////////** /**//////** +// ** /** ** /** /** /** +// ** /** ** ******** /** /** +// // /******/ //////// // // +// +// FOSA(Frescor Operating System Adaptation layer) +//================================================ + + +#include + +#include "fosa_thread_groups.h" + +/** + * fosa_thread_group_create() + * + * Create an empty thread group and return an identifier + * + * This function stores in the variable pointed to by group the + * identifier of a thread group that is created by the function. + * + * Returns 0 if successful; otherwise it returns an error code: + * FOSA_EAGAIN: no resources are currently available to create the + * thread group + * + * Alternatively, in case of error the implementation is allowed to + * notify it to the system console and then terminate the FRSH + * implementation and dependant applications + **/ + +int fosa_thread_group_create(fosa_thread_group_id_t *group) +{ + int error; + + error = marte_threadset_create( (marte_thread_set_t *) group); + + return error; +} + + +/** + * fosa_thread_group_destroy() + * + * Destroy a thread group + * + * This function destroys the thread group identified by group. The + * threads that were in the group are detached from the group. It is + * an error to use the identifier after this call. The effects of + * using a CPU-time clock associated with the destroyed thread are + * undefined. + * + * Returns 0 if successful; otherwise it returns an error code: + * FOSA_EINVAL: group is invalid + * + * Alternatively, in case of error the implementation is allowed to + * notify it to the system console and then terminate the FRSH + * implementation and dependant applications + **/ +int fosa_thread_group_destroy(fosa_thread_group_id_t group) +{ + int error; + + error = marte_threadset_destroy(group); + + return error; +} + +/** + * fosa_thread_group_add() + * + * Add a thread to a thread group + * + * This function adds the thread identified with thread_id to the + * thread group identified by group. + * + * Returns 0 if successful; otherwise it returns an error code: + * FOSA_EINVAL: group is invalid + * FOSA_ENOTSUP: thread already a member of some other group + * FOSA_EAGAIN: no resources available to add the new thread + * FOSA_ESRCH: thread_id doesn't identify a valid thread + * + * Alternatively, in case of error the implementation is allowed to + * notify it to the system console and then terminate the FRSH + * implementation and dependant applications + **/ + +int fosa_thread_group_add(fosa_thread_group_id_t group, + fosa_thread_id_t thread_id) +{ + int error; + + error = marte_threadset_add(group, thread_id); + + return error; +} + + + +/** + * fosa_thread_group_del() + * + * Delete a thread from a thread group + * + * This function deletes the thread identified with thread_id from + * the thread group identified by group. + * + * Returns 0 if successful; otherwise it returns an error code: + * FOSA_EINVAL: group is invalid + * FOSA_EINVAL: thread is not a member of the group + * FOSA_ESRCH: thread_id doesn't identify a valid thread + * + * Alternatively, in case of error the implementation is allowed to + * notify it to the system console and then terminate the FRSH + * implementation and dependant applications + **/ +int fosa_thread_group_del(fosa_thread_group_id_t group, + fosa_thread_id_t thread_id) +{ + int error; + + error = marte_threadset_del(group, thread_id); + + return error; +} + + +/** + * fosa_get_groupcpu_clock() + * + * Get the identifier of a cpu-time clock associated to a thread + * group + * + * This function stores in the variable pointed to by clockid the + * identifier of a cpu-time clock for the thread group specified + * by group. + * + * Returns 0 if successful; otherwise it returns an error code: + * FOSA_EINVAL: the group is invalid + * FOSA_EINVAL: clock_id is a null pointer + * + * Alternatively, in case of error the implementation is allowed to + * notify it to the system console and then terminate the FRSH + * implementation and dependant applications + **/ +int fosa_get_groupcpu_clock(const fosa_thread_group_id_t group, + fosa_clock_id_t *clock_id) +{ + int error; + + error = marte_getgroupcpuclockid(group, clock_id); + return error; +} + + + + diff --git a/src_marte_os/tests/test_clock_and_timers/test_clock_and_timers.c b/src_marte_os/tests/test_clock_and_timers/test_clock_and_timers.c index b3a00ef..cb3cb2b 100644 --- a/src_marte_os/tests/test_clock_and_timers/test_clock_and_timers.c +++ b/src_marte_os/tests/test_clock_and_timers/test_clock_and_timers.c @@ -62,7 +62,8 @@ // TODO: use #include when it works for all architectures #include // for exit in assert -static void inline assert(expression) + +static void inline asserto(expression) { if (!expression) { printe(__FILE__":%u: failed assertion.\n", __LINE__); diff --git a/src_marte_os/tests/test_thread_groups/Makefile b/src_marte_os/tests/test_thread_groups/Makefile new file mode 100644 index 0000000..529e02a --- /dev/null +++ b/src_marte_os/tests/test_thread_groups/Makefile @@ -0,0 +1,12 @@ +include ../../../config.mk +include ../../../rules.mk + + +test_fosa_long_jump.exe: test_fosa_long_jump.o $(FOSA_PATH)/lib/libfosa_$(PLATFORM).a $(FOSA_PATH)/marte_non_local_jump/non_local_jump.o + $(CC) -L$(FOSA_PATH)/lib $< -lfosa_$(PLATFORM) $(FOSA_PATH)/marte_non_local_jump/non_local_jump.o -o $@ + + +simple_test_non_local_jump.exe: simple_test_non_local_jump.o $(FOSA_PATH)/lib/libfosa_$(PLATFORM).a $(FOSA_PATH)/marte_non_local_jump/non_local_jump.o + $(CC) -L$(FOSA_PATH)/lib $< -lfosa_$(PLATFORM) $(FOSA_PATH)/marte_non_local_jump/non_local_jump.o -o $@ + + diff --git a/src_marte_os/tests/test_thread_groups/test_thread_groups.c b/src_marte_os/tests/test_thread_groups/test_thread_groups.c new file mode 100644 index 0000000..a5755b3 --- /dev/null +++ b/src_marte_os/tests/test_thread_groups/test_thread_groups.c @@ -0,0 +1,412 @@ +// ----------------------------------------------------------------------- +// 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 +#include + +#include +#include // for exit in assert +#include // for memset + +#include "fosa.h" + +/*****************************/ +/* D E F I N I T I O N S */ +/*****************************/ +#define RT_ERROR_SIGWAIT -2 +#define RT_ERROR_TIMER -3 + +#define SIGNAL_TIMER (FOSA_SIGNAL_MAX - 1) + +#define SIGNAL_A (FOSA_SIGNAL_MAX - 2) +#define SIGNAL_KILL_A (FOSA_SIGNAL_MAX - 3) + +#define SIGNAL_B (FOSA_SIGNAL_MAX - 4) +#define SIGNAL_KILL_B (FOSA_SIGNAL_MAX - 5) +#define SIGNAL_C (FOSA_SIGNAL_MAX - 6) +#define SIGNAL_KILL_C (FOSA_SIGNAL_MAX - 7) + + +#define PRIO_MAIN 4 +#define PRIO_A 5 +#define PRIO_B 6 +#define PRIO_C 7 +#define PRIO_CATCHER 8 + + +typedef struct _my_signal_info_t +{ + fosa_rel_time_t eat_time; +} my_signal_info_t; + +typedef struct _my_thread_arg_t +{ + char identifier[100]; + fosa_signal_t signum; + fosa_signal_t sigkill; +} my_thread_arg_t; + + + + +/***************************/ +/* P R O T O T Y P E S */ +/***************************/ +static void *controlled_thread(void *thread_arg); +static void *catcher_thread(void *arg); + +static void create_thread(fosa_thread_code_t thread_code, + void *arg, + int priority, + fosa_thread_id_t *tid); + +static void time_printf(const char *format, ...); + + +/***************************/ +/* S T A T I C D A T A */ +/***************************/ +static fosa_abs_time_t start_time; +static bool timer_expired; + + +int main () +{ + int err = -1; + + fosa_thread_id_t tid_A, tid_B, tid_C, tid_catcher; + my_thread_arg_t thread_arg_A, thread_arg_B, thread_arg_C; + fosa_rel_time_t eat_time_A, eat_time_B, eat_time_C, group_time; + fosa_signal_info_t siginfo_A, siginfo_B, siginfo_C, siginfo_timer; + + fosa_thread_group_id_t thread_group_id; + fosa_clock_id_t group_clock_id; + fosa_timer_id_t group_timer; + + /* Initialize base time and thread arguments */ + /*********************************************/ + fosa_clock_get_time(FOSA_CLOCK_REALTIME, &start_time); + + strcpy(thread_arg_A.identifier, "THREAD A"); + thread_arg_A.signum = SIGNAL_A; + thread_arg_A.sigkill = SIGNAL_KILL_A; + siginfo_A.sival_ptr = &eat_time_A; + + strcpy(thread_arg_B.identifier, "THREAD B"); + thread_arg_B.signum = SIGNAL_B; + thread_arg_B.sigkill = SIGNAL_KILL_B; + siginfo_B.sival_ptr = &eat_time_B; + + strcpy(thread_arg_C.identifier, "THREAD C"); + thread_arg_C.signum = SIGNAL_C; + thread_arg_C.sigkill = SIGNAL_KILL_C; + siginfo_C.sival_ptr = &eat_time_C; + + + /* We set our priority and create the threads. The threads */ + /* will be blocked waiting for the signal. */ + /************************************************************/ + err = fosa_thread_set_prio(fosa_thread_self(), fosa_get_priority_min() + PRIO_MAIN); + if (err != 0) + { + printf("MAIN: Error %d with setting main priority\n", err); + exit(1); + } + + create_thread(controlled_thread, &thread_arg_A, PRIO_A, &tid_A); + create_thread(controlled_thread, &thread_arg_B, PRIO_B, &tid_B); + create_thread(controlled_thread, &thread_arg_C, PRIO_C, &tid_C); + + create_thread(catcher_thread, NULL, PRIO_CATCHER, &tid_catcher); + + + /* We create the thread group, get its clock and create a timer */ + /****************************************************************/ + err = fosa_thread_group_create(&thread_group_id); + if (err != 0) + { + printf("MAIN: Error %d creating thread_group\n", err); + exit(1); + } + + err = fosa_get_groupcpu_clock(thread_group_id, &group_clock_id); + if (err != 0) + { + printf("MAIN: Error %d obtaining group clock\n", err); + exit(1); + } + + err = fosa_timer_create(group_clock_id, SIGNAL_TIMER, siginfo_timer, &group_timer); + if (err != 0) + { + printf("MAIN: Error %d obtaining group CPU timer\n", err); + exit(1); + } + + /* We add the 3 threads to the group */ + /*************************************/ + err = fosa_thread_group_add(thread_group_id, tid_A); + if (err != 0) + { + printf("MAIN: Error %d adding thread to thread group\n", err); + exit(1); + } + + err = fosa_thread_group_add(thread_group_id, tid_B); + if (err != 0) + { + printf("MAIN: Error %d adding thread to thread group\n", err); + exit(1); + } + + err = fosa_thread_group_add(thread_group_id, tid_C); + if (err != 0) + { + printf("MAIN: Error %d adding thread to thread group\n", err); + exit(1); + } + + + /* First experiment: We arm the group CPU timer with 5 sec and */ + /* make each thread execute two seconds each. */ + /****************************************************************/ + eat_time_A = fosa_msec_to_rel_time(2000); + eat_time_B = fosa_msec_to_rel_time(2000); + eat_time_C = fosa_msec_to_rel_time(2000); + + group_time = fosa_msec_to_rel_time(5000); + + timer_expired = false; + time_printf("MAIN: Arming group timer for 5 seconds\n"); + err = fosa_rel_timer_arm(group_timer, &group_time); + if (err != 0) + { + printf("MAIN: Error %d queueing signal\n", err); + exit(1); + } + + err = fosa_signal_queue(SIGNAL_A, siginfo_A, (fosa_thread_id_t) 0); + if (err != 0) + { + printf("MAIN: Error %d queueing signal\n", err); + exit(1); + } + + err = fosa_signal_queue(SIGNAL_B, siginfo_B, (fosa_thread_id_t) 0); + if (err != 0) + { + printf("MAIN: Error %d queueing signal\n", err); + exit(1); + } + + err = fosa_signal_queue(SIGNAL_C, siginfo_C, (fosa_thread_id_t) 0); + if (err != 0) + { + printf("MAIN: Error %d queueing signal\n", err); + exit(1); + } + + time_printf("MAIN: Back after all threads\n"); + + assert(timer_expired); + + + return 0; +} + + +// ---------------------------------------------------------------- + +/** + * This is a controlled thread. It stays waiting for a signal and + * then eats the requested time sent in the signal info. + **/ +static void *controlled_thread(void *arg) +{ + + fosa_signal_t signal_set[2]; + int err; + + my_thread_arg_t *thread_arg = (my_thread_arg_t *) arg; + + time_printf("%s: Initializing\n", thread_arg->identifier); + + signal_set[0] = thread_arg->signum; + signal_set[1] = thread_arg->sigkill; + err = fosa_set_accepted_signals(signal_set, 2); + if (err !=0) + { + printf ("%s: Error %d while setting the signal mask\n", thread_arg->identifier, err); + exit (1); + } + + + while(1) + { + fosa_signal_t signal_received; + fosa_signal_info_t info_received; + my_signal_info_t *signal_info; + + err = fosa_signal_wait(signal_set, 2, &signal_received, &info_received); + if ( err != 0) + { + printf("%s: Error %d while waiting for signal\n", thread_arg->identifier, err); + exit(1); + } + + if (signal_received == thread_arg->sigkill) + { + time_printf("%s: Terminating\n", thread_arg->identifier); + break; + } + + signal_info = (my_signal_info_t *) info_received.sival_ptr; + + time_printf("%s: about to eat %ld msec\n", thread_arg->identifier, fosa_rel_time_to_msec(signal_info->eat_time) ); + + fosa_eat(&signal_info->eat_time); + } + + return NULL; +} + +// ------------------------------------------------------------------ + +static void *catcher_thread(void *arg) +{ + int err = -1; + fosa_signal_t signal_set[1]; + + time_printf("CATCHER: Initializing\n"); + + signal_set[0] = SIGNAL_TIMER; + err = fosa_set_accepted_signals(signal_set, 1); + if (err !=0) + { + printf ("CATCHER: Error %d while setting the signal mask\n", err); + exit (1); + } + + while(1) + { + fosa_signal_t signal_received; + fosa_signal_info_t info_received; + + err = fosa_signal_wait(signal_set, 1, &signal_received, &info_received); + if ( err != 0) + { + printf("CATCHER: Error %d while waiting for signal\n", err); + exit(1); + } + + time_printf("CATCHER: Group timer expired!!!\n"); + timer_expired = true; + } + + return NULL; +} + + +// ------------------------------------------------------------------------ + +static void create_thread(fosa_thread_code_t thread_code, + void *arg, + int priority, + fosa_thread_id_t *tid) +{ + fosa_thread_attr_t attr; + int err; + + err = fosa_thread_attr_init(&attr); + if (err != 0) { + printf("Error %d while initializing the attr\n", err); + exit(1); + } + + err = fosa_thread_attr_set_prio(&attr, fosa_get_priority_min() + priority); + if (err != 0) { + printf("Error %d while setting priority\n", err); + exit(1); + } + + err = fosa_thread_create(tid, &attr, thread_code, arg); + if (err) { + printf("Error %d in fosa_thread_create\n", err); + exit(1); + } +} + + + +// ------------------------------------------------------------------------ + + +static void time_printf(const char *format, ...) +{ + va_list args; + + fosa_abs_time_t current_time; + fosa_rel_time_t interval; + + fosa_clock_get_time(FOSA_CLOCK_REALTIME, ¤t_time); + interval = fosa_abs_time_extract_interval(start_time, current_time); + + printf("%ld:", fosa_rel_time_to_msec(interval)); + + va_start(args, format); + vprintf(format, args); + va_end(args); +} -- 2.39.2