From c090db7405b72ce6d0b726c0a39fb1c1aebab7ea Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 12 Sep 2017 08:09:16 +0200 Subject: posix: Implement self-contained POSIX semaphores For semaphore object pointer and object validation see POSIX_SEMAPHORE_VALIDATE_OBJECT(). Destruction or close of a busy semaphore returns an error status. The object is not flushed. POSIX semaphores are now available in all configurations and no longer depend on --enable-posix. Update #2514. Update #3116. --- cpukit/posix/Makefile.am | 24 ++++-- cpukit/posix/include/rtems/posix/semaphore.h | 18 +--- cpukit/posix/include/rtems/posix/semaphoreimpl.h | 82 +++++++++--------- cpukit/posix/preinstall.am | 16 ++-- cpukit/posix/src/semaphore.c | 14 +--- cpukit/posix/src/semaphorecreatesupp.c | 102 ----------------------- cpukit/posix/src/semaphoredeletesupp.c | 13 +-- cpukit/posix/src/semaphorewaitsupp.c | 53 ------------ cpukit/posix/src/semclose.c | 33 ++++---- cpukit/posix/src/semdestroy.c | 31 ++----- cpukit/posix/src/semgetvalue.c | 33 +++----- cpukit/posix/src/seminit.c | 28 +------ cpukit/posix/src/semopen.c | 86 +++++++++++++------ cpukit/posix/src/sempost.c | 60 ++++++++----- cpukit/posix/src/semtimedwait.c | 97 ++++++++++----------- cpukit/posix/src/semtrywait.c | 36 ++++---- cpukit/posix/src/semunlink.c | 13 +-- cpukit/posix/src/semwait.c | 18 +--- cpukit/sapi/src/posixapi.c | 25 ++++++ cpukit/score/Makefile.am | 1 + cpukit/score/include/rtems/score/semaphoreimpl.h | 73 ++++++++++++++++ cpukit/score/preinstall.am | 4 + cpukit/score/src/semaphore.c | 73 +++------------- 23 files changed, 412 insertions(+), 521 deletions(-) delete mode 100644 cpukit/posix/src/semaphorecreatesupp.c delete mode 100644 cpukit/posix/src/semaphorewaitsupp.c create mode 100644 cpukit/score/include/rtems/score/semaphoreimpl.h (limited to 'cpukit') diff --git a/cpukit/posix/Makefile.am b/cpukit/posix/Makefile.am index 3bb5bd29f9..1d9e209101 100644 --- a/cpukit/posix/Makefile.am +++ b/cpukit/posix/Makefile.am @@ -21,6 +21,8 @@ include_rtems_posix_HEADERS += include/rtems/posix/keyimpl.h include_rtems_posix_HEADERS += include/rtems/posix/config.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/semaphore.h +include_rtems_posix_HEADERS += include/rtems/posix/semaphoreimpl.h include_rtems_posix_HEADERS += include/rtems/posix/spinlockimpl.h if HAS_PTHREADS @@ -44,8 +46,6 @@ include_rtems_posix_HEADERS += include/rtems/posix/pthreadimpl.h include_rtems_posix_HEADERS += include/rtems/posix/ptimer.h include_rtems_posix_HEADERS += include/rtems/posix/shm.h include_rtems_posix_HEADERS += include/rtems/posix/shmimpl.h -include_rtems_posix_HEADERS += include/rtems/posix/semaphore.h -include_rtems_posix_HEADERS += include/rtems/posix/semaphoreimpl.h include_rtems_posix_HEADERS += include/rtems/posix/threadsup.h include_rtems_posix_HEADERS += include/rtems/posix/timer.h include_rtems_posix_HEADERS += include/rtems/posix/timerimpl.h @@ -186,6 +186,15 @@ libposix_a_SOURCES += src/pspininit.c libposix_a_SOURCES += src/pspinlock.c libposix_a_SOURCES += src/pspinunlock.c +## SEMAPHORE_C_FILES +libposix_a_SOURCES += src/semdestroy.c +libposix_a_SOURCES += src/semgetvalue.c +libposix_a_SOURCES += src/seminit.c +libposix_a_SOURCES += src/sempost.c +libposix_a_SOURCES += src/semtimedwait.c +libposix_a_SOURCES += src/semtrywait.c +libposix_a_SOURCES += src/semwait.c + if HAS_PTHREADS libposix_a_SOURCES += src/sigpending.c \ src/sigqueue.c src/sigsuspend.c src/sigtimedwait.c \ @@ -199,12 +208,11 @@ libposix_a_SOURCES += src/prwlock.c src/prwlockdestroy.c src/prwlockinit.c \ src/rwlockattrinit.c src/rwlockattrsetpshared.c ## SEMAPHORE_C_FILES -libposix_a_SOURCES += src/semaphore.c src/semaphorecreatesupp.c \ - src/semaphoredeletesupp.c \ - src/semaphorewaitsupp.c \ - src/semclose.c src/semdestroy.c src/semgetvalue.c src/seminit.c \ - src/semopen.c src/sempost.c src/semtimedwait.c src/semtrywait.c \ - src/semunlink.c src/semwait.c +libposix_a_SOURCES += src/semaphore.c +libposix_a_SOURCES += src/semaphoredeletesupp.c +libposix_a_SOURCES += src/semclose.c +libposix_a_SOURCES += src/semopen.c +libposix_a_SOURCES += src/semunlink.c ## TIME_C_FILES libposix_a_SOURCES += src/adjtime.c src/clockgetcpuclockid.c diff --git a/cpukit/posix/include/rtems/posix/semaphore.h b/cpukit/posix/include/rtems/posix/semaphore.h index 6598397052..9133db22be 100644 --- a/cpukit/posix/include/rtems/posix/semaphore.h +++ b/cpukit/posix/include/rtems/posix/semaphore.h @@ -21,7 +21,6 @@ #include #include -#include #ifdef __cplusplus extern "C" { @@ -41,19 +40,10 @@ extern "C" { */ typedef struct { - Objects_Control Object; - CORE_semaphore_Control Semaphore; - bool named; - bool linked; - uint32_t open_count; - /* - * sem_t is 32-bit. If Object_Id is 16-bit, then they are not - * interchangeable. We have to be able to return a pointer to - * a 32-bit form of the 16-bit Id. - */ - #if defined(RTEMS_USE_16_BIT_OBJECT) - sem_t Semaphore_id; - #endif + Objects_Control Object; + sem_t Semaphore; + bool linked; + uint32_t open_count; } POSIX_Semaphore_Control; /** @} */ diff --git a/cpukit/posix/include/rtems/posix/semaphoreimpl.h b/cpukit/posix/include/rtems/posix/semaphoreimpl.h index 43440298ec..fd17743699 100644 --- a/cpukit/posix/include/rtems/posix/semaphoreimpl.h +++ b/cpukit/posix/include/rtems/posix/semaphoreimpl.h @@ -21,21 +21,25 @@ #include #include -#include +#include #include #ifdef __cplusplus extern "C" { #endif +/** + * @brief This is a random number used to check if a semaphore object is + * properly initialized. + */ +#define POSIX_SEMAPHORE_MAGIC 0x5d367fe7UL + /** * This defines the information control block used to manage * this class of objects. */ extern Objects_Information _POSIX_Semaphore_Information; -#define POSIX_SEMAPHORE_TQ_OPERATIONS &_Thread_queue_Operations_FIFO - RTEMS_INLINE_ROUTINE POSIX_Semaphore_Control * _POSIX_Semaphore_Allocate_unprotected( void ) { @@ -57,53 +61,45 @@ RTEMS_INLINE_ROUTINE void _POSIX_Semaphore_Free ( } RTEMS_INLINE_ROUTINE POSIX_Semaphore_Control *_POSIX_Semaphore_Get( - const sem_t *id, - Thread_queue_Context *queue_context + sem_t *sem ) { - _Thread_queue_Context_initialize( queue_context ); - return (POSIX_Semaphore_Control *) _Objects_Get( - (Objects_Id) *id, - &queue_context->Lock_context.Lock_context, - &_POSIX_Semaphore_Information - ); + return RTEMS_CONTAINER_OF( sem, POSIX_Semaphore_Control, Semaphore ); } -/** - * @brief POSIX Semaphore Create Support - * - * This routine supports the sem_init and sem_open routines. - */ +RTEMS_INLINE_ROUTINE bool _POSIX_Semaphore_Is_named( const sem_t *sem ) +{ + return sem->_Semaphore._Queue._name != NULL; +} -int _POSIX_Semaphore_Create_support( - const char *name, - size_t name_len, - unsigned int value, - POSIX_Semaphore_Control **the_sem -); +RTEMS_INLINE_ROUTINE bool _POSIX_Semaphore_Is_busy( const sem_t *sem ) +{ + return sem->_Semaphore._Queue._heads != NULL; +} + +RTEMS_INLINE_ROUTINE void _POSIX_Semaphore_Initialize( + sem_t *sem, + const char *name, + unsigned int value +) +{ + sem->_flags = (uintptr_t) sem ^ POSIX_SEMAPHORE_MAGIC; + _Semaphore_Initialize_named( &sem->_Semaphore, name, value ); +} + +RTEMS_INLINE_ROUTINE void _POSIX_Semaphore_Destroy( sem_t *sem ) +{ + sem->_flags = 0; + _Semaphore_Destroy( &sem->_Semaphore ); +} /** * @brief POSIX Semaphore Delete * * This routine supports the sem_close and sem_unlink routines. */ -void _POSIX_Semaphore_Delete( - POSIX_Semaphore_Control *the_semaphore, - Thread_queue_Context *queue_context -); +void _POSIX_Semaphore_Delete( POSIX_Semaphore_Control *the_semaphore ); -/** - * @brief POSIX semaphore wait support. - * - * This routine supports the sem_wait, sem_trywait, and sem_timedwait - * services. - */ -int _POSIX_Semaphore_Wait_support( - sem_t *sem, - bool blocking, - Watchdog_Interval timeout -); - /** * @brief POSIX Semaphore Namespace Remove */ @@ -129,6 +125,16 @@ RTEMS_INLINE_ROUTINE POSIX_Semaphore_Control *_POSIX_Semaphore_Get_by_name( ); } +#define POSIX_SEMAPHORE_VALIDATE_OBJECT( sem ) \ + do { \ + if ( \ + ( sem ) == NULL \ + || ( (uintptr_t) ( sem ) ^ POSIX_SEMAPHORE_MAGIC ) != ( sem )->_flags \ + ) { \ + rtems_set_errno_and_return_minus_one( EINVAL ); \ + } \ + } while ( 0 ) + #ifdef __cplusplus } #endif diff --git a/cpukit/posix/preinstall.am b/cpukit/posix/preinstall.am index cfb087c923..d67f9face8 100644 --- a/cpukit/posix/preinstall.am +++ b/cpukit/posix/preinstall.am @@ -47,6 +47,14 @@ $(PROJECT_INCLUDE)/rtems/posix/priorityimpl.h: include/rtems/posix/priorityimpl. $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/priorityimpl.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/priorityimpl.h +$(PROJECT_INCLUDE)/rtems/posix/semaphore.h: include/rtems/posix/semaphore.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/semaphore.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/semaphore.h + +$(PROJECT_INCLUDE)/rtems/posix/semaphoreimpl.h: include/rtems/posix/semaphoreimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/semaphoreimpl.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/semaphoreimpl.h + $(PROJECT_INCLUDE)/rtems/posix/spinlockimpl.h: include/rtems/posix/spinlockimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/spinlockimpl.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/spinlockimpl.h @@ -120,14 +128,6 @@ $(PROJECT_INCLUDE)/rtems/posix/shmimpl.h: include/rtems/posix/shmimpl.h $(PROJEC $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/shmimpl.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/shmimpl.h -$(PROJECT_INCLUDE)/rtems/posix/semaphore.h: include/rtems/posix/semaphore.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/semaphore.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/semaphore.h - -$(PROJECT_INCLUDE)/rtems/posix/semaphoreimpl.h: include/rtems/posix/semaphoreimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/semaphoreimpl.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/semaphoreimpl.h - $(PROJECT_INCLUDE)/rtems/posix/threadsup.h: include/rtems/posix/threadsup.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/threadsup.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/threadsup.h diff --git a/cpukit/posix/src/semaphore.c b/cpukit/posix/src/semaphore.c index 661456c748..a82ad17966 100644 --- a/cpukit/posix/src/semaphore.c +++ b/cpukit/posix/src/semaphore.c @@ -18,19 +18,11 @@ #include "config.h" #endif -#include - -#include -#include -#include -#include -#include - -#include +#include #include #include -#include -#include + +#include Objects_Information _POSIX_Semaphore_Information; diff --git a/cpukit/posix/src/semaphorecreatesupp.c b/cpukit/posix/src/semaphorecreatesupp.c deleted file mode 100644 index 4a33336230..0000000000 --- a/cpukit/posix/src/semaphorecreatesupp.c +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @file - * - * @brief Function does Actual creation and Initialization of POSIX Semaphore - * @ingroup POSIXAPI - */ - -/* - * COPYRIGHT (c) 1989-2009. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include -#include -#include -#include -#include -#include /* strlen */ - -#include -#include -#include -#include - -/* - * _POSIX_Semaphore_Create_support - * - * This routine does the actual creation and initialization of - * a poxix semaphore. It is a support routine for sem_init and - * sem_open. - */ -int _POSIX_Semaphore_Create_support( - const char *name_arg, - size_t name_len, - unsigned int value, - POSIX_Semaphore_Control **the_sem -) -{ - POSIX_Semaphore_Control *the_semaphore; - char *name; - - /* - * Make a copy of the user's string for name just in case it was - * dynamically constructed. - */ - if ( name_arg != NULL ) { - name = _Workspace_String_duplicate( name_arg, name_len ); - if ( !name ) { - rtems_set_errno_and_return_minus_one( ENOMEM ); - } - } else { - name = NULL; - } - - the_semaphore = _POSIX_Semaphore_Allocate_unprotected(); - if ( !the_semaphore ) { - _Workspace_Free( name ); - rtems_set_errno_and_return_minus_one( ENOSPC ); - } - - if ( name ) { - the_semaphore->named = true; - the_semaphore->open_count = 1; - the_semaphore->linked = true; - } else { - the_semaphore->named = false; - the_semaphore->open_count = 0; - the_semaphore->linked = false; - } - - /* - * POSIX does not appear to specify what the discipline for - * blocking tasks on this semaphore should be. It could somehow - * be derived from the current scheduling policy. One - * thing is certain, no matter what we decide, it won't be - * the same as all other POSIX implementations. :) - */ - _CORE_semaphore_Initialize( &the_semaphore->Semaphore, value ); - - /* - * Make the semaphore available for use. - */ - _Objects_Open_string( - &_POSIX_Semaphore_Information, - &the_semaphore->Object, - name - ); - - *the_sem = the_semaphore; - - return 0; -} diff --git a/cpukit/posix/src/semaphoredeletesupp.c b/cpukit/posix/src/semaphoredeletesupp.c index 325e4a6c1b..dbcfebfd65 100644 --- a/cpukit/posix/src/semaphoredeletesupp.c +++ b/cpukit/posix/src/semaphoredeletesupp.c @@ -20,20 +20,11 @@ #include -void _POSIX_Semaphore_Delete( - POSIX_Semaphore_Control *the_semaphore, - Thread_queue_Context *queue_context -) +void _POSIX_Semaphore_Delete( POSIX_Semaphore_Control *the_semaphore ) { if ( !the_semaphore->linked && !the_semaphore->open_count ) { _Objects_Close( &_POSIX_Semaphore_Information, &the_semaphore->Object ); - _CORE_semaphore_Destroy( - &the_semaphore->Semaphore, - POSIX_SEMAPHORE_TQ_OPERATIONS, - queue_context - ); + _POSIX_Semaphore_Destroy( &the_semaphore->Semaphore ); _POSIX_Semaphore_Free( the_semaphore ); - } else { - _CORE_semaphore_Release( &the_semaphore->Semaphore, queue_context ); } } diff --git a/cpukit/posix/src/semaphorewaitsupp.c b/cpukit/posix/src/semaphorewaitsupp.c deleted file mode 100644 index a4c43fd704..0000000000 --- a/cpukit/posix/src/semaphorewaitsupp.c +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file - * - * @brief POSIX Semaphore Wait Support - * @ingroup POSIXSemaphorePrivate - */ - -/* - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include -#include - -THREAD_QUEUE_OBJECT_ASSERT( POSIX_Semaphore_Control, Semaphore.Wait_queue ); - -int _POSIX_Semaphore_Wait_support( - sem_t *sem, - bool blocking, - Watchdog_Interval timeout -) -{ - POSIX_Semaphore_Control *the_semaphore; - Thread_queue_Context queue_context; - Status_Control status; - - the_semaphore = _POSIX_Semaphore_Get( sem, &queue_context ); - - if ( the_semaphore == NULL ) { - rtems_set_errno_and_return_minus_one( EINVAL ); - } - - _Thread_queue_Context_set_relative_timeout( &queue_context, timeout ); - status = _CORE_semaphore_Seize( - &the_semaphore->Semaphore, - POSIX_SEMAPHORE_TQ_OPERATIONS, - _Thread_Executing, - blocking, - &queue_context - ); - return _POSIX_Zero_or_minus_one_plus_errno( status ); -} diff --git a/cpukit/posix/src/semclose.c b/cpukit/posix/src/semclose.c index ebcf7a26b3..a27b165350 100644 --- a/cpukit/posix/src/semclose.c +++ b/cpukit/posix/src/semclose.c @@ -18,32 +18,37 @@ #include "config.h" #endif -#include - #include -int sem_close( - sem_t *sem -) +int sem_close( sem_t *sem ) { POSIX_Semaphore_Control *the_semaphore; - Thread_queue_Context queue_context; + uint32_t open_count; + + POSIX_SEMAPHORE_VALIDATE_OBJECT( sem ); + + if ( !_POSIX_Semaphore_Is_named( sem ) ) { + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + the_semaphore = _POSIX_Semaphore_Get( sem ); _Objects_Allocator_lock(); - the_semaphore = _POSIX_Semaphore_Get( sem, &queue_context ); - if ( the_semaphore == NULL ) { + open_count = the_semaphore->open_count; + + if ( open_count == 0 ) { _Objects_Allocator_unlock(); rtems_set_errno_and_return_minus_one( EINVAL ); } - _CORE_semaphore_Acquire_critical( - &the_semaphore->Semaphore, - &queue_context - ); - the_semaphore->open_count -= 1; - _POSIX_Semaphore_Delete( the_semaphore, &queue_context ); + if ( open_count == 1 && _POSIX_Semaphore_Is_busy( sem ) ) { + _Objects_Allocator_unlock(); + rtems_set_errno_and_return_minus_one( EBUSY ); + } + the_semaphore->open_count = open_count - 1; + _POSIX_Semaphore_Delete( the_semaphore ); _Objects_Allocator_unlock(); return 0; } diff --git a/cpukit/posix/src/semdestroy.c b/cpukit/posix/src/semdestroy.c index 8b81470bbf..61f5b1e80f 100644 --- a/cpukit/posix/src/semdestroy.c +++ b/cpukit/posix/src/semdestroy.c @@ -18,39 +18,20 @@ #include "config.h" #endif -#include - #include -int sem_destroy( - sem_t *sem -) +int sem_destroy( sem_t *sem ) { - POSIX_Semaphore_Control *the_semaphore; - Thread_queue_Context queue_context; - - _Objects_Allocator_lock(); - the_semaphore = _POSIX_Semaphore_Get( sem, &queue_context ); + POSIX_SEMAPHORE_VALIDATE_OBJECT( sem ); - if ( the_semaphore == NULL ) { - _Objects_Allocator_unlock(); + if ( _POSIX_Semaphore_Is_named( sem ) ) { rtems_set_errno_and_return_minus_one( EINVAL ); } - _CORE_semaphore_Acquire_critical( - &the_semaphore->Semaphore, - &queue_context - ); - - if ( the_semaphore->named ) { - /* Undefined operation on a named semaphore */ - _CORE_semaphore_Release( &the_semaphore->Semaphore, &queue_context ); - _Objects_Allocator_unlock(); - rtems_set_errno_and_return_minus_one( EINVAL ); + if ( _POSIX_Semaphore_Is_busy( sem ) ) { + rtems_set_errno_and_return_minus_one( EBUSY ); } - _POSIX_Semaphore_Delete( the_semaphore, &queue_context ); - - _Objects_Allocator_unlock(); + _POSIX_Semaphore_Destroy( sem ); return 0; } diff --git a/cpukit/posix/src/semgetvalue.c b/cpukit/posix/src/semgetvalue.c index 1b752944fa..f0242f2ca8 100644 --- a/cpukit/posix/src/semgetvalue.c +++ b/cpukit/posix/src/semgetvalue.c @@ -18,31 +18,24 @@ #include "config.h" #endif -#include - #include int sem_getvalue( - sem_t *__restrict sem, + sem_t *__restrict _sem, int *__restrict sval ) { - POSIX_Semaphore_Control *the_semaphore; - Thread_queue_Context queue_context; - - the_semaphore = _POSIX_Semaphore_Get( sem, &queue_context ); - - if ( the_semaphore == NULL ) { - rtems_set_errno_and_return_minus_one( EINVAL ); - } - - _CORE_semaphore_Acquire_critical( - &the_semaphore->Semaphore, - &queue_context - ); - - *sval = _CORE_semaphore_Get_count( &the_semaphore->Semaphore ); - - _CORE_semaphore_Release( &the_semaphore->Semaphore, &queue_context ); + Sem_Control *sem; + ISR_Level level; + Thread_queue_Context queue_context; + + POSIX_SEMAPHORE_VALIDATE_OBJECT( _sem ); + + sem = _Sem_Get( &_sem->_Semaphore ); + _Thread_queue_Context_initialize( &queue_context ); + _Thread_queue_Context_ISR_disable( &queue_context, level ); + _Sem_Queue_acquire_critical( sem, &queue_context ); + *sval = (int) sem->count; + _Sem_Queue_release( sem, level, &queue_context ); return 0; } diff --git a/cpukit/posix/src/seminit.c b/cpukit/posix/src/seminit.c index cf06f6ce41..65104ad2c7 100644 --- a/cpukit/posix/src/seminit.c +++ b/cpukit/posix/src/seminit.c @@ -18,17 +18,11 @@ #include "config.h" #endif -#include +#include -#include -#include -#include -#include #include -#include -#include -#include +RTEMS_STATIC_ASSERT(NULL == SEM_FAILED, sem_failed); /* * 11.2.1 Initialize an Unnamed Semaphore, P1003.1b-1993, p.219 @@ -40,9 +34,6 @@ int sem_init( unsigned int value ) { - int status; - POSIX_Semaphore_Control *the_semaphore; - if ( sem == NULL ) { rtems_set_errno_and_return_minus_one( EINVAL ); } @@ -51,17 +42,6 @@ int sem_init( rtems_set_errno_and_return_minus_one( EINVAL ); } - _Objects_Allocator_lock(); - status = _POSIX_Semaphore_Create_support( - NULL, - 0, - value, - &the_semaphore - ); - _Objects_Allocator_unlock(); - - if ( status != -1 ) - *sem = the_semaphore->Object.id; - - return status; + _POSIX_Semaphore_Initialize( sem, NULL, value ); + return 0; } diff --git a/cpukit/posix/src/semopen.c b/cpukit/posix/src/semopen.c index 98163cca8d..63915fca57 100644 --- a/cpukit/posix/src/semopen.c +++ b/cpukit/posix/src/semopen.c @@ -18,17 +18,64 @@ #include "config.h" #endif -#include +#include +#include -#include +#include #include -#include -#include #include -#include -#include -#include +static sem_t *_POSIX_Semaphore_Create_support( + const char *name_arg, + size_t name_len, + unsigned int value +) +{ + POSIX_Semaphore_Control *the_semaphore; + char *name; + + if ( value > SEM_VALUE_MAX ) { + rtems_set_errno_and_return_value( EINVAL, SEM_FAILED ); + } + + /* + * Make a copy of the user's string for name just in case it was + * dynamically constructed. + */ + name = _Workspace_String_duplicate( name_arg, name_len ); + if ( name == NULL ) { + rtems_set_errno_and_return_value( ENOMEM, SEM_FAILED ); + } + + the_semaphore = _POSIX_Semaphore_Allocate_unprotected(); + if ( the_semaphore == NULL ) { + _Workspace_Free( name ); + rtems_set_errno_and_return_value( ENOSPC, SEM_FAILED ); + } + + the_semaphore->open_count = 1; + the_semaphore->linked = true; + + /* + * POSIX does not appear to specify what the discipline for + * blocking tasks on this semaphore should be. It could somehow + * be derived from the current scheduling policy. One + * thing is certain, no matter what we decide, it won't be + * the same as all other POSIX implementations. :) + */ + _POSIX_Semaphore_Initialize( &the_semaphore->Semaphore, name, value ); + + /* + * Make the semaphore available for use. + */ + _Objects_Open_string( + &_POSIX_Semaphore_Information, + &the_semaphore->Object, + name + ); + + return &the_semaphore->Semaphore; +} /* * sem_open @@ -59,10 +106,10 @@ sem_t *sem_open( va_list arg; unsigned int value = 0; - int status; POSIX_Semaphore_Control *the_semaphore; size_t name_len; Objects_Get_by_name_error error; + sem_t *sem; if ( oflag & O_CREAT ) { va_start(arg, oflag); @@ -108,7 +155,7 @@ sem_t *sem_open( the_semaphore->open_count += 1; _Objects_Allocator_unlock(); - goto return_id; + return &the_semaphore->Semaphore; } /* @@ -116,27 +163,12 @@ sem_t *sem_open( * checked. We should go ahead and create a semaphore. */ - status =_POSIX_Semaphore_Create_support( + sem = _POSIX_Semaphore_Create_support( name, name_len, - value, - &the_semaphore + value ); - /* - * errno was set by Create_support, so don't set it again. - */ - _Objects_Allocator_unlock(); - - if ( status != 0 ) - return SEM_FAILED; - -return_id: - #if defined(RTEMS_USE_16_BIT_OBJECT) - the_semaphore->Semaphore_id = the_semaphore->Object.id; - return &the_semaphore->Semaphore_id; - #else - return &the_semaphore->Object.id; - #endif + return sem; } diff --git a/cpukit/posix/src/sempost.c b/cpukit/posix/src/sempost.c index da2b1a5495..de0ae71fc7 100644 --- a/cpukit/posix/src/sempost.c +++ b/cpukit/posix/src/sempost.c @@ -18,31 +18,51 @@ #include "config.h" #endif -#include -#include - #include -#include -int sem_post( - sem_t *sem -) +#include + +int sem_post( sem_t *_sem ) { - POSIX_Semaphore_Control *the_semaphore; - Thread_queue_Context queue_context; - Status_Control status; + Sem_Control *sem; + ISR_Level level; + Thread_queue_Context queue_context; + Thread_queue_Heads *heads; + unsigned int count; + + POSIX_SEMAPHORE_VALIDATE_OBJECT( _sem ); + + sem = _Sem_Get( &_sem->_Semaphore ); + _Thread_queue_Context_initialize( &queue_context ); + _Thread_queue_Context_ISR_disable( &queue_context, level ); + _Sem_Queue_acquire_critical( sem, &queue_context ); + + heads = sem->Queue.Queue.heads; + count = sem->count; + + if ( __predict_true( heads == NULL && count < SEM_VALUE_MAX ) ) { + sem->count = count + 1; + _Sem_Queue_release( sem, level, &queue_context ); + return 0; + } + + if ( __predict_true( heads != NULL ) ) { + const Thread_queue_Operations *operations; + Thread_Control *first; - the_semaphore = _POSIX_Semaphore_Get( sem, &queue_context ); + _Thread_queue_Context_set_ISR_level( &queue_context, level ); + operations = SEMAPHORE_TQ_OPERATIONS; + first = ( *operations->first )( heads ); - if ( the_semaphore == NULL ) { - rtems_set_errno_and_return_minus_one( EINVAL ); + _Thread_queue_Extract_critical( + &sem->Queue.Queue, + operations, + first, + &queue_context + ); + return 0; } - status = _CORE_semaphore_Surrender( - &the_semaphore->Semaphore, - POSIX_SEMAPHORE_TQ_OPERATIONS, - SEM_VALUE_MAX, - &queue_context - ); - return _POSIX_Zero_or_minus_one_plus_errno( status ); + _Sem_Queue_release( sem, level, &queue_context ); + rtems_set_errno_and_return_minus_one( EOVERFLOW ); } diff --git a/cpukit/posix/src/semtimedwait.c b/cpukit/posix/src/semtimedwait.c index 09028f4d08..f00557c38d 100644 --- a/cpukit/posix/src/semtimedwait.c +++ b/cpukit/posix/src/semtimedwait.c @@ -18,18 +18,8 @@ #include "config.h" #endif -#include - -#include -#include -#include -#include -#include - -#include -#include #include -#include +#include /* * 11.2.6 Lock a Semaphore, P1003.1b-1993, p.226 @@ -38,47 +28,60 @@ */ int sem_timedwait( - sem_t *__restrict sem, + sem_t *__restrict _sem, const struct timespec *__restrict abstime ) { - Watchdog_Interval ticks; - bool do_wait = true; - TOD_Absolute_timeout_conversion_results status; - int lock_status; + Sem_Control *sem; + Thread_queue_Context queue_context; + ISR_Level level; + Thread_Control *executing; + unsigned int count; - /* - * POSIX requires that blocking calls with timeouts that take - * an absolute timeout must ignore issues with the absolute - * time provided if the operation would otherwise succeed. - * So we check the abstime provided, and hold on to whether it - * is valid or not. If it isn't correct and in the future, - * then we do a polling operation and convert the UNSATISFIED - * status into the appropriate error. - * - * If the status is TOD_ABSOLUTE_TIMEOUT_INVALID, - * TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST, or TOD_ABSOLUTE_TIMEOUT_IS_NOW, - * then we should not wait. - */ - status = _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ); - if ( status != TOD_ABSOLUTE_TIMEOUT_IS_IN_FUTURE ) - do_wait = false; + POSIX_SEMAPHORE_VALIDATE_OBJECT( _sem ); - lock_status = _POSIX_Semaphore_Wait_support( sem, do_wait, ticks ); + sem = _Sem_Get( &_sem->_Semaphore ); + _Thread_queue_Context_initialize( &queue_context ); + _Thread_queue_Context_ISR_disable( &queue_context, level ); + executing = _Sem_Queue_acquire_critical( sem, &queue_context ); - /* - * This service only gives us the option to block. We used a polling - * attempt to obtain if the abstime was not in the future. If we did - * not obtain the semaphore, then not look at the status immediately, - * make sure the right reason is returned. - */ - if ( !do_wait && (lock_status == EBUSY) ) { - if ( lock_status == TOD_ABSOLUTE_TIMEOUT_INVALID ) - rtems_set_errno_and_return_minus_one( EINVAL ); - if ( lock_status == TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST || - lock_status == TOD_ABSOLUTE_TIMEOUT_IS_NOW ) - rtems_set_errno_and_return_minus_one( ETIMEDOUT ); - } + count = sem->count; + if ( __predict_true( count > 0 ) ) { + sem->count = count - 1; + _Sem_Queue_release( sem, level, &queue_context ); + return 0; + } else { + Watchdog_Interval ticks; + Status_Control status; + + switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) { + case TOD_ABSOLUTE_TIMEOUT_INVALID: + _Sem_Queue_release( sem, level, &queue_context ); + rtems_set_errno_and_return_minus_one( EINVAL ); + break; + case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST: + case TOD_ABSOLUTE_TIMEOUT_IS_NOW: + _Sem_Queue_release( sem, level, &queue_context ); + rtems_set_errno_and_return_minus_one( ETIMEDOUT ); + break; + default: + break; + } - return lock_status; + _Thread_queue_Context_set_thread_state( + &queue_context, + STATES_WAITING_FOR_SEMAPHORE + ); + _Thread_queue_Context_set_do_nothing_enqueue_callout( &queue_context ); + _Thread_queue_Context_set_relative_timeout( &queue_context, ticks ); + _Thread_queue_Context_set_ISR_level( &queue_context, level ); + _Thread_queue_Enqueue( + &sem->Queue.Queue, + SEMAPHORE_TQ_OPERATIONS, + executing, + &queue_context + ); + status = _Thread_Wait_get_status( executing ); + return _POSIX_Zero_or_minus_one_plus_errno( status ); + } } diff --git a/cpukit/posix/src/semtrywait.c b/cpukit/posix/src/semtrywait.c index a6836d8eaf..673343d4b4 100644 --- a/cpukit/posix/src/semtrywait.c +++ b/cpukit/posix/src/semtrywait.c @@ -18,21 +18,29 @@ #include "config.h" #endif -#include - -#include -#include -#include -#include -#include - -#include #include -#include -int sem_trywait( - sem_t *sem -) +int sem_trywait( sem_t *_sem ) { - return _POSIX_Semaphore_Wait_support(sem, false, WATCHDOG_NO_TIMEOUT); + Sem_Control *sem; + Thread_queue_Context queue_context; + ISR_Level level; + unsigned int count; + + POSIX_SEMAPHORE_VALIDATE_OBJECT( _sem ); + + sem = _Sem_Get( &_sem->_Semaphore ); + _Thread_queue_Context_initialize( &queue_context ); + _Thread_queue_Context_ISR_disable( &queue_context, level ); + _Sem_Queue_acquire_critical( sem, &queue_context ); + + count = sem->count; + if ( __predict_true( count > 0 ) ) { + sem->count = count - 1; + _Sem_Queue_release( sem, level, &queue_context ); + return 0; + } else { + _Sem_Queue_release( sem, level, &queue_context ); + rtems_set_errno_and_return_minus_one( EAGAIN ); + } } diff --git a/cpukit/posix/src/semunlink.c b/cpukit/posix/src/semunlink.c index 02fcdcab1b..2abc8f9435 100644 --- a/cpukit/posix/src/semunlink.c +++ b/cpukit/posix/src/semunlink.c @@ -18,17 +18,12 @@ #include "config.h" #endif -#include - #include -int sem_unlink( - const char *name -) +int sem_unlink( const char *name ) { POSIX_Semaphore_Control *the_semaphore; Objects_Get_by_name_error error; - Thread_queue_Context queue_context; _Objects_Allocator_lock(); @@ -39,12 +34,8 @@ int sem_unlink( } _POSIX_Semaphore_Namespace_remove( the_semaphore ); - - _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context ); - _CORE_semaphore_Acquire_critical( &the_semaphore->Semaphore, &queue_context ); the_semaphore->linked = false; - _POSIX_Semaphore_Delete( the_semaphore, &queue_context ); - + _POSIX_Semaphore_Delete( the_semaphore ); _Objects_Allocator_unlock(); return 0; } diff --git a/cpukit/posix/src/semwait.c b/cpukit/posix/src/semwait.c index 30cf5ad344..0353af4029 100644 --- a/cpukit/posix/src/semwait.c +++ b/cpukit/posix/src/semwait.c @@ -18,21 +18,11 @@ #include "config.h" #endif -#include - -#include -#include -#include -#include -#include - -#include #include -#include -int sem_wait( - sem_t *sem -) +int sem_wait( sem_t *sem ) { - return _POSIX_Semaphore_Wait_support( sem, true, WATCHDOG_NO_TIMEOUT ); + POSIX_SEMAPHORE_VALIDATE_OBJECT( sem ); + _Semaphore_Wait( &sem->_Semaphore ); + return 0; } diff --git a/cpukit/sapi/src/posixapi.c b/cpukit/sapi/src/posixapi.c index e7d34fdf60..ef725bea96 100644 --- a/cpukit/sapi/src/posixapi.c +++ b/cpukit/sapi/src/posixapi.c @@ -20,6 +20,31 @@ #endif #include +#include +#include + +#ifdef HEAP_PROTECTION +RTEMS_STATIC_ASSERT( + POSIX_SEMAPHORE_MAGIC != HEAP_BEGIN_PROTECTOR_0, + POSIX_SEMAPHORE_MAGIC_0 +); +RTEMS_STATIC_ASSERT( + POSIX_SEMAPHORE_MAGIC != HEAP_BEGIN_PROTECTOR_1, + POSIX_SEMAPHORE_MAGIC_1 +); +RTEMS_STATIC_ASSERT( + POSIX_SEMAPHORE_MAGIC != HEAP_END_PROTECTOR_0, + POSIX_SEMAPHORE_MAGIC_2 +); +RTEMS_STATIC_ASSERT( + POSIX_SEMAPHORE_MAGIC != HEAP_END_PROTECTOR_1, + POSIX_SEMAPHORE_MAGIC_3 +); +RTEMS_STATIC_ASSERT( + POSIX_SEMAPHORE_MAGIC != HEAP_FREE_PATTERN, + POSIX_SEMAPHORE_MAGIC_4 +); +#endif void _POSIX_Fatal_error( POSIX_Fatal_domain domain, int eno ) { diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index d2dd80d6f0..03a15e3b09 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -80,6 +80,7 @@ include_rtems_score_HEADERS += include/rtems/score/schedulersimple.h include_rtems_score_HEADERS += include/rtems/score/schedulersimpleimpl.h include_rtems_score_HEADERS += include/rtems/score/schedulersmp.h include_rtems_score_HEADERS += include/rtems/score/schedulersmpimpl.h +include_rtems_score_HEADERS += include/rtems/score/semaphoreimpl.h include_rtems_score_HEADERS += include/rtems/score/smp.h include_rtems_score_HEADERS += include/rtems/score/smpbarrier.h include_rtems_score_HEADERS += include/rtems/score/smplock.h diff --git a/cpukit/score/include/rtems/score/semaphoreimpl.h b/cpukit/score/include/rtems/score/semaphoreimpl.h new file mode 100644 index 0000000000..a7857db93e --- /dev/null +++ b/cpukit/score/include/rtems/score/semaphoreimpl.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef _RTEMS_SCORE_SEMAPHOREIMPL_H +#define _RTEMS_SCORE_SEMAPHOREIMPL_H + +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct { + Thread_queue_Syslock_queue Queue; + unsigned int count; +} Sem_Control; + +#define SEMAPHORE_TQ_OPERATIONS &_Thread_queue_Operations_priority + +static inline Sem_Control *_Sem_Get( struct _Semaphore_Control *_sem ) +{ + return (Sem_Control *) _sem; +} + +static inline Thread_Control *_Sem_Queue_acquire_critical( + Sem_Control *sem, + Thread_queue_Context *queue_context +) +{ + Thread_Control *executing; + + executing = _Thread_Executing; + _Thread_queue_Queue_acquire_critical( + &sem->Queue.Queue, + &executing->Potpourri_stats, + &queue_context->Lock_context.Lock_context + ); + + return executing; +} + +static inline void _Sem_Queue_release( + Sem_Control *sem, + ISR_Level level, + Thread_queue_Context *queue_context +) +{ + _Thread_queue_Queue_release_critical( + &sem->Queue.Queue, + &queue_context->Lock_context.Lock_context + ); + _ISR_Local_enable( level ); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _RTEMS_SCORE_SEMAPHOREIMPL_H */ diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am index da231541b0..32356e3c4a 100644 --- a/cpukit/score/preinstall.am +++ b/cpukit/score/preinstall.am @@ -288,6 +288,10 @@ $(PROJECT_INCLUDE)/rtems/score/schedulersmpimpl.h: include/rtems/score/scheduler $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/schedulersmpimpl.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/schedulersmpimpl.h +$(PROJECT_INCLUDE)/rtems/score/semaphoreimpl.h: include/rtems/score/semaphoreimpl.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/semaphoreimpl.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/semaphoreimpl.h + $(PROJECT_INCLUDE)/rtems/score/smp.h: include/rtems/score/smp.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/smp.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/smp.h diff --git a/cpukit/score/src/semaphore.c b/cpukit/score/src/semaphore.c index 28a2f0a76d..e670367e86 100644 --- a/cpukit/score/src/semaphore.c +++ b/cpukit/score/src/semaphore.c @@ -16,92 +16,45 @@ #include "config.h" #endif -#include +#include +#include #include -#include -#include -#include - -#define SEMAPHORE_TQ_OPERATIONS &_Thread_queue_Operations_priority - -typedef struct { - Thread_queue_Syslock_queue Queue; - unsigned int count; -} Semaphore_Control; - RTEMS_STATIC_ASSERT( - offsetof( Semaphore_Control, Queue ) + offsetof( Sem_Control, Queue ) == offsetof( struct _Semaphore_Control, _Queue ), SEMAPHORE_CONTROL_QUEUE ); RTEMS_STATIC_ASSERT( - offsetof( Semaphore_Control, count ) + offsetof( Sem_Control, count ) == offsetof( struct _Semaphore_Control, _count ), SEMAPHORE_CONTROL_COUNT ); RTEMS_STATIC_ASSERT( - sizeof( Semaphore_Control ) == sizeof( struct _Semaphore_Control ), + sizeof( Sem_Control ) == sizeof( struct _Semaphore_Control ), SEMAPHORE_CONTROL_SIZE ); -static Semaphore_Control *_Semaphore_Get( - struct _Semaphore_Control *_sem -) -{ - return (Semaphore_Control *) _sem; -} - -static Thread_Control *_Semaphore_Queue_acquire_critical( - Semaphore_Control *sem, - Thread_queue_Context *queue_context -) -{ - Thread_Control *executing; - - executing = _Thread_Executing; - _Thread_queue_Queue_acquire_critical( - &sem->Queue.Queue, - &executing->Potpourri_stats, - &queue_context->Lock_context.Lock_context - ); - - return executing; -} - -static void _Semaphore_Queue_release( - Semaphore_Control *sem, - ISR_Level level, - Thread_queue_Context *queue_context -) -{ - _Thread_queue_Queue_release_critical( - &sem->Queue.Queue, - &queue_context->Lock_context.Lock_context - ); - _ISR_Local_enable( level ); -} - void _Semaphore_Wait( struct _Semaphore_Control *_sem ) { - Semaphore_Control *sem ; + Sem_Control *sem; ISR_Level level; Thread_queue_Context queue_context; Thread_Control *executing; unsigned int count; - sem = _Semaphore_Get( _sem ); + sem = _Sem_Get( _sem ); _Thread_queue_Context_initialize( &queue_context ); _Thread_queue_Context_ISR_disable( &queue_context, level ); - executing = _Semaphore_Queue_acquire_critical( sem, &queue_context ); + executing = _Sem_Queue_acquire_critical( sem, &queue_context ); count = sem->count; if ( __predict_true( count > 0 ) ) { sem->count = count - 1; - _Semaphore_Queue_release( sem, level, &queue_context ); + _Sem_Queue_release( sem, level, &queue_context ); } else { _Thread_queue_Context_set_thread_state( &queue_context, @@ -121,21 +74,21 @@ void _Semaphore_Wait( struct _Semaphore_Control *_sem ) void _Semaphore_Post( struct _Semaphore_Control *_sem ) { - Semaphore_Control *sem; + Sem_Control *sem; ISR_Level level; Thread_queue_Context queue_context; Thread_queue_Heads *heads; - sem = _Semaphore_Get( _sem ); + sem = _Sem_Get( _sem ); _Thread_queue_Context_initialize( &queue_context ); _Thread_queue_Context_ISR_disable( &queue_context, level ); - _Semaphore_Queue_acquire_critical( sem, &queue_context ); + _Sem_Queue_acquire_critical( sem, &queue_context ); heads = sem->Queue.Queue.heads; if ( __predict_true( heads == NULL ) ) { _Assert( sem->count < UINT_MAX ); ++sem->count; - _Semaphore_Queue_release( sem, level, &queue_context ); + _Sem_Queue_release( sem, level, &queue_context ); } else { const Thread_queue_Operations *operations; Thread_Control *first; -- cgit v1.2.3