[PATCH] posix: Implement self-contained POSIX semaphores
Sebastian Huber
sebastian.huber at embedded-brains.de
Wed Sep 20 08:22:30 UTC 2017
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.
Update #3116.
---
cpukit/posix/Makefile.am | 3 +-
cpukit/posix/include/rtems/posix/semaphore.h | 18 +-
cpukit/posix/include/rtems/posix/semaphoreimpl.h | 82 ++++----
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/score/Makefile.am | 1 +
cpukit/score/include/rtems/score/semaphoreimpl.h | 73 +++++++
cpukit/score/preinstall.am | 4 +
cpukit/score/src/semaphore.c | 73 ++-----
testsuites/psxtests/psxsem01/init.c | 241 +++++++++++++++++++++--
testsuites/sptests/spthreadq01/init.c | 16 --
23 files changed, 591 insertions(+), 537 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
diff --git a/cpukit/posix/Makefile.am b/cpukit/posix/Makefile.am
index 3bb5bd29f9..2c88dbbc19 100644
--- a/cpukit/posix/Makefile.am
+++ b/cpukit/posix/Makefile.am
@@ -199,9 +199,8 @@ 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 \
+libposix_a_SOURCES += src/semaphore.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
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/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/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 at 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/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/sptests/spthreadq01/init.c b/testsuites/sptests/spthreadq01/init.c
index 8f02e4d650..684d96b66a 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);
@@ -221,9 +214,6 @@ static void test_posix_init(test_context *ctx)
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);
@@ -314,11 +304,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 +362,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
--
2.12.3
More information about the devel
mailing list