From: Christian Mauderer <christian.maude...@embedded-brains.de> --- cpukit/libcsupport/src/gxx_wrappers.c | 15 +------- cpukit/posix/src/pthreadonce.c | 37 +----------------- cpukit/score/Makefile.am | 2 + cpukit/score/include/rtems/score/onceimpl.h | 50 ++++++++++++++++++++++++ cpukit/score/preinstall.am | 10 +++-- cpukit/score/src/once.c | 60 +++++++++++++++++++++++++++++ 6 files changed, 123 insertions(+), 51 deletions(-) create mode 100644 cpukit/score/include/rtems/score/onceimpl.h create mode 100644 cpukit/score/src/once.c
diff --git a/cpukit/libcsupport/src/gxx_wrappers.c b/cpukit/libcsupport/src/gxx_wrappers.c index 31f6254..711daa4 100644 --- a/cpukit/libcsupport/src/gxx_wrappers.c +++ b/cpukit/libcsupport/src/gxx_wrappers.c @@ -29,6 +29,7 @@ #endif #include <rtems/gxx_wrappers.h> +#include <rtems/score/onceimpl.h> #include <stdlib.h> @@ -43,19 +44,7 @@ int rtems_gxx_once(__gthread_once_t *once, void (*func) (void)) printk( "gxx_wrappers: once=%x, func=%x\n", *once, func ); #endif - if ( *(volatile __gthread_once_t *)once == 0 ) { - rtems_mode saveMode; - __gthread_once_t o; - - rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &saveMode); - if ( (o = *(volatile __gthread_once_t *)once) == 0 ) { - *(volatile __gthread_once_t *)once = 1; - } - rtems_task_mode(saveMode, RTEMS_PREEMPT_MASK, &saveMode); - if ( o == 0 ) - (*func)(); - } - return 0; + return _Once( once, func ); } int rtems_gxx_key_create (__gthread_key_t *key, void (*dtor) (void *)) diff --git a/cpukit/posix/src/pthreadonce.c b/cpukit/posix/src/pthreadonce.c index 6b8274d..295bc57 100644 --- a/cpukit/posix/src/pthreadonce.c +++ b/cpukit/posix/src/pthreadonce.c @@ -23,51 +23,18 @@ #include <pthread.h> #include <errno.h> -#include <rtems/score/apimutex.h> - -#define PTHREAD_ONCE_INIT_NOT_RUN 0 -#define PTHREAD_ONCE_INIT_RUNNING 1 -#define PTHREAD_ONCE_INIT_COMPLETE 2 +#include <rtems/score/onceimpl.h> int pthread_once( pthread_once_t *once_control, void (*init_routine)(void) ) { - int r = 0; - if ( !once_control || !init_routine ) return EINVAL; if ( once_control->is_initialized != 1 ) return EINVAL; - if ( once_control->init_executed != PTHREAD_ONCE_INIT_COMPLETE ) { - _Once_Lock(); - - /* - * Getting to here means the once_control is locked so we have: - * 1. The init has not run and the state is PTHREAD_ONCE_INIT_NOT_RUN. - * 2. The init has finished and the state is PTHREAD_ONCE_INIT_RUN. - * 3. The init is being run by this thread and the state - * PTHREAD_ONCE_INIT_RUNNING so we are nesting. This is an error. - */ - - switch ( once_control->init_executed ) { - case PTHREAD_ONCE_INIT_NOT_RUN: - once_control->init_executed = PTHREAD_ONCE_INIT_RUNNING; - (*init_routine)(); - once_control->init_executed = PTHREAD_ONCE_INIT_COMPLETE; - break; - case PTHREAD_ONCE_INIT_RUNNING: - r = EINVAL; - break; - default: - break; - } - - _Once_Unlock(); - } - - return r; + return _Once( &once_control->init_executed, init_routine ); } diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index 6c4293a..aeee4b6 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -41,6 +41,7 @@ include_rtems_score_HEADERS += include/rtems/score/isrlock.h include_rtems_score_HEADERS += include/rtems/score/freechain.h include_rtems_score_HEADERS += include/rtems/score/object.h include_rtems_score_HEADERS += include/rtems/score/objectimpl.h +include_rtems_score_HEADERS += include/rtems/score/onceimpl.h include_rtems_score_HEADERS += include/rtems/score/percpu.h include_rtems_score_HEADERS += include/rtems/score/priority.h include_rtems_score_HEADERS += include/rtems/score/prioritybitmap.h @@ -335,6 +336,7 @@ libscore_a_SOURCES += src/apiext.c src/chain.c src/chainappend.c \ src/interr.c src/isr.c src/wkspace.c src/wkstringduplicate.c libscore_a_SOURCES += src/debugisownerofallocator.c libscore_a_SOURCES += src/profilingisrentryexit.c +libscore_a_SOURCES += src/once.c EXTRA_DIST = src/Unlimited.txt diff --git a/cpukit/score/include/rtems/score/onceimpl.h b/cpukit/score/include/rtems/score/onceimpl.h new file mode 100644 index 0000000..ac4a394 --- /dev/null +++ b/cpukit/score/include/rtems/score/onceimpl.h @@ -0,0 +1,50 @@ +/** + * @file + * + * @ingroup ScoreOnce + * + * @brief Once API. + * + * Functions used by posix once as well as gxx_wrappers. + */ + +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rt...@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifndef _RTEMS_ONCE_H +#define _RTEMS_ONCE_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup ScoreOnce Once Functions. + * + * @ingroup Score + * + * @brief Once functions. + * + * @{ + */ + +int _Once( int *once_state, void (*init_routine)(void) ); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _RTEMS_SCORE_TLS_H */ diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am index bb6508c..31853d5 100644 --- a/cpukit/score/preinstall.am +++ b/cpukit/score/preinstall.am @@ -5,14 +5,14 @@ $(srcdir)/preinstall.am: Makefile.am $(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am endif -PREINSTALL_DIRS = -DISTCLEANFILES += $(PREINSTALL_DIRS) - all-am: $(PREINSTALL_FILES) PREINSTALL_FILES = CLEANFILES = $(PREINSTALL_FILES) +PREINSTALL_DIRS = +DISTCLEANFILES += $(PREINSTALL_DIRS) + $(PROJECT_INCLUDE)/rtems/$(dirstamp): @$(MKDIR_P) $(PROJECT_INCLUDE)/rtems @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp) @@ -147,6 +147,10 @@ $(PROJECT_INCLUDE)/rtems/score/objectimpl.h: include/rtems/score/objectimpl.h $( $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/objectimpl.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/objectimpl.h +$(PROJECT_INCLUDE)/rtems/score/onceimpl.h: include/rtems/score/onceimpl.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/onceimpl.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/onceimpl.h + $(PROJECT_INCLUDE)/rtems/score/percpu.h: include/rtems/score/percpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/percpu.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/percpu.h diff --git a/cpukit/score/src/once.c b/cpukit/score/src/once.c new file mode 100644 index 0000000..bfeca2a --- /dev/null +++ b/cpukit/score/src/once.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rt...@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include <errno.h> +#include <rtems/score/onceimpl.h> +#include <rtems/score/apimutex.h> + +#define ONCE_STATE_NOT_RUN 0 +#define ONCE_STATE_RUNNING 1 +#define ONCE_STATE_COMPLETE 2 + +int _Once( int *once_state, void (*init_routine)(void) ) +{ + int r = 0; + + if ( *once_state != ONCE_STATE_COMPLETE ) { + _Once_Lock(); + + /* + * Getting to here means the once_control is locked so we have: + * 1. The init has not run and the state is ONCE_STATE_NOT_RUN. + * 2. The init has finished and the state is ONCE_STATE_COMPLETE (already + * caught by the previous if). + * 3. The init is being run by this thread and the state + * ONCE_STATE_RUNNING so we are nesting. This is an error. + */ + + switch ( *once_state ) { + case ONCE_STATE_NOT_RUN: + *once_state = ONCE_STATE_RUNNING; + (*init_routine)(); + *once_state = ONCE_STATE_COMPLETE; + break; + case ONCE_STATE_RUNNING: + r = EINVAL; + break; + default: + break; + } + + _Once_Unlock(); + } + + return r; +} -- 1.8.4.5 _______________________________________________ rtems-devel mailing list rtems-devel@rtems.org http://www.rtems.org/mailman/listinfo/rtems-devel