2006-10-30 Joel Sherrill <joel@OARcorp.com>

PR 841/rtems
	* itron/inline/rtems/itron/semaphore.inl, itron/src/twai_sem.c,
	posix/include/rtems/posix/semaphore.h,
	posix/inline/rtems/posix/semaphore.inl,
	posix/src/semaphorewaitsupp.c, posix/src/semtimedwait.c,
	posix/src/semwait.c, rtems/src/semobtain.c,
	rtems/src/semtranslatereturncode.c,
	score/include/rtems/score/coresem.h, score/src/coresemseize.c: Make
	sem_timedwait more conformant to Open Group specification.
This commit is contained in:
Joel Sherrill
2006-10-30 22:21:23 +00:00
parent 842a8fe157
commit 0c2ec7f52c
12 changed files with 140 additions and 92 deletions

View File

@@ -1,3 +1,15 @@
2006-10-30 Joel Sherrill <joel@OARcorp.com>
PR 841/rtems
* itron/inline/rtems/itron/semaphore.inl, itron/src/twai_sem.c,
posix/include/rtems/posix/semaphore.h,
posix/inline/rtems/posix/semaphore.inl,
posix/src/semaphorewaitsupp.c, posix/src/semtimedwait.c,
posix/src/semwait.c, rtems/src/semobtain.c,
rtems/src/semtranslatereturncode.c,
score/include/rtems/score/coresem.h, score/src/coresemseize.c: Make
sem_timedwait more conformant to Open Group specification.
2006-10-25 Jennifer Averett <jennifer@oarcorp.com>
* libcsupport/src/termios.c: Change attribute of semaphore. It was

View File

@@ -172,6 +172,8 @@ RTEMS_INLINE_ROUTINE ER _ITRON_Semaphore_Translate_core_semaphore_return_code (
return E_TMOUT;
case CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED:
return E_QOVR;
case CORE_SEMAPHORE_BAD_TIMEOUT_VALUE:
return E_PAR;
case THREAD_STATUS_PROXY_BLOCKING:
return THREAD_STATUS_PROXY_BLOCKING;
}

View File

@@ -30,23 +30,23 @@ ER twai_sem(
TMO tmout
)
{
ITRON_Semaphore_Control *the_semaphore;
Objects_Locations location;
Watchdog_Interval interval;
boolean wait;
CORE_semaphore_Status status;
ITRON_Semaphore_Control *the_semaphore;
Objects_Locations location;
Watchdog_Interval interval;
Core_semaphore_Blocking_option blocking;
interval = 0;
if ( tmout == TMO_POL ) {
wait = FALSE;
blocking = CORE_SEMAPHORE_NO_WAIT;
} else {
wait = TRUE;
blocking = CORE_SEMAPHORE_BLOCK_FOREVER;
if ( tmout != TMO_FEVR )
interval = TOD_MILLISECONDS_TO_TICKS(tmout);
}
if ( wait && _ITRON_Is_in_non_task_state() )
return E_CTX;
if ( _ITRON_Is_in_non_task_state() )
return E_CTX;
}
the_semaphore = _ITRON_Semaphore_Get( semid, &location );
switch ( location ) {
@@ -58,12 +58,13 @@ ER twai_sem(
_CORE_semaphore_Seize(
&the_semaphore->semaphore,
the_semaphore->Object.id,
wait, /* wait for a timeout */
blocking, /* wait for a timeout */
interval /* timeout value */
);
_Thread_Enable_dispatch();
status = (CORE_semaphore_Status) _Thread_Executing->Wait.return_code;
return _ITRON_Semaphore_Translate_core_semaphore_return_code( status );
return _ITRON_Semaphore_Translate_core_semaphore_return_code(
_Thread_Executing->Wait.return_code
);
}
return E_OK;
}

View File

