diff options
31 files changed, 639 insertions, 559 deletions
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 <semaphore.h> #include <rtems/score/object.h> -#include <rtems/score/coresem.h> #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,7 +21,7 @@ #include <rtems/posix/semaphore.h> #include <rtems/posix/posixapi.h> -#include <rtems/score/coresemimpl.h> +#include <rtems/score/semaphoreimpl.h> #include <rtems/seterr.h> #ifdef __cplusplus @@ -29,13 +29,17 @@ 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,54 +61,46 @@ 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 */ RTEMS_INLINE_ROUTINE void _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 <stdarg.h> - -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <semaphore.h> -#include <limits.h> - -#include <rtems/system.h> +#include <rtems/posix/semaphoreimpl.h> #include <rtems/config.h> #include <rtems/sysinit.h> -#include <rtems/posix/semaphoreimpl.h> -#include <rtems/seterr.h> + +#include <limits.h> 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 <stdarg.h> - -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <semaphore.h> -#include <limits.h> -#include <string.h> /* strlen */ - -#include <rtems/system.h> -#include <rtems/score/wkspace.h> -#include <rtems/posix/semaphoreimpl.h> -#include <rtems/seterr.h> - -/* - * _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 <rtems/posix/semaphoreimpl.h> -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 <semaphore.h> - -#include <rtems/posix/semaphoreimpl.h> -#include <rtems/posix/posixapi.h> - -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 <semaphore.h> - #include <rtems/posix/semaphoreimpl.h> -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 <semaphore.h> - #include <rtems/posix/semaphoreimpl.h> -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 <semaphore.h> - #include <rtems/posix/semaphoreimpl.h> 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 <stdarg.h> +#include <rtems/posix/semaphoreimpl.h> -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <semaphore.h> #include <limits.h> -#include <rtems/system.h> -#include <rtems/posix/semaphoreimpl.h> -#include <rtems/seterr.h> +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 <stdarg.h> +#include <rtems/posix/semaphoreimpl.h> +#include <rtems/score/wkspace.h> -#include <errno.h> +#include <stdarg.h> #include <fcntl.h> -#include <pthread.h> -#include <semaphore.h> #include <limits.h> -#include <rtems/system.h> -#include <rtems/posix/semaphoreimpl.h> -#include <rtems/seterr.h> +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 <semaphore.h> -#include <limits.h> - #include <rtems/posix/semaphoreimpl.h> -#include <rtems/posix/posixapi.h> -int sem_post( - sem_t *sem -) +#include <limits.h> + +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 <stdarg.h> - -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <semaphore.h> -#include <limits.h> - -#include <rtems/system.h> -#include <rtems/score/todimpl.h> #include <rtems/posix/semaphoreimpl.h> -#include <rtems/seterr.h> +#include <rtems/score/todimpl.h> /* * 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 <stdarg.h> - -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <semaphore.h> -#include <limits.h> - -#include <rtems/system.h> #include <rtems/posix/semaphoreimpl.h> -#include <rtems/seterr.h> -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 <semaphore.h> - #include <rtems/posix/semaphoreimpl.h> -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 <stdarg.h> - -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <semaphore.h> -#include <limits.h> - -#include <rtems/system.h> #include <rtems/posix/semaphoreimpl.h> -#include <rtems/seterr.h> -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 <rtems/posix/posixapi.h> +#include <rtems/posix/semaphoreimpl.h> +#include <rtems/score/heap.h> + +#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 + * <rtems@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.org/license/LICENSE. + */ + +#ifndef _RTEMS_SCORE_SEMAPHOREIMPL_H +#define _RTEMS_SCORE_SEMAPHOREIMPL_H + +#include <sys/lock.h> + +#include <rtems/score/percpu.h> +#include <rtems/score/threadqimpl.h> + +#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 <sys/lock.h> +#include <rtems/score/semaphoreimpl.h> +#include <rtems/score/statesimpl.h> #include <limits.h> -#include <rtems/score/assert.h> -#include <rtems/score/threadimpl.h> -#include <rtems/score/threadqimpl.h> - -#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; diff --git a/testsuites/psxtests/psxcancel/init.c b/testsuites/psxtests/psxcancel/init.c index 90f474971d..c4c442b668 100644 --- a/testsuites/psxtests/psxcancel/init.c +++ b/testsuites/psxtests/psxcancel/init.c @@ -263,7 +263,6 @@ static void resourceSnapshotCheck( void ) #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION #define CONFIGURE_MAXIMUM_POSIX_THREADS 2 -#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 2 #define CONFIGURE_POSIX_INIT_THREAD_TABLE diff --git a/testsuites/psxtests/psxeintr_join/init.c b/testsuites/psxtests/psxeintr_join/init.c index 7fe0da73cd..f0810b50a5 100644 --- a/testsuites/psxtests/psxeintr_join/init.c +++ b/testsuites/psxtests/psxeintr_join/init.c @@ -130,7 +130,6 @@ void *POSIX_Init( void *arg ) #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION #define CONFIGURE_MAXIMUM_POSIX_THREADS 2 -#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 1 #define CONFIGURE_INIT #include <rtems/confdefs.h> diff --git a/testsuites/psxtests/psxsem01/init.c b/testsuites/psxtests/psxsem01/init.c index 9ba8935292..ae0b390a7c 100644 --- a/testsuites/psxtests/psxsem01/init.c +++ b/testsuites/psxtests/psxsem01/init.c @@ -38,10 +38,8 @@ static void *sem_wait_task(void *arg) rv = sem_wait( sem ); rtems_test_assert( rv == 0 ); - errno = 0; rv = sem_wait( sem ); - rtems_test_assert( rv == -1 ); - rtems_test_assert( errno == EINVAL ); + rtems_test_assert( rv == 0 ); return NULL; } @@ -70,11 +68,69 @@ static void test_sem_wait_during_delete(void) rtems_test_assert( rv == 0 ); rtems_test_assert( val == 0 ); + errno = 0; + rv = sem_destroy( &sem ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EBUSY ); + + rv = sem_post( &sem ); + rtems_test_assert( rv == 0 ); + + eno = pthread_join( th, NULL ); + rtems_test_assert( eno == 0 ); + rv = sem_destroy( &sem ); rtems_test_assert( rv == 0 ); +} + +static void test_named_sem_wait_during_delete(void) +{ + sem_t *sem; + sem_t *sem2; + int rv; + pthread_t th; + int eno; + int val; + + sem = sem_open( "sem", O_CREAT | O_EXCL, 0777, 1 ); + rtems_test_assert( sem != SEM_FAILED ); + + sem2 = sem_open( "sem", 0 ); + rtems_test_assert( sem2 != SEM_FAILED ); + rtems_test_assert( sem == sem2 ); + + eno = pthread_create( &th, NULL, sem_wait_task, sem ); + rtems_test_assert( eno == 0 ); + + rv = sem_getvalue( sem, &val ); + rtems_test_assert( rv == 0 ); + rtems_test_assert( val == 1 ); + + sched_yield(); + + rv = sem_getvalue( sem, &val ); + rtems_test_assert( rv == 0 ); + rtems_test_assert( val == 0 ); + + rv = sem_close( sem2 ); + rtems_test_assert( rv == 0 ); + + errno = 0; + rv = sem_close( sem ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EBUSY ); + + rv = sem_post( sem ); + rtems_test_assert( rv == 0 ); eno = pthread_join( th, NULL ); rtems_test_assert( eno == 0 ); + + rv = sem_close( sem ); + rtems_test_assert( rv == 0 ); + + rv = sem_unlink( "sem" ); + rtems_test_assert( rv == 0 ); } static void test_sem_post_overflow(void) @@ -111,11 +167,161 @@ static void test_sem_post_overflow(void) static void test_sem_init_too_large_inital_value(void) { + sem_t sem; + sem_t *sem2; + int rv; + + errno = 0; + rv = sem_init( &sem, 0, (unsigned int) SEM_VALUE_MAX + 1 ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + sem2 = sem_open( + "sem", + O_CREAT | O_EXCL, + 0777, + (unsigned int) SEM_VALUE_MAX + 1 + ); + rtems_test_assert( sem2 == SEM_FAILED ); + rtems_test_assert( errno == EINVAL ); +} + +static void test_sem_null(void) +{ + int rv; + int val; + struct timespec to; + + rtems_test_assert( NULL == SEM_FAILED ); + + errno = 0; + rv = sem_init( NULL, 0, 0 ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + rv = sem_wait( NULL ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + rv = sem_post( NULL ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + rv = sem_wait( NULL ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + rv = sem_trywait( NULL ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + to.tv_sec = 1; + to.tv_nsec = 1; + errno = 0; + rv = sem_timedwait( NULL, &to ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + rv = sem_getvalue( NULL, &val ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + rv = sem_destroy( NULL ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + rv = sem_close( NULL ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); +} + +static void test_sem_not_initialized(void) +{ sem_t sem; + int rv; + int val; + struct timespec to; + + memset( &sem, 0xff, sizeof( sem ) ); + + errno = 0; + rv = sem_wait( &sem ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + rv = sem_post( &sem ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + rv = sem_wait( &sem ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + rv = sem_trywait( &sem ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + to.tv_sec = 1; + to.tv_nsec = 1; + errno = 0; + rv = sem_timedwait( &sem, &to ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + rv = sem_getvalue( &sem, &val ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + rv = sem_destroy( &sem ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + errno = 0; + rv = sem_close( &sem ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); +} + +static void test_sem_invalid_copy(void) +{ + sem_t sem; + sem_t sem2; int rv; + int val; + + rv = sem_init( &sem, 0, 0 ); + rtems_test_assert( rv == 0 ); + + val = 1; + rv = sem_getvalue( &sem, &val ); + rtems_test_assert( rv == 0 ); + rtems_test_assert( val == 0 ); + + memcpy( &sem2, &sem, sizeof( sem2 ) ); errno = 0; - rv = sem_init( &sem, 0, (unsigned int) SEM_VALUE_MAX + 1 ); + rv = sem_getvalue( &sem2, &val ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + rv = sem_destroy( &sem ); + rtems_test_assert( rv == 0 ); + + errno = 0; + rv = sem_getvalue( &sem, &val ); rtems_test_assert( rv == -1 ); rtems_test_assert( errno == EINVAL ); } @@ -155,10 +361,14 @@ void *POSIX_Init( sprintf(failure_msg, "sem_init %d", i ); fatal_posix_service_status( status, 0, failure_msg); } - puts( "Init: sem_init - UNSUCCESSFUL (ENOSPC)" ); + + puts( "Init: sem_init - SUCCESSFUL" ); status = sem_init(&sem2, 0, 1); - fatal_posix_service_status( status, -1, "sem_init error return status"); - fatal_posix_service_status( errno, ENOSPC, "sem_init errorno ENOSPC" ); + fatal_posix_service_status( status, 0, "sem_init"); + + puts( "Init: sem_destroy - SUCCESSFUL" ); + status = sem_destroy(&sem2); + fatal_posix_service_status( status, 0, "sem_destroy"); puts( "Init: sem_getvalue - SUCCESSFUL "); for (i = 0; i < MAX_SEMS; i++) { @@ -168,8 +378,7 @@ void *POSIX_Init( fatal_posix_service_status( value, i, "sem_getvalue correct value" ); } puts( "Init: sem_getvalue - UNSUCCESSFUL "); - sem2 = 0; - status = sem_getvalue(&sem2, &value); + status = sem_getvalue(SEM_FAILED, &value); fatal_posix_service_status( status, -1, "sem_getvalue error return status"); fatal_posix_service_status( errno, EINVAL, "sem_getvalue errno EINVAL"); @@ -178,7 +387,7 @@ void *POSIX_Init( fatal_posix_service_status( status, 0, "sem_destroy semaphore 0"); puts( "Init: sem_destroy - UNSUCCESSFUL (EINVAL)" ); - status = sem_destroy(&sem2); + status = sem_destroy(SEM_FAILED); fatal_posix_service_status( status, -1, "sem_destroy error return status"); fatal_posix_service_status( errno, EINVAL, "sem_destroy errno EINVAL"); @@ -188,7 +397,7 @@ void *POSIX_Init( /* sem[1].count = 0 */ puts( "Init: sem_wait - UNSUCCESSFUL (EINVAL)" ); - status = sem_wait(&sem2); + status = sem_wait(SEM_FAILED); fatal_posix_service_status( status, -1, "sem_wait error return status"); fatal_posix_service_status( errno, EINVAL, "sem_wait errno EINVAL"); @@ -214,7 +423,7 @@ void *POSIX_Init( /* sem[1].count = 0 */ puts( "Init: sem_trywait - UNSUCCESSFUL (EINVAL)" ); - status = sem_trywait(&sem2); + status = sem_trywait(SEM_FAILED); fatal_posix_service_status( status, -1, "sem_trywait error return status"); fatal_posix_service_status( errno, EINVAL, "sem_trywait errno EINVAL"); @@ -256,7 +465,7 @@ void *POSIX_Init( #endif puts( "Init: sem_post - UNSUCCESSFUL (EINVAL)" ); - status = sem_post(&sem2); + status = sem_post(SEM_FAILED); fatal_posix_service_status( status, -1, "sem_post error return status"); fatal_posix_service_status( errno, EINVAL, "sem_post errno EINVAL"); @@ -392,9 +601,13 @@ void *POSIX_Init( fatal_posix_service_status( errno, ENOENT, "sem_unlink errno ENOENT"); rtems_test_assert( (status == -1) && (errno == ENOENT) ); + test_named_sem_wait_during_delete(); test_sem_wait_during_delete(); test_sem_post_overflow(); test_sem_init_too_large_inital_value(); + test_sem_null(); + test_sem_not_initialized(); + test_sem_invalid_copy(); /* Try adding in unlinking before closing... (can we still open?) */ @@ -413,7 +626,7 @@ void *POSIX_Init( #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION #define CONFIGURE_MAXIMUM_POSIX_THREADS 2 -#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES MAX_SEMS +#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 2 #define CONFIGURE_POSIX_INIT_THREAD_TABLE #define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE \ diff --git a/testsuites/psxtmtests/psxtmsem02/init.c b/testsuites/psxtmtests/psxtmsem02/init.c index 4629ac5f4c..3c2f34a20b 100644 --- a/testsuites/psxtmtests/psxtmsem02/init.c +++ b/testsuites/psxtmtests/psxtmsem02/init.c @@ -159,7 +159,6 @@ void *POSIX_Init(void *argument) #define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER #define CONFIGURE_MAXIMUM_POSIX_THREADS 1 -#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 2 #define CONFIGURE_POSIX_INIT_THREAD_TABLE #define CONFIGURE_INIT diff --git a/testsuites/psxtmtests/psxtmsem03/init.c b/testsuites/psxtmtests/psxtmsem03/init.c index 585b88d6cd..687c8c6343 100644 --- a/testsuites/psxtmtests/psxtmsem03/init.c +++ b/testsuites/psxtmtests/psxtmsem03/init.c @@ -124,7 +124,6 @@ void *POSIX_Init( #define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER #define CONFIGURE_MAXIMUM_POSIX_THREADS OPERATION_COUNT + 2 -#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES MAX_SEMS #define CONFIGURE_POSIX_INIT_THREAD_TABLE #define CONFIGURE_INIT diff --git a/testsuites/psxtmtests/psxtmsem04/init.c b/testsuites/psxtmtests/psxtmsem04/init.c index 5cebc9daa0..540f0a3b97 100644 --- a/testsuites/psxtmtests/psxtmsem04/init.c +++ b/testsuites/psxtmtests/psxtmsem04/init.c @@ -99,7 +99,6 @@ void *POSIX_Init(void *argument) #define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER #define CONFIGURE_MAXIMUM_POSIX_THREADS 2 -#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES MAX_SEMS #define CONFIGURE_POSIX_INIT_THREAD_TABLE #define CONFIGURE_INIT diff --git a/testsuites/psxtmtests/psxtmsem05/init.c b/testsuites/psxtmtests/psxtmsem05/init.c index 12594c4e99..07b96b2024 100644 --- a/testsuites/psxtmtests/psxtmsem05/init.c +++ b/testsuites/psxtmtests/psxtmsem05/init.c @@ -159,7 +159,6 @@ void *POSIX_Init( #define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER #define CONFIGURE_MAXIMUM_POSIX_THREADS OPERATION_COUNT + 2 -#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES MAX_SEMS #define CONFIGURE_POSIX_INIT_THREAD_TABLE #define CONFIGURE_INIT diff --git a/testsuites/sptests/spthreadq01/init.c b/testsuites/sptests/spthreadq01/init.c index 8f02e4d650..2b994e5d68 100644 --- a/testsuites/sptests/spthreadq01/init.c +++ b/testsuites/sptests/spthreadq01/init.c @@ -40,7 +40,6 @@ typedef struct { rtems_id mq; rtems_id br; #if defined(RTEMS_POSIX_API) - sem_t psem; pthread_mutex_t pmtx; pthread_cond_t pcv; pthread_rwlock_t prw; @@ -120,12 +119,6 @@ static void posix_worker(test_context *ctx) int eno; char buf[1]; - wake_up_master(ctx); - rtems_test_assert(get_wait_id(ctx) == ctx->psem); - - rv = sem_post(&ctx->psem); - rtems_test_assert(rv == 0); - eno = pthread_mutex_lock(&ctx->pmtx); rtems_test_assert(eno == 0); @@ -217,13 +210,9 @@ static void test_classic_init(test_context *ctx) static void test_posix_init(test_context *ctx) { #if defined(RTEMS_POSIX_API) - int rv; int eno; struct mq_attr attr; - rv = sem_init(&ctx->psem, 0, 0); - rtems_test_assert(rv == 0); - eno = pthread_mutex_init(&ctx->pmtx, NULL); rtems_test_assert(eno == 0); @@ -306,7 +295,6 @@ static void test_classic_obj(test_context *ctx) static void test_posix_obj(test_context *ctx) { #if defined(RTEMS_POSIX_API) - int rv; int eno; char buf[1]; unsigned prio; @@ -314,11 +302,6 @@ static void test_posix_obj(test_context *ctx) wait_for_worker(ctx); - rv = sem_wait(&ctx->psem); - rtems_test_assert(rv == 0); - - wait_for_worker(ctx); - eno = pthread_mutex_lock(&ctx->pmtx); rtems_test_assert(eno == 0); @@ -377,7 +360,6 @@ static rtems_task Init( #define CONFIGURE_MAXIMUM_BARRIERS 1 #if defined(RTEMS_POSIX_API) - #define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 1 #define CONFIGURE_MAXIMUM_POSIX_MUTEXES 1 #define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES 1 #define CONFIGURE_MAXIMUM_POSIX_RWLOCKS 1 |