posix: Implement self-contained POSIX semaphores

For semaphore object pointer and object validation see
POSIX_SEMAPHORE_VALIDATE_OBJECT().

Destruction or close of a busy semaphore returns an error status.  The
object is not flushed.

POSIX semaphores are now available in all configurations and no longer
depend on --enable-posix.

Update #2514.
Update #3116.
This commit is contained in:
Sebastian Huber
2017-09-12 08:09:16 +02:00
parent 47b1e31f11
commit c090db7405
31 changed files with 638 additions and 558 deletions

View File

@@ -21,6 +21,8 @@ include_rtems_posix_HEADERS += include/rtems/posix/keyimpl.h
include_rtems_posix_HEADERS += include/rtems/posix/config.h
include_rtems_posix_HEADERS += include/rtems/posix/posixapi.h
include_rtems_posix_HEADERS += include/rtems/posix/priorityimpl.h
include_rtems_posix_HEADERS += include/rtems/posix/semaphore.h
include_rtems_posix_HEADERS += include/rtems/posix/semaphoreimpl.h
include_rtems_posix_HEADERS += include/rtems/posix/spinlockimpl.h
if HAS_PTHREADS
@@ -44,8 +46,6 @@ include_rtems_posix_HEADERS += include/rtems/posix/pthreadimpl.h
include_rtems_posix_HEADERS += include/rtems/posix/ptimer.h
include_rtems_posix_HEADERS += include/rtems/posix/shm.h
include_rtems_posix_HEADERS += include/rtems/posix/shmimpl.h
include_rtems_posix_HEADERS += include/rtems/posix/semaphore.h
include_rtems_posix_HEADERS += include/rtems/posix/semaphoreimpl.h
include_rtems_posix_HEADERS += include/rtems/posix/threadsup.h
include_rtems_posix_HEADERS += include/rtems/posix/timer.h
include_rtems_posix_HEADERS += include/rtems/posix/timerimpl.h
@@ -186,6 +186,15 @@ libposix_a_SOURCES += src/pspininit.c
libposix_a_SOURCES += src/pspinlock.c
libposix_a_SOURCES += src/pspinunlock.c
## SEMAPHORE_C_FILES
libposix_a_SOURCES += src/semdestroy.c
libposix_a_SOURCES += src/semgetvalue.c
libposix_a_SOURCES += src/seminit.c
libposix_a_SOURCES += src/sempost.c
libposix_a_SOURCES += src/semtimedwait.c
libposix_a_SOURCES += src/semtrywait.c
libposix_a_SOURCES += src/semwait.c
if HAS_PTHREADS
libposix_a_SOURCES += src/sigpending.c \
src/sigqueue.c src/sigsuspend.c src/sigtimedwait.c \
@@ -199,12 +208,11 @@ libposix_a_SOURCES += src/prwlock.c src/prwlockdestroy.c src/prwlockinit.c \
src/rwlockattrinit.c src/rwlockattrsetpshared.c
## SEMAPHORE_C_FILES
libposix_a_SOURCES += src/semaphore.c src/semaphorecreatesupp.c \
src/semaphoredeletesupp.c \
src/semaphorewaitsupp.c \
src/semclose.c src/semdestroy.c src/semgetvalue.c src/seminit.c \
src/semopen.c src/sempost.c src/semtimedwait.c src/semtrywait.c \
src/semunlink.c src/semwait.c
libposix_a_SOURCES += src/semaphore.c
libposix_a_SOURCES += src/semaphoredeletesupp.c
libposix_a_SOURCES += src/semclose.c
libposix_a_SOURCES += src/semopen.c
libposix_a_SOURCES += src/semunlink.c
## TIME_C_FILES
libposix_a_SOURCES += src/adjtime.c src/clockgetcpuclockid.c

View File

@@ -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;
/** @} */

View File

