[PATCH] posix: Use interal mutex for once implementation

Sebastian Huber sebastian.huber at embedded-brains.de
Tue Mar 18 07:36:38 UTC 2014


Enable pthread_once() for all configurations.  The pthread_once()
function is one means to initialize POSIX keys.  Another use case is the
C++ support.
---
 cpukit/posix/Makefile.am                    |    7 +--
 cpukit/posix/include/rtems/posix/onceimpl.h |   57 ---------------------------
 cpukit/posix/preinstall.am                  |    4 --
 cpukit/posix/src/once.c                     |   46 ---------------------
 cpukit/posix/src/pthreadonce.c              |   49 ++++++++++-------------
 cpukit/sapi/include/confdefs.h              |   14 +-----
 cpukit/sapi/src/exinit.c                    |    3 +-
 cpukit/sapi/src/posixapi.c                  |    1 -
 cpukit/score/include/rtems/score/apimutex.h |   12 ++++++
 testsuites/psxtests/psxconfig01/init.c      |    3 +-
 10 files changed, 43 insertions(+), 153 deletions(-)
 delete mode 100644 cpukit/posix/include/rtems/posix/onceimpl.h
 delete mode 100644 cpukit/posix/src/once.c

diff --git a/cpukit/posix/Makefile.am b/cpukit/posix/Makefile.am
index 53a5887..346b65a 100644
--- a/cpukit/posix/Makefile.am
+++ b/cpukit/posix/Makefile.am
@@ -36,7 +36,6 @@ 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/priorityimpl.h
 include_rtems_posix_HEADERS += include/rtems/posix/psignal.h
 include_rtems_posix_HEADERS += include/rtems/posix/psignalimpl.h
@@ -113,9 +112,6 @@ 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 \
@@ -160,6 +156,9 @@ libposix_a_SOURCES += src/key.c src/keycreate.c src/keydelete.c \
     src/keygetspecific.c src/keyfreememory.c src/keyrundestructors.c \
     src/keysetspecific.c
 
+## ONCE_C_FILES
+libposix_a_SOURCES += src/pthreadonce.c
+
 libposix_a_SOURCES += src/sigaddset.c src/sigdelset.c src/sigfillset.c \
    src/sigemptyset.c src/sigismember.c
 