@@ -153,9 +153,9 @@ void _POSIX_Semaphore_Delete(
*/
int _POSIX_Semaphore_Wait_support(
sem_t *sem,
boolean blocking,
Watchdog_Interval timeout
sem_t *sem,
Core_semaphore_Blocking_option blocking,
Watchdog_Interval timeout
);
/*

View File

@@ -64,7 +64,7 @@ RTEMS_INLINE_ROUTINE void _POSIX_Semaphore_Namespace_remove (
*/
RTEMS_INLINE_ROUTINE POSIX_Semaphore_Control *_POSIX_Semaphore_Get (
sem_t *id,
sem_t *id,
Objects_Locations *location
)
{

View File

@@ -26,13 +26,13 @@
*/
int _POSIX_Semaphore_Wait_support(
sem_t *sem,
boolean blocking,
Watchdog_Interval timeout
sem_t *sem,
Core_semaphore_Blocking_option blocking,
Watchdog_Interval timeout
)
{
register POSIX_Semaphore_Control *the_semaphore;
Objects_Locations location;
POSIX_Semaphore_Control *the_semaphore;
Objects_Locations location;
the_semaphore = _POSIX_Semaphore_Get( sem, &location );
switch ( location ) {
@@ -65,6 +65,9 @@ int _POSIX_Semaphore_Wait_support(
* count to the largest value the count can hold.
*/
break;
case CORE_SEMAPHORE_BAD_TIMEOUT_VALUE:
rtems_set_errno_and_return_minus_one( EINVAL );
break;
}
}
return 0;

View File

@@ -35,34 +35,37 @@ int sem_timedwait(
/*
* The abstime is a walltime. We turn it into an interval.
*/
Watchdog_Interval ticks;
struct timespec current_time;
struct timespec difference;
Watchdog_Interval ticks = 0;
struct timespec current_time;
struct timespec difference;
Core_semaphore_Blocking_option blocking = CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT;
/*
* Error check the absolute time to timeout
*/
#if 0
if ( /* abstime->tv_sec < 0 || */ abstime->tv_nsec ) /* tv_sec is unsigned */
return EINVAL;
blocking = CORE_SEMAPHORE_BAD_TIMEOUT_VALUE;
else
#endif
if ( abstime->tv_nsec >= TOD_NANOSECONDS_PER_SECOND )
return EINVAL;
(void) clock_gettime( CLOCK_REALTIME, &current_time );
blocking = CORE_SEMAPHORE_BAD_TIMEOUT_VALUE;
else {
(void) clock_gettime( CLOCK_REALTIME, &current_time );
/*
* Make sure the abstime is in the future
*/
if ( abstime->tv_sec < current_time.tv_sec )
blocking = CORE_SEMAPHORE_BAD_TIMEOUT_VALUE;
else if ( (abstime->tv_sec == current_time.tv_sec) &&
(abstime->tv_nsec <= current_time.tv_nsec) )
blocking = CORE_SEMAPHORE_BAD_TIMEOUT_VALUE;
else {
_POSIX_Timespec_subtract( &current_time, abstime, &difference );
ticks = _POSIX_Timespec_to_interval( &difference );
blocking = CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT;
}
}
/*
* Make sure the abstime is in the future
*/
if ( abstime->tv_sec < current_time.tv_sec )
return EINVAL;
if ( (abstime->tv_sec == current_time.tv_sec) &&
(abstime->tv_nsec <= current_time.tv_nsec) )
return EINVAL;
_POSIX_Timespec_subtract( &current_time, abstime, &difference );
ticks = _POSIX_Timespec_to_interval( &difference );
return _POSIX_Semaphore_Wait_support( sem, TRUE, ticks );
return _POSIX_Semaphore_Wait_support( sem, blocking, ticks );
}

View File

@@ -31,5 +31,9 @@ int sem_wait(
sem_t *sem
)
{
return _POSIX_Semaphore_Wait_support( sem, TRUE, THREAD_QUEUE_WAIT_FOREVER );
return _POSIX_Semaphore_Wait_support(
sem,
CORE_SEMAPHORE_BLOCK_FOREVER,
THREAD_QUEUE_WAIT_FOREVER
);
}

View File

@@ -71,10 +71,9 @@ rtems_status_code rtems_semaphore_obtain(
rtems_interval timeout
)
{
register Semaphore_Control *the_semaphore;
Objects_Locations location;
boolean wait;
ISR_Level level;
register Semaphore_Control *the_semaphore;
Objects_Locations location;
ISR_Level level;
the_semaphore = _Semaphore_Get_interrupt_disable( id, &location, &level );
switch ( location ) {
@@ -92,16 +91,11 @@ rtems_status_code rtems_semaphore_obtain(
return RTEMS_INVALID_ID;
case OBJECTS_LOCAL:
if ( _Options_Is_no_wait( option_set ) )
wait = FALSE;
else
wait = TRUE;
if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) {
_CORE_mutex_Seize(
&the_semaphore->Core_control.mutex,
id,
wait,
((_Options_Is_no_wait( option_set )) ? FALSE : TRUE),
timeout,
level
);
@@ -113,7 +107,8 @@ rtems_status_code rtems_semaphore_obtain(
_CORE_semaphore_Seize_isr_disable(
&the_semaphore->Core_control.semaphore,
id,
wait,
((_Options_Is_no_wait( option_set )) ?
CORE_SEMAPHORE_NO_WAIT : CORE_SEMAPHORE_BLOCK_FOREVER),
timeout,
&level
);

View File

@@ -54,7 +54,7 @@
* _Semaphore_Translate_core_mutex_return_code
*
* Input parameters:
* the_mutex_status - mutex status code to translate
* status - mutex status code to translate
*
* Output parameters:
* rtems status code - translated RTEMS status code
@@ -73,18 +73,16 @@ rtems_status_code _Semaphore_Translate_core_mutex_return_code_[] = {
rtems_status_code _Semaphore_Translate_core_mutex_return_code (
uint32_t the_mutex_status
uint32_t status
)
{
#if defined(RTEMS_MULTIPROCESSING)
if ( the_mutex_status == THREAD_STATUS_PROXY_BLOCKING )
if ( status == THREAD_STATUS_PROXY_BLOCKING )
return RTEMS_PROXY_BLOCKING;
else
#endif
if ( the_mutex_status > CORE_MUTEX_STATUS_CEILING_VIOLATED )
if ( status > CORE_MUTEX_STATUS_CEILING_VIOLATED )
return RTEMS_INTERNAL_ERROR;
else
return _Semaphore_Translate_core_mutex_return_code_[the_mutex_status];
return _Semaphore_Translate_core_mutex_return_code_[status];
}
/*PAGE
@@ -92,7 +90,7 @@ rtems_status_code _Semaphore_Translate_core_mutex_return_code (
* _Semaphore_Translate_core_semaphore_return_code
*
* Input parameters:
* the_semaphore_status - semaphore status code to translate
* status - semaphore status code to translate
*
* Output parameters:
* rtems status code - translated RTEMS status code
@@ -105,20 +103,18 @@ rtems_status_code _Semaphore_Translate_core_semaphore_return_code_[] = {
RTEMS_OBJECT_WAS_DELETED, /* CORE_SEMAPHORE_WAS_DELETED */
RTEMS_TIMEOUT, /* CORE_SEMAPHORE_TIMEOUT */
RTEMS_INTERNAL_ERROR, /* CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED */
RTEMS_INTERNAL_ERROR /* CORE_SEMAPHORE_BAD_TIMEOUT_VALUE */
};
rtems_status_code _Semaphore_Translate_core_semaphore_return_code (
uint32_t the_semaphore_status
uint32_t status
)
{
#if defined(RTEMS_MULTIPROCESSING)
if ( the_semaphore_status == THREAD_STATUS_PROXY_BLOCKING )
if ( status == THREAD_STATUS_PROXY_BLOCKING )
return RTEMS_PROXY_BLOCKING;
else
#endif
if ( the_semaphore_status > CORE_MUTEX_STATUS_CEILING_VIOLATED )
if ( status > CORE_MUTEX_STATUS_CEILING_VIOLATED )
return RTEMS_INTERNAL_ERROR;
else
return _Semaphore_Translate_core_semaphore_return_code_[the_semaphore_status];
return _Semaphore_Translate_core_semaphore_return_code_[status];
}

View File

@@ -82,7 +82,14 @@ typedef enum {
/** This status indicates that an attempt was made to unlock the semaphore
* and this would have made its count greater than that allowed.
*/
CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED
CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED,
/** This status indicates that the semaphore was not immediately
* available and the caller passed a bad timeout value to the API
* routine. In this case, the API required that the validity check
* for the timeout occur after the check that the semaphore was immediately
* available.
*/
CORE_SEMAPHORE_BAD_TIMEOUT_VALUE
} CORE_semaphore_Status;
/**
@@ -115,6 +122,25 @@ typedef struct {
uint32_t count;
} CORE_semaphore_Control;
/**
* The following enumerated type is the set of blocking options
* available to seize operation.
*/
typedef enum {
/** This value indicates that the caller does not wish to block. */
CORE_SEMAPHORE_NO_WAIT,
/** This value indicates that the caller is willing to block forever. */
CORE_SEMAPHORE_BLOCK_FOREVER,
/** This value indicates that the caller is blocking with a timeout. */
CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT,
/** This value indicates that the caller wanted to block but passed in
* a bad timeout value to the API. Unfortunately, this is a weird case
* where the timeout bad error is required to be generated only if
* the semaphore is not available.
*/
CORE_SEMAPHORE_BAD_TIMEOUT
} Core_semaphore_Blocking_option;
/**
* This routine initializes the semaphore based on the parameters passed.
*
@@ -137,15 +163,15 @@ void _CORE_semaphore_Initialize(
* @param[in] the_semaphore is the semaphore to seize
* @param[in] id is the Id of the API level Semaphore object associated
* with this instance of a SuperCore Semaphore
* @param[in] wait is TRUE if the calling thread is willing to wait
* @param[in] wait is the blocking mode
* @param[in] timeout is the number of ticks the calling thread is willing
* to wait if @a wait is TRUE.
*/
void _CORE_semaphore_Seize(
CORE_semaphore_Control *the_semaphore,
Objects_Id id,
boolean wait,
Watchdog_Interval timeout
CORE_semaphore_Control *the_semaphore,
Objects_Id id,
Core_semaphore_Blocking_option wait,
Watchdog_Interval timeout
);
/**

View File

@@ -51,10 +51,10 @@
*/
void _CORE_semaphore_Seize(
CORE_semaphore_Control *the_semaphore,
Objects_Id id,
boolean wait,
Watchdog_Interval timeout
CORE_semaphore_Control *the_semaphore,
Objects_Id id,
Core_semaphore_Blocking_option wait,
Watchdog_Interval timeout
)
{
Thread_Control *executing;
@@ -69,16 +69,22 @@ void _CORE_semaphore_Seize(
return;
}
if ( !wait ) {
_ISR_Enable( level );
executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
return;
switch ( wait ) {
case CORE_SEMAPHORE_NO_WAIT:
_ISR_Enable( level );
executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
return;
case CORE_SEMAPHORE_BAD_TIMEOUT:
executing->Wait.return_code = CORE_SEMAPHORE_BAD_TIMEOUT_VALUE;
return;
case CORE_SEMAPHORE_BLOCK_FOREVER:
case CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT:
_Thread_queue_Enter_critical_section( &the_semaphore->Wait_queue );
executing->Wait.queue = &the_semaphore->Wait_queue;
executing->Wait.id = id;
_ISR_Enable( level );
_Thread_queue_Enqueue( &the_semaphore->Wait_queue, timeout );
break;
}
_Thread_queue_Enter_critical_section( &the_semaphore->Wait_queue );
executing->Wait.queue = &the_semaphore->Wait_queue;
executing->Wait.id = id;
_ISR_Enable( level );
_Thread_queue_Enqueue( &the_semaphore->Wait_queue, timeout );
}