forked from Imagelibrary/rtems
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.
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
57
cpukit/posix/include/rtems/posix/onceimpl.h
Normal file
57
cpukit/posix/include/rtems/posix/onceimpl.h
Normal file
@@ -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 */
|
||||
@@ -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
|
||||
|
||||
49
cpukit/posix/src/once.c
Normal file
49
cpukit/posix/src/once.c
Normal file
@@ -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 );
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1694,6 +1694,11 @@ const rtems_libio_helper rtems_fs_init_helper =
|
||||
#include <rtems/posix/threadsup.h>
|
||||
#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 +
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user