@@ -21,21 +21,25 @@
#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
extern "C" {
#endif
/**
* @brief This is a random number used to check if a semaphore object is
* properly initialized.
*/
#define POSIX_SEMAPHORE_MAGIC 0x5d367fe7UL
/**
* This defines the information control block used to manage
* this class of objects.
*/
extern Objects_Information _POSIX_Semaphore_Information;
#define POSIX_SEMAPHORE_TQ_OPERATIONS &_Thread_queue_Operations_FIFO
RTEMS_INLINE_ROUTINE POSIX_Semaphore_Control *
_POSIX_Semaphore_Allocate_unprotected( void )
{
@@ -57,53 +61,45 @@ RTEMS_INLINE_ROUTINE void _POSIX_Semaphore_Free (
}
RTEMS_INLINE_ROUTINE POSIX_Semaphore_Control *_POSIX_Semaphore_Get(
const sem_t *id,
Thread_queue_Context *queue_context
sem_t *sem
)
{
_Thread_queue_Context_initialize( queue_context );
return (POSIX_Semaphore_Control *) _Objects_Get(
(Objects_Id) *id,
&queue_context->Lock_context.Lock_context,
&_POSIX_Semaphore_Information
);
return RTEMS_CONTAINER_OF( sem, POSIX_Semaphore_Control, Semaphore );
}
/**
* @brief POSIX Semaphore Create Support
*
* This routine supports the sem_init and sem_open routines.
*/
RTEMS_INLINE_ROUTINE bool _POSIX_Semaphore_Is_named( const sem_t *sem )
{
return sem->_Semaphore._Queue._name != NULL;
}
int _POSIX_Semaphore_Create_support(
const char *name,
size_t name_len,
unsigned int value,
POSIX_Semaphore_Control **the_sem
);
RTEMS_INLINE_ROUTINE bool _POSIX_Semaphore_Is_busy( const sem_t *sem )
{
return sem->_Semaphore._Queue._heads != NULL;
}
RTEMS_INLINE_ROUTINE void _POSIX_Semaphore_Initialize(
sem_t *sem,
const char *name,
unsigned int value
)
{
sem->_flags = (uintptr_t) sem ^ POSIX_SEMAPHORE_MAGIC;
_Semaphore_Initialize_named( &sem->_Semaphore, name, value );
}
RTEMS_INLINE_ROUTINE void _POSIX_Semaphore_Destroy( sem_t *sem )
{
sem->_flags = 0;
_Semaphore_Destroy( &sem->_Semaphore );
}
/**
* @brief POSIX Semaphore Delete
*
* This routine supports the sem_close and sem_unlink routines.
*/
void _POSIX_Semaphore_Delete(
POSIX_Semaphore_Control *the_semaphore,
Thread_queue_Context *queue_context
);
void _POSIX_Semaphore_Delete( POSIX_Semaphore_Control *the_semaphore );
/**
* @brief POSIX semaphore wait support.
*
* This routine supports the sem_wait, sem_trywait, and sem_timedwait
* services.
*/
int _POSIX_Semaphore_Wait_support(
sem_t *sem,
bool blocking,
Watchdog_Interval timeout
);
/**
* @brief POSIX Semaphore Namespace Remove
*/
@@ -129,6 +125,16 @@ RTEMS_INLINE_ROUTINE POSIX_Semaphore_Control *_POSIX_Semaphore_Get_by_name(
);
}
#define POSIX_SEMAPHORE_VALIDATE_OBJECT( sem ) \
do { \
if ( \
( sem ) == NULL \
|| ( (uintptr_t) ( sem ) ^ POSIX_SEMAPHORE_MAGIC ) != ( sem )->_flags \
) { \
rtems_set_errno_and_return_minus_one( EINVAL ); \
} \
} while ( 0 )
#ifdef __cplusplus
}
#endif

View File

@@ -47,6 +47,14 @@ $(PROJECT_INCLUDE)/rtems/posix/priorityimpl.h: include/rtems/posix/priorityimpl.
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/priorityimpl.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/priorityimpl.h
$(PROJECT_INCLUDE)/rtems/posix/semaphore.h: include/rtems/posix/semaphore.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/semaphore.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/semaphore.h
$(PROJECT_INCLUDE)/rtems/posix/semaphoreimpl.h: include/rtems/posix/semaphoreimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/semaphoreimpl.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/semaphoreimpl.h
$(PROJECT_INCLUDE)/rtems/posix/spinlockimpl.h: include/rtems/posix/spinlockimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/spinlockimpl.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/spinlockimpl.h
@@ -120,14 +128,6 @@ $(PROJECT_INCLUDE)/rtems/posix/shmimpl.h: include/rtems/posix/shmimpl.h $(PROJEC
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/shmimpl.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/shmimpl.h
$(PROJECT_INCLUDE)/rtems/posix/semaphore.h: include/rtems/posix/semaphore.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/semaphore.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/semaphore.h
$(PROJECT_INCLUDE)/rtems/posix/semaphoreimpl.h: include/rtems/posix/semaphoreimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/semaphoreimpl.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/semaphoreimpl.h
$(PROJECT_INCLUDE)/rtems/posix/threadsup.h: include/rtems/posix/threadsup.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/threadsup.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/threadsup.h

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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 );
}
}

