diff options
Diffstat (limited to 'cpukit/posix/src/mutextimedlock.c')
-rw-r--r-- | cpukit/posix/src/mutextimedlock.c | 54 |
1 files changed, 50 insertions, 4 deletions
diff --git a/cpukit/posix/src/mutextimedlock.c b/cpukit/posix/src/mutextimedlock.c index e86c3040dd..f1963c2efe 100644 --- a/cpukit/posix/src/mutextimedlock.c +++ b/cpukit/posix/src/mutextimedlock.c @@ -28,12 +28,58 @@ int pthread_mutex_timedlock( pthread_mutex_t *mutex, - const struct timespec *timeout + const struct timespec *abstime ) { - return _POSIX_Mutex_Lock_support( + Watchdog_Interval ticks; + boolean do_wait; + POSIX_Absolute_timeout_conversion_results_t status; + int lock_status; + + /* + * 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. + */ + 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_Mutex_Lock_support( mutex, - TRUE, - _POSIX_Timespec_to_interval( timeout ) + do_wait, + ticks ); + + /* + * This service only gives us the option to block. We used a polling + * attempt to lock if the abstime was not in the future. If we did + * not obtain the mutex, then not look at the status immediately, + * make sure the right reason is returned. + */ + 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 lock_status; } |