diff --git a/cpukit/posix/include/rtems/posix/onceimpl.h b/cpukit/posix/include/rtems/posix/onceimpl.h
deleted file mode 100644
index 48f876a..0000000
--- a/cpukit/posix/include/rtems/posix/onceimpl.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * @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 at 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_ONCEIMPL_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 d0f36f9..6e3f2a2 100644
--- a/cpukit/posix/preinstall.am
+++ b/cpukit/posix/preinstall.am
@@ -88,10 +88,6 @@ $(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/priorityimpl.h: include/rtems/posix/priorityimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/priorityimpl.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/priorityimpl.h
diff --git a/cpukit/posix/src/once.c b/cpukit/posix/src/once.c
deleted file mode 100644
index e91daf2..0000000
--- a/cpukit/posix/src/once.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * @file
- *
- * @brief POSIX Once Manager Initialization
- * @ingroup POSIX_ONCE POSIX Once Support
- */
-
-/*
- *  COPYRIGHT (c) 2013
- *  Chris Johns <chrisj at 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/posixapi.h>
-#include <rtems/posix/onceimpl.h>
-
-void _POSIX_Once_Manager_initialization(void)
-{
-  pthread_mutexattr_t mattr;
-  int eno;
-
-  _POSIX_Once_Lock = PTHREAD_MUTEX_INITIALIZER;
-
-  eno = pthread_mutexattr_init( &mattr );
-  _Assert( eno == 0 );
-  eno = pthread_mutexattr_settype( &mattr, PTHREAD_MUTEX_RECURSIVE );
-  _Assert( eno == 0 );
-
-  eno = pthread_mutex_init( &_POSIX_Once_Lock, &mattr );
-  if ( eno != 0 )
-    _POSIX_Fatal_error( POSIX_FD_PTHREAD_ONCE, eno );
-
-  eno = pthread_mutexattr_destroy( &mattr );
-  _Assert( eno == 0 );
-}
diff --git a/cpukit/posix/src/pthreadonce.c b/cpukit/posix/src/pthreadonce.c
index aa8afe7..262f673 100644
--- a/cpukit/posix/src/pthreadonce.c
+++ b/cpukit/posix/src/pthreadonce.c
@@ -23,8 +23,7 @@
 #include <pthread.h>
 #include <errno.h>
 
-#include <rtems.h>
-#include <rtems/system.h>
+#include <rtems/score/apimutex.h>
 #include <rtems/posix/onceimpl.h>
 
 #define PTHREAD_ONCE_INIT_NOT_RUN  0
@@ -45,34 +44,30 @@ int pthread_once(
     return EINVAL;
 
   if ( once_control->init_executed != PTHREAD_ONCE_INIT_COMPLETE ) {
-    r = pthread_mutex_lock( &_POSIX_Once_Lock );
-    if ( r == 0 ) {
-      int rr;
+    _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.
-       */
+    /*
+     * 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;
-      }
-      rr = pthread_mutex_unlock( &_POSIX_Once_Lock );
-      if ( r == 0 )
-        r = rr;
+    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;
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index 08b8b5f..add58ae 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -1766,11 +1766,6 @@ 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.
    */
@@ -1899,7 +1894,6 @@ 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 + \
@@ -2130,11 +2124,11 @@ const rtems_libio_helper rtems_fs_init_helper =
 #endif
 
 /**
- * RTEMS uses one instance of an internal mutex class.  This accounts
- * for that mutex
+ * RTEMS uses two instance of an internal mutex class.  This accounts
+ * for these mutexes.
  */
 #define CONFIGURE_API_MUTEX_MEMORY \
-  _Configure_Object_RAM(1, sizeof(API_Mutex_Control))
+  _Configure_Object_RAM(2, sizeof(API_Mutex_Control))
 
 /**
  * This calculates the amount of memory reserved for the IDLE tasks.
@@ -2349,7 +2343,6 @@ 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 +
@@ -2599,7 +2592,6 @@ const rtems_libio_helper rtems_fs_init_helper =
 #ifdef RTEMS_POSIX_API
     /* POSIX API Pieces */
     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 +
diff --git a/cpukit/sapi/src/exinit.c b/cpukit/sapi/src/exinit.c
index 077a092..cc929cb 100644
--- a/cpukit/sapi/src/exinit.c
+++ b/cpukit/sapi/src/exinit.c
@@ -116,8 +116,9 @@ void rtems_initialize_data_structures(void)
    */
   _Objects_Information_table[OBJECTS_INTERNAL_API] = _Internal_Objects;
 
-  _API_Mutex_Initialization( 1 );
+  _API_Mutex_Initialization( 2 );
   _API_Mutex_Allocate( &_RTEMS_Allocator_Mutex );
+  _API_Mutex_Allocate( &_Once_Mutex );
 
   _Watchdog_Handler_initialization();
   _TOD_Handler_initialization();
diff --git a/cpukit/sapi/src/posixapi.c b/cpukit/sapi/src/posixapi.c
index de502ec..7014b59 100644
--- a/cpukit/sapi/src/posixapi.c
+++ b/cpukit/sapi/src/posixapi.c
@@ -79,7 +79,6 @@ void _POSIX_API_Initialize(void)
     _POSIX_Condition_variables_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();
diff --git a/cpukit/score/include/rtems/score/apimutex.h b/cpukit/score/include/rtems/score/apimutex.h
index a34270e..1178ccb 100644
--- a/cpukit/score/include/rtems/score/apimutex.h
+++ b/cpukit/score/include/rtems/score/apimutex.h
@@ -120,6 +120,18 @@ SCORE_EXTERN API_Mutex_Control *_RTEMS_Allocator_Mutex;
 #define _RTEMS_Unlock_allocator() \
   _API_Mutex_Unlock( _RTEMS_Allocator_Mutex )
 
+SCORE_EXTERN API_Mutex_Control *_Once_Mutex;
+
+static inline void _Once_Lock( void )
+{
+  _API_Mutex_Lock( _Once_Mutex );
+}
+
+static inline void _Once_Unlock( void )
+{
+  _API_Mutex_Unlock( _Once_Mutex );
+}
+
 /** @} */
 
 #ifdef __cplusplus
diff --git a/testsuites/psxtests/psxconfig01/init.c b/testsuites/psxtests/psxconfig01/init.c
index 17849b0..3481f32 100644
--- a/testsuites/psxtests/psxconfig01/init.c
+++ b/testsuites/psxtests/psxconfig01/init.c
@@ -487,8 +487,7 @@ static rtems_task Init(rtems_task_argument argument)
   }
   rtems_resource_snapshot_take(&snapshot);
   rtems_test_assert(
-    snapshot.posix_api.active_mutexes ==
-    (CONFIGURE_MAXIMUM_POSIX_MUTEXES + CONFIGURE_MAXIMUM_POSIX_INTERNAL_MUTEXES)
+    snapshot.posix_api.active_mutexes == CONFIGURE_MAXIMUM_POSIX_MUTEXES
   );
 #endif
 
-- 
1.7.7




More information about the devel mailing list