View File

@@ -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 );
}

View File

@@ -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;
}

View File

@@ -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;
POSIX_SEMAPHORE_VALIDATE_OBJECT( sem );
_Objects_Allocator_lock();
the_semaphore = _POSIX_Semaphore_Get( sem, &queue_context );
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;
}

View File

@@ -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;
Sem_Control *sem;
ISR_Level level;
Thread_queue_Context queue_context;
the_semaphore = _POSIX_Semaphore_Get( sem, &queue_context );
POSIX_SEMAPHORE_VALIDATE_OBJECT( _sem );
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 = _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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -18,31 +18,51 @@
#include "config.h"
#endif
#include <semaphore.h>
#include <rtems/posix/semaphoreimpl.h>
#include <limits.h>
#include <rtems/posix/semaphoreimpl.h>
#include <rtems/posix/posixapi.h>
int sem_post(
sem_t *sem
)
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;
the_semaphore = _POSIX_Semaphore_Get( sem, &queue_context );
POSIX_SEMAPHORE_VALIDATE_OBJECT( _sem );
if ( the_semaphore == NULL ) {
rtems_set_errno_and_return_minus_one( EINVAL );
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;
}
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 );
if ( __predict_true( heads != NULL ) ) {
const Thread_queue_Operations *operations;
Thread_Control *first;
_Thread_queue_Context_set_ISR_level( &queue_context, level );
operations = SEMAPHORE_TQ_OPERATIONS;
first = ( *operations->first )( heads );
_Thread_queue_Extract_critical(
&sem->Queue.Queue,
operations,
first,
&queue_context
);
return 0;
}
_Sem_Queue_release( sem, level, &queue_context );
rtems_set_errno_and_return_minus_one( EOVERFLOW );
}

View File

@@ -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;
}
_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 );
}
return lock_status;
}

View File

