[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