summaryrefslogtreecommitdiffstats
path: root/cpukit/posix/src/mutextimedlock.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/posix/src/mutextimedlock.c')
-rw-r--r--cpukit/posix/src/mutextimedlock.c54
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;
}