@@ -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 );
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -20,6 +20,31 @@
#endif
#include <rtems/posix/posixapi.h>
#include <rtems/posix/semaphoreimpl.h>
#include <rtems/score/heap.h>
#ifdef HEAP_PROTECTION
RTEMS_STATIC_ASSERT(
POSIX_SEMAPHORE_MAGIC != HEAP_BEGIN_PROTECTOR_0,
POSIX_SEMAPHORE_MAGIC_0
);
RTEMS_STATIC_ASSERT(
POSIX_SEMAPHORE_MAGIC != HEAP_BEGIN_PROTECTOR_1,
POSIX_SEMAPHORE_MAGIC_1
);
RTEMS_STATIC_ASSERT(
POSIX_SEMAPHORE_MAGIC != HEAP_END_PROTECTOR_0,
POSIX_SEMAPHORE_MAGIC_2
);
RTEMS_STATIC_ASSERT(
POSIX_SEMAPHORE_MAGIC != HEAP_END_PROTECTOR_1,
POSIX_SEMAPHORE_MAGIC_3
);
RTEMS_STATIC_ASSERT(
POSIX_SEMAPHORE_MAGIC != HEAP_FREE_PATTERN,
POSIX_SEMAPHORE_MAGIC_4
);
#endif
void _POSIX_Fatal_error( POSIX_Fatal_domain domain, int eno )
{

View File

@@ -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

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2015, 2017 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#ifndef _RTEMS_SCORE_SEMAPHOREIMPL_H
#define _RTEMS_SCORE_SEMAPHOREIMPL_H
#include <sys/lock.h>
#include <rtems/score/percpu.h>
#include <rtems/score/threadqimpl.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct {
Thread_queue_Syslock_queue Queue;
unsigned int count;
} Sem_Control;
#define SEMAPHORE_TQ_OPERATIONS &_Thread_queue_Operations_priority
static inline Sem_Control *_Sem_Get( struct _Semaphore_Control *_sem )
{
return (Sem_Control *) _sem;
}
static inline Thread_Control *_Sem_Queue_acquire_critical(
Sem_Control *sem,
Thread_queue_Context *queue_context
)
{
Thread_Control *executing;
executing = _Thread_Executing;
_Thread_queue_Queue_acquire_critical(
&sem->Queue.Queue,
&executing->Potpourri_stats,
&queue_context->Lock_context.Lock_context
);
return executing;
}
static inline void _Sem_Queue_release(
Sem_Control *sem,
ISR_Level level,
Thread_queue_Context *queue_context
)
{
_Thread_queue_Queue_release_critical(
&sem->Queue.Queue,
&queue_context->Lock_context.Lock_context
);
_ISR_Local_enable( level );
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _RTEMS_SCORE_SEMAPHOREIMPL_H */

View File

@@ -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

View File

@@ -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;

View File

@@ -263,7 +263,6 @@ static void resourceSnapshotCheck( void )
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
#define CONFIGURE_MAXIMUM_POSIX_THREADS 2
#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 2
#define CONFIGURE_POSIX_INIT_THREAD_TABLE

View File

@@ -130,7 +130,6 @@ void *POSIX_Init( void *arg )
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
#define CONFIGURE_MAXIMUM_POSIX_THREADS 2
#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 1
#define CONFIGURE_INIT
#include <rtems/confdefs.h>

View File

@@ -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,13 +167,163 @@ static void test_sem_post_overflow(void)
static void test_sem_init_too_large_inital_value(void)
{
sem_t sem;
int rv;
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_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 );
}
void *POSIX_Init(
@@ -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 \

View File

@@ -159,7 +159,6 @@ void *POSIX_Init(void *argument)
#define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER
#define CONFIGURE_MAXIMUM_POSIX_THREADS 1
#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 2
#define CONFIGURE_POSIX_INIT_THREAD_TABLE
#define CONFIGURE_INIT

View File

@@ -124,7 +124,6 @@ void *POSIX_Init(
#define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER
#define CONFIGURE_MAXIMUM_POSIX_THREADS OPERATION_COUNT + 2
#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES MAX_SEMS
#define CONFIGURE_POSIX_INIT_THREAD_TABLE
#define CONFIGURE_INIT

View File

@@ -99,7 +99,6 @@ void *POSIX_Init(void *argument)
#define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER
#define CONFIGURE_MAXIMUM_POSIX_THREADS 2
#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES MAX_SEMS
#define CONFIGURE_POSIX_INIT_THREAD_TABLE
#define CONFIGURE_INIT

View File

@@ -159,7 +159,6 @@ void *POSIX_Init(
#define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER
#define CONFIGURE_MAXIMUM_POSIX_THREADS OPERATION_COUNT + 2
#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES MAX_SEMS
#define CONFIGURE_POSIX_INIT_THREAD_TABLE
#define CONFIGURE_INIT

View File

@@ -40,7 +40,6 @@ typedef struct {
rtems_id mq;
rtems_id br;
#if defined(RTEMS_POSIX_API)
sem_t psem;
pthread_mutex_t pmtx;
pthread_cond_t pcv;
pthread_rwlock_t prw;
@@ -120,12 +119,6 @@ static void posix_worker(test_context *ctx)
int eno;
char buf[1];
wake_up_master(ctx);
rtems_test_assert(get_wait_id(ctx) == ctx->psem);
rv = sem_post(&ctx->psem);
rtems_test_assert(rv == 0);
eno = pthread_mutex_lock(&ctx->pmtx);
rtems_test_assert(eno == 0);
@@ -217,13 +210,9 @@ static void test_classic_init(test_context *ctx)
static void test_posix_init(test_context *ctx)
{
#if defined(RTEMS_POSIX_API)
int rv;
int eno;
struct mq_attr attr;
rv = sem_init(&ctx->psem, 0, 0);
rtems_test_assert(rv == 0);
eno = pthread_mutex_init(&ctx->pmtx, NULL);
rtems_test_assert(eno == 0);
@@ -306,7 +295,6 @@ static void test_classic_obj(test_context *ctx)
static void test_posix_obj(test_context *ctx)
{
#if defined(RTEMS_POSIX_API)
int rv;
int eno;
char buf[1];
unsigned prio;
@@ -314,11 +302,6 @@ static void test_posix_obj(test_context *ctx)
wait_for_worker(ctx);
rv = sem_wait(&ctx->psem);
rtems_test_assert(rv == 0);
wait_for_worker(ctx);
eno = pthread_mutex_lock(&ctx->pmtx);
rtems_test_assert(eno == 0);
@@ -377,7 +360,6 @@ static rtems_task Init(
#define CONFIGURE_MAXIMUM_BARRIERS 1
#if defined(RTEMS_POSIX_API)
#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 1
#define CONFIGURE_MAXIMUM_POSIX_MUTEXES 1
#define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES 1
#define CONFIGURE_MAXIMUM_POSIX_RWLOCKS 1