summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2013-08-14 10:21:41 +1000
committerChris Johns <chrisj@rtems.org>2013-08-14 10:21:41 +1000
commit03acc5915e002f0b03eee9e86212209705cca6d6 (patch)
tree93c452a3f546f0d6f4456481c78e9fc6d4a6e082 /cpukit
parentposix: Handle recursive attributes correctly. (diff)
downloadrtems-03acc5915e002f0b03eee9e86212209705cca6d6.tar.bz2
posix: Change pthread_once to be SMP safe.
Change pthread_once from using disabled pre-emption to using a pthread mutex making it SMP safe. GCC using a posix threading model uses pthread_once. The pthread mutex requires at least 1 mutex is configured so confdefs.h has been updated to account for the internal mutex.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/posix/Makefile.am6
-rw-r--r--cpukit/posix/include/rtems/posix/onceimpl.h57
-rw-r--r--cpukit/posix/preinstall.am4
-rw-r--r--cpukit/posix/src/once.c49
-rw-r--r--cpukit/posix/src/pthreadonce.c50
-rw-r--r--cpukit/sapi/include/confdefs.h7
-rw-r--r--cpukit/sapi/src/posixapi.c2
7 files changed, 164 insertions, 11 deletions
diff --git a/cpukit/posix/Makefile.am b/cpukit/posix/Makefile.am
index 1b83eee090..ea6d3d983d 100644
--- a/cpukit/posix/Makefile.am
+++ b/cpukit/posix/Makefile.am
@@ -33,6 +33,7 @@ include_rtems_posix_HEADERS += include/rtems/posix/mqueue.h
include_rtems_posix_HEADERS += include/rtems/posix/mqueueimpl.h
include_rtems_posix_HEADERS += include/rtems/posix/mutex.h
include_rtems_posix_HEADERS += include/rtems/posix/muteximpl.h
+include_rtems_posix_HEADERS += include/rtems/posix/onceimpl.h
include_rtems_posix_HEADERS += include/rtems/posix/posixapi.h
include_rtems_posix_HEADERS += include/rtems/posix/priorityimpl.h
include_rtems_posix_HEADERS += include/rtems/posix/psignal.h
@@ -115,6 +116,9 @@ libposix_a_SOURCES += src/mutexattrdestroy.c src/mutexattrgetprioceiling.c \
src/mutexlocksupp.c src/mutexsetprioceiling.c src/mutextimedlock.c \
src/mutextranslatereturncode.c src/mutextrylock.c src/mutexunlock.c
+## ONCE_C_FILES
+libposix_a_SOURCES += src/once.c src/pthreadonce.c
+
## PTHREAD_C_FILES
libposix_a_SOURCES += src/pthreadatfork.c src/pthreadattrdestroy.c \
src/pthreadattrgetdetachstate.c src/pthreadattrgetinheritsched.c \
@@ -131,7 +135,7 @@ libposix_a_SOURCES += src/pthreadatfork.c src/pthreadattrdestroy.c \
src/pthreadexit.c src/pthreadgetcpuclockid.c \
src/pthreadgetschedparam.c \
src/pthreadinitthreads.c src/pthreadjoin.c src/pthreadkill.c \
- src/pthreadonce.c src/pthreadself.c \
+ src/pthreadself.c \
src/pthreadsetschedparam.c src/pthreadsigmask.c \
src/psxpriorityisvalid.c src/psxtransschedparam.c
diff --git a/cpukit/posix/include/rtems/posix/onceimpl.h b/cpukit/posix/include/rtems/posix/onceimpl.h
new file mode 100644
index 0000000000..f0238107a6
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/onceimpl.h
@@ -0,0 +1,57 @@
+/**
+ * @file
+ *
+ * @brief Private Inlined Routines for POSIX Once
+ *
+ * This include file contains the static inline implementation of the private
+ * inlined routines for POSIX once.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * COPYRIGHT (c) 2013.
+ * Chris Johns <chrisj@rtems.org>
+ *
+ * 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.
+ */
+
+#include <rtems/score/objectimpl.h>
+#include <rtems/score/percpu.h>
+
+#ifndef _RTEMS_POSIX_ONCEIMPL_H
+#define _RTEMS_POSIX_ONCEMPL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup POSIX_ONCE
+ *
+ * @{
+ */
+
+/**
+ * @brief Lock to allow once mutex's to be initialized.
+ */
+POSIX_EXTERN pthread_mutex_t _POSIX_Once_Lock;
+
+/**
+ * @brief POSIX once manager initialization.
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+void _POSIX_Once_Manager_initialization(void);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/preinstall.am b/cpukit/posix/preinstall.am
index 093a9df914..d0e238cd15 100644
--- a/cpukit/posix/preinstall.am
+++ b/cpukit/posix/preinstall.am
@@ -84,6 +84,10 @@ $(PROJECT_INCLUDE)/rtems/posix/muteximpl.h: include/rtems/posix/muteximpl.h $(PR
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/muteximpl.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/muteximpl.h
+$(PROJECT_INCLUDE)/rtems/posix/onceimpl.h: include/rtems/posix/onceimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/onceimpl.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/onceimpl.h
+
$(PROJECT_INCLUDE)/rtems/posix/posixapi.h: include/rtems/posix/posixapi.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/posixapi.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/posixapi.h
diff --git a/cpukit/posix/src/once.c b/cpukit/posix/src/once.c
new file mode 100644
index 0000000000..d77c3c12e3
--- /dev/null
+++ b/cpukit/posix/src/once.c
@@ -0,0 +1,49 @@
+/**
+ * @file
+ *
+ * @brief POSIX Once Manager Initialization
+ * @ingroup POSIX_ONCE POSIX Once Support
+ */
+
+/*
+ * COPYRIGHT (c) 2013
+ * Chris Johns <chrisj@rtems.org>
+ *
+ * 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.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/posix/onceimpl.h>
+
+pthread_mutex_t _POSIX_Once_Lock;
+
+void _POSIX_Once_Manager_initialization(void)
+{
+ pthread_mutexattr_t mattr;
+ int r;
+
+ _POSIX_Once_Lock = PTHREAD_MUTEX_INITIALIZER;
+
+ r = pthread_mutexattr_init( &mattr );
+ if ( r != 0 )
+ rtems_fatal( RTEMS_FATAL_SOURCE_ASSERT, 0x80aa0000 | r );
+
+ r = pthread_mutexattr_settype( &mattr, PTHREAD_MUTEX_RECURSIVE );
+ if ( r != 0 )
+ rtems_fatal( RTEMS_FATAL_SOURCE_ASSERT, 0x80aa1000 | r );
+
+ r = pthread_mutex_init( &_POSIX_Once_Lock, &mattr );
+ if ( r != 0 )
+ rtems_fatal( RTEMS_FATAL_SOURCE_ASSERT, 0x80aa2000 | r );
+
+ pthread_mutexattr_destroy( &mattr );
+}
diff --git a/cpukit/posix/src/pthreadonce.c b/cpukit/posix/src/pthreadonce.c
index 0700a222c7..2b02f1e53c 100644
--- a/cpukit/posix/src/pthreadonce.c
+++ b/cpukit/posix/src/pthreadonce.c
@@ -25,25 +25,55 @@
#include <rtems.h>
#include <rtems/system.h>
-#include <rtems/score/thread.h>
+#include <rtems/posix/onceimpl.h>
+
+#define PTHREAD_ONCE_INIT_NOT_RUN 0
+#define PTHREAD_ONCE_INIT_RUNNING 1
+#define PTHREAD_ONCE_INIT_RUN 2
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->init_executed ) {
- rtems_mode saveMode;
- rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &saveMode);
- if ( !once_control->init_executed ) {
- once_control->is_initialized = true;
- once_control->init_executed = true;
- (*init_routine)();
+ if ( once_control->is_initialized != 1 )
+ return EINVAL;
+
+ if ( once_control->init_executed != PTHREAD_ONCE_INIT_RUN ) {
+ r = pthread_mutex_lock( &_POSIX_Once_Lock );
+ if ( r == 0 ) {
+ int rr;
+
+ /*
+ * 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_RUN;
+ break;
+ case PTHREAD_ONCE_INIT_RUNNING:
+ r = EINVAL;
+ break;
+ default:
+ break;
+ }
+ rr = pthread_mutex_unlock( &_POSIX_Once_Lock );
+ if ( r == 0 )
+ r = rr;
}
- rtems_task_mode(saveMode, RTEMS_PREEMPT_MASK, &saveMode);
}
- return 0;
+
+ return r;
}
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index 50db8779af..2a3af15912 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -1695,6 +1695,11 @@ const rtems_libio_helper rtems_fs_init_helper =
#include <rtems/posix/timer.h>
/**
+ * POSIX Once support uses a single mutex.
+ */
+ #define CONFIGURE_MAXIMUM_POSIX_INTERNAL_MUTEXES 1
+
+ /**
* Account for the object control structures plus the name
* of the object to be duplicated.
*/
@@ -1856,6 +1861,7 @@ const rtems_libio_helper rtems_fs_init_helper =
#define CONFIGURE_MEMORY_FOR_POSIX \
( CONFIGURE_MEMORY_FOR_POSIX_MUTEXES( CONFIGURE_MAXIMUM_POSIX_MUTEXES + \
+ CONFIGURE_MAXIMUM_POSIX_INTERNAL_MUTEXES + \
CONFIGURE_MAXIMUM_GO_CHANNELS + CONFIGURE_GO_INIT_MUTEXES) + \
CONFIGURE_MEMORY_FOR_POSIX_CONDITION_VARIABLES( \
CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES + \
@@ -2304,6 +2310,7 @@ const rtems_libio_helper rtems_fs_init_helper =
CONFIGURE_MAXIMUM_POSIX_THREADS + CONFIGURE_MAXIMUM_ADA_TASKS +
CONFIGURE_MAXIMUM_GOROUTINES,
CONFIGURE_MAXIMUM_POSIX_MUTEXES + CONFIGURE_GNAT_MUTEXES +
+ CONFIGURE_MAXIMUM_POSIX_INTERNAL_MUTEXES +
CONFIGURE_MAXIMUM_ADA_TASKS + CONFIGURE_MAXIMUM_FAKE_ADA_TASKS +
CONFIGURE_GO_INIT_MUTEXES + CONFIGURE_MAXIMUM_GO_CHANNELS,
CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES +
diff --git a/cpukit/sapi/src/posixapi.c b/cpukit/sapi/src/posixapi.c
index af9ba2cac3..2d784a1671 100644
--- a/cpukit/sapi/src/posixapi.c
+++ b/cpukit/sapi/src/posixapi.c
@@ -33,6 +33,7 @@
#include <rtems/posix/keyimpl.h>
#include <rtems/posix/mqueueimpl.h>
#include <rtems/posix/muteximpl.h>
+#include <rtems/posix/onceimpl.h>
#include <rtems/posix/posixapi.h>
#include <rtems/posix/priorityimpl.h>
#include <rtems/posix/psignalimpl.h>
@@ -66,6 +67,7 @@ void _POSIX_API_Initialize(void)
_POSIX_Key_Manager_initialization();
_POSIX_Mutex_Manager_initialization();
_POSIX_Message_queue_Manager_initialization();
+ _POSIX_Once_Manager_initialization();
_POSIX_Semaphore_Manager_initialization();
_POSIX_Timer_Manager_initialization();
_POSIX_Barrier_Manager_initialization();