From: brocalv Date: Thu, 15 Jan 2009 17:09:27 +0000 (+0000) Subject: fosa_partikle: added support for FOSA group clocks X-Git-Url: https://rtime.felk.cvut.cz/gitweb/frescor/fosa.git/commitdiff_plain/e9a45fa7c5f41cb92da7c189f9fb523dea2437d0 fosa_partikle: added support for FOSA group clocks git-svn-id: http://www.frescor.org/private/svn/frescor/fosa/trunk@1476 35b4ef3e-fd22-0410-ab77-dab3279adceb --- diff --git a/include/fosa_opaque_types.h b/include/fosa_opaque_types.h index 6dddc6b..bff0981 100644 --- a/include/fosa_opaque_types.h +++ b/include/fosa_opaque_types.h @@ -365,7 +365,6 @@ typedef struct { bool activated; } FOSA_ADS_ACTIONS_T_OPAQUE; -typedef unsigned long FOSA_LONG_JUMP_CONTEXT_T_OPAQUE [32]; typedef pthread_t FOSA_THREAD_ID_T_OPAQUE; typedef pthread_attr_t FOSA_THREAD_ATTR_T_OPAQUE; @@ -374,9 +373,10 @@ typedef clockid_t FOSA_CLOCK_ID_T_OPAQUE; typedef timer_t FOSA_TIMER_ID_T_OPAQUE; typedef pthread_cond_t FOSA_COND_T_OPAQUE; typedef pthread_mutex_t FOSA_MUTEX_T_OPAQUE; +typedef unsigned long FOSA_LONG_JUMP_CONTEXT_T_OPAQUE [32]; +typedef group_clock_t FOSA_THREAD_SET_ID_T_OPAQUE; -typedef int FOSA_THREAD_SET_ID_T_OPAQUE; -#define FOSA_NULL_THREAD_SET_ID_OPAQUE -1; +#define FOSA_NULL_THREAD_SET_ID_OPAQUE 0x0; enum _fosa_clocks_e { FOSA_SYSTEM_CLOCK_OPAQUE = CLOCK_MONOTONIC @@ -391,7 +391,7 @@ enum _fosa_clocks_e { enum _fosa_signal_limits_e { LONGJMP_FIRSTSIG = SIGRTMAX - LONGJMP_NSIG + 1, FOSA_SIGNAL_MAX = LONGJMP_FIRSTSIG - 1, - FOSA_SIGNAL_MIN = FOSA_SIGNAL_MAX, + FOSA_SIGNAL_MIN = SIGRTMIN, FOSA_NULL_SIGNAL = -1, }; diff --git a/src_partikle/Makefile b/src_partikle/Makefile index d5c7faf..a52fce6 100644 --- a/src_partikle/Makefile +++ b/src_partikle/Makefile @@ -1,7 +1,7 @@ include ../config.mk include ../rules.mk -FOSA_MODULES=fosa_clocks_and_timers fosa_threads_and_signals fosa_app_def_sched fosa_mutexes_and_condvars fosa_misc fosa_long_jump fosa_time fosa_setjmp +FOSA_MODULES=fosa_clocks_and_timers fosa_threads_and_signals fosa_app_def_sched fosa_mutexes_and_condvars fosa_misc fosa_long_jump fosa_time fosa_setjmp fosa_group_clocks FOSA_OBJS=$(addsuffix .o,$(FOSA_MODULES)) check_gcc = $(shell \ diff --git a/src_partikle/fosa_group_clocks.c b/src_partikle/fosa_group_clocks.c new file mode 100644 index 0000000..c7bc638 --- /dev/null +++ b/src_partikle/fosa_group_clocks.c @@ -0,0 +1,188 @@ +// ----------------------------------------------------------------------- +// 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_group_clocks.c +//============================================== +// ******** ****** ******** ********** +// **///// /** ** **////// /** /** +// ** /** ** /** /** /** +// ******* /** ** /********* /********** +// **//// /** ** ////////** /**//////** +// ** /** ** /** /** /** +// ** /** ** ******** /** /** +// // /******/ //////// // // +// +// FOSA(Frescor Operating System Adaptation layer) +//================================================ + +#include "fosa_group_clocks.h" + +/** + * fosa_thread_set_create() + * + * Create an empty thread set and return an identifier + * + * This function stores in the variable pointed to by set the + * identifier of a thread set 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 set + * + * 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_set_create(fosa_thread_set_id_t *set) +{ + return groupclock_create (set); +} + + +/** + * fosa_thread_set_destroy() + * + * Destroy a thread set + * + * This function destroys the thread set identified by set. The + * threads that were in the set are detached from the set. 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: set 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_set_destroy(fosa_thread_set_id_t set) +{ + return groupclock_delete (set); +} + + +/** + * fosa_thread_set_add() + * + * Add a thread to a thread set + * + * This function adds the thread identified with thread_id to the + * thread set identified by set. + * + * Returns 0 if successful; otherwise it returns an error code: + * FOSA_EINVAL: set is invalid + * FOSA_ENOTSUP: thread already a member of some other set + * 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_set_add(fosa_thread_set_id_t set, + fosa_thread_id_t thread_id) +{ + return groupclock_add (set, thread_id); +} + + + +/** + * fosa_thread_set_del() + * + * Delete a thread from a thread set + * + * This function deletes the thread identified with thread_id from + * the thread set identified by set. + * + * Returns 0 if successful; otherwise it returns an error code: + * FOSA_EINVAL: set is invalid + * FOSA_EINVAL: thread is not a member of the set + * 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_set_del(fosa_thread_set_id_t set, + fosa_thread_id_t thread_id) +{ + return groupclock_remove (set, thread_id); +} + +/** + * fosa_get_groupcpu_clock() + * + * Get the identifier of a cpu-time clock associated to a thread + * set + * + * This function stores in the variable pointed to by clockid the + * identifier of a cpu-time clock for the thread set specified + * by set. + * + * Returns 0 if successful; otherwise it returns an error code: + * FOSA_EINVAL: the set 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_set_id_t set, + fosa_clock_id_t *clock_id) +{ + return groupclock_getclockid (set, clock_id); +} diff --git a/src_partikle/fosa_threads_and_signals.c b/src_partikle/fosa_threads_and_signals.c index 18bcf8e..c652cb5 100644 --- a/src_partikle/fosa_threads_and_signals.c +++ b/src_partikle/fosa_threads_and_signals.c @@ -71,6 +71,8 @@ #include #include +#define TRACE(str, args...) printf ("%d: %s: " str, __LINE__, __func__, ##args) + /************************* * Thread identification *************************/ @@ -266,6 +268,9 @@ int fosa_set_accepted_signals(fosa_signal_t set[], int size) sigset_t accept_set; struct sigaction act; +// printf ("%d: %s: limits=[%d, %d]\n", __LINE__, __FUNCTION__, +// FOSA_SIGNAL_MIN, FOSA_SIGNAL_MAX); + if (size < 0) return EINVAL; @@ -274,15 +279,21 @@ int fosa_set_accepted_signals(fosa_signal_t set[], int size) act.sa_flags = SA_SIGINFO; act.sa_handler = SIG_DFL; +// printf ("%d: %s: add signals\n", __LINE__, __FUNCTION__); for (i = 0; i < size; i ++) { +// printf ("%d: %s: signal=%d \n", __LINE__, __FUNCTION__, set[i]); + if (FOSA_SIGNAL_MIN > set [i] || set [i] > FOSA_SIGNAL_MAX) return EINVAL; - sigaction (set [i], &act, NULL); +// printf ("%d: %s: sigaction\n", __LINE__, __FUNCTION__); + sigaction (set [i], &act, NULL); sigaddset (&accept_set, set [i]); } - - return pthread_sigmask (SIG_BLOCK, &accept_set, NULL); + +// printf ("%d: %s: pthread_sigmask\n", __LINE__, __FUNCTION__); + assert (!pthread_sigmask (SIG_BLOCK, &accept_set, NULL)); + return 0; } @@ -303,9 +314,10 @@ int fosa_signal_queue (fosa_signal_t set[], int size, fosa_signal_t *signal_received, fosa_signal_info_t *info) { - return fosa_signal_timedwait (set, size, signal_received, info, NULL); + return fosa_signal_timedwait (set, size, signal_received, info, NULL); } + int fosa_signal_timedwait (fosa_signal_t set[], int size, fosa_signal_t *signal_received, fosa_signal_info_t *info, const fosa_rel_time_t *timeout) @@ -313,8 +325,7 @@ int fosa_signal_queue int i, sig; sigset_t wset; siginfo_t nfo; - struct timespec tout = fosa_rel_time_to_timespec (*timeout); - + if (size < 0) return EINVAL; @@ -325,7 +336,7 @@ int fosa_signal_queue sigaddset (&wset, set [i]); } - sig = sigtimedwait (&wset, &nfo, &tout); + sig = sigtimedwait (&wset, &nfo, timeout); if (sig == -1) return errno; diff --git a/src_partikle/tests/test_group_clocks.c b/src_partikle/tests/test_group_clocks.c new file mode 100644 index 0000000..ef0bdc4 --- /dev/null +++ b/src_partikle/tests/test_group_clocks.c @@ -0,0 +1,422 @@ +// ----------------------------------------------------------------------- +// 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. +// ----------------------------------------------------------------------- + +/* + * Vicent Brocal : + * Minor modifications to adapt the code to test the implementation of + * group clocks for PaRTiKle. + */ + +#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; + +fosa_clock_id_t group_clock_id; + +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_set_id_t thread_set_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 set, get its clock and create a timer */ + /****************************************************************/ + err = fosa_thread_set_create(&thread_set_id); + if (err != 0) + { + printf("MAIN: Error %d creating thread_set\n", err); + exit(1); + } + + err = fosa_get_groupcpu_clock(thread_set_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 set */ + /*************************************/ + err = fosa_thread_set_add(thread_set_id, tid_A); + if (err != 0) + { + printf("MAIN: Error %d adding thread to thread set\n", err); + exit(1); + } + + err = fosa_thread_set_add(thread_set_id, tid_B); + if (err != 0) + { + printf("MAIN: Error %d adding thread to thread set\n", err); + exit(1); + } + + err = fosa_thread_set_add(thread_set_id, tid_C); + if (err != 0) + { + printf("MAIN: Error %d adding thread to thread set\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); + } + + struct timespec t = {2,0}; + nanosleep (&t, NULL); + 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); +}