diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2008-07-18 18:45:56 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2008-07-18 18:45:56 +0000 |
commit | 6a0898bba30ccd936e0ac1d6268970316efe92c4 (patch) | |
tree | 364d967bdfcdb75695666e37263cb2f0bed3a077 /cpukit/posix/src/semtimedwait.c | |
parent | Changed special purpose register inline functions to macros. (diff) | |
download | rtems-6a0898bba30ccd936e0ac1d6268970316efe92c4.tar.bz2 |
2008-07-18 Joel Sherrill <joel.sherrill@oarcorp.com>
PR 1291/cpukit
* itron/inline/rtems/itron/semaphore.inl, itron/src/twai_sem.c,
posix/include/mqueue.h, posix/include/rtems/posix/mqueue.h,
posix/include/rtems/posix/semaphore.h,
posix/include/rtems/posix/time.h, posix/src/condtimedwait.c,
posix/src/mqueuereceive.c, posix/src/mqueuerecvsupp.c,
posix/src/mqueuesend.c, posix/src/mqueuesendsupp.c,
posix/src/mqueuetimedreceive.c, posix/src/mqueuetimedsend.c,
posix/src/mutextimedlock.c, posix/src/mutextranslatereturncode.c,
posix/src/posixtimespecabsolutetimeout.c,
posix/src/prwlocktimedrdlock.c, posix/src/prwlocktimedwrlock.c,
posix/src/semaphoretranslatereturncode.c,
posix/src/semaphorewaitsupp.c, posix/src/semtimedwait.c,
posix/src/semtrywait.c, posix/src/semwait.c,
posix/src/sigtimedwait.c, posix/src/timersettime.c,
posix/src/ualarm.c, rtems/src/semobtain.c,
rtems/src/semtranslatereturncode.c,
score/include/rtems/score/coremutex.h,
score/include/rtems/score/coresem.h, score/src/coresemseize.c: This
patch addresses issues on implementation of the timeout on the
following POSIX services. Some of these services incorrectly took a
timeout as a relative time. Others would compute a 0 delta to timeout
if the absolute time and the current time were equal and thus
incorrectly block the caller forever. The root of the confusion is
that POSIX specifies that if the timeout is incorrect (e.g. in the
past, is now, or is numerically invalid), that it does not matter if
the call would succeed without blocking. This is in contrast to RTEMS
programming style where all errors are checked before any critical
sections are entered. This fix implemented a more uniform way of
handling POSIX absolute time timeouts.
+ pthread_cond_timedwait - could block forever
+ mq_timedreceive - used relative not absolute time
+ mq_timedsend - used relative not absolute time
+ pthread_mutex_timedlock - used relative not absolute time
+ pthread_rwlock_timedrdlock- used relative not absolute time
+ pthread_rwlock_timedwrlock- used relative not absolute time
+ sem_timedwait - could block forever
Diffstat (limited to 'cpukit/posix/src/semtimedwait.c')
-rw-r--r-- | cpukit/posix/src/semtimedwait.c | 63 |
1 files changed, 41 insertions, 22 deletions
diff --git a/cpukit/posix/src/semtimedwait.c b/cpukit/posix/src/semtimedwait.c index 6b93b9232b..b76fa17a81 100644 --- a/cpukit/posix/src/semtimedwait.c +++ b/cpukit/posix/src/semtimedwait.c @@ -1,5 +1,5 @@ /* - * COPYRIGHT (c) 1989-2007. + * COPYRIGHT (c) 1989-2008. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -39,32 +39,51 @@ int sem_timedwait( const struct timespec *abstime ) { + Watchdog_Interval ticks; + boolean do_wait = TRUE; + POSIX_Absolute_timeout_conversion_results_t status; + int lock_status; + /* - * The abstime is a walltime. We turn it into an interval. + * 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. */ - Watchdog_Interval ticks = 0; - struct timespec current_time; - struct timespec difference; - Core_semaphore_Blocking_option blocking = CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT; + status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks ); + switch ( status ) { + case POSIX_ABSOLUTE_TIMEOUT_INVALID: + case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST: + case POSIX_ABSOLUTE_TIMEOUT_IS_NOW: + do_wait = FALSE; + break; + case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE: + do_wait = TRUE; + break; + } + + lock_status = _POSIX_Semaphore_Wait_support( sem, do_wait, ticks ); /* - * Error check the absolute time to timeout + * 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 ( !_Timespec_Is_valid( abstime ) ) { - blocking = CORE_SEMAPHORE_BAD_TIMEOUT_VALUE; - } else { - _TOD_Get( ¤t_time ); - /* - * Make sure the abstime is in the future - */ - if ( _Timespec_Less_than( abstime, ¤t_time ) ) { - blocking = CORE_SEMAPHORE_BAD_TIMEOUT; - } else { - _Timespec_Subtract( ¤t_time, abstime, &difference ); - ticks = _Timespec_To_ticks( &difference ); - blocking = CORE_SEMAPHORE_BLOCK_WITH_TIMEOUT; + if ( !do_wait && (lock_status == EBUSY) ) { + switch (lock_status) { + case POSIX_ABSOLUTE_TIMEOUT_INVALID: + return EINVAL; + case POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST: + case POSIX_ABSOLUTE_TIMEOUT_IS_NOW: + return ETIMEDOUT; + case POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE: + break; } - } + } - return _POSIX_Semaphore_Wait_support( sem, blocking, ticks ); + return lock_status; } |