summaryrefslogtreecommitdiffstats
path: root/cpukit/posix/src/prwlocktimedwrlock.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/posix/src/prwlocktimedwrlock.c')
-rw-r--r--cpukit/posix/src/prwlocktimedwrlock.c49
1 files changed, 40 insertions, 9 deletions
diff --git a/cpukit/posix/src/prwlocktimedwrlock.c b/cpukit/posix/src/prwlocktimedwrlock.c
index adf45b77fc..a826df8371 100644
--- a/cpukit/posix/src/prwlocktimedwrlock.c
+++ b/cpukit/posix/src/prwlocktimedwrlock.c
@@ -1,7 +1,7 @@
/*
* POSIX RWLock Manager -- Attempt to Obtain a Write Lock on a RWLock Instance
*
- * COPYRIGHT (c) 1989-2007.
+ * COPYRIGHT (c) 1989-2008.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -40,17 +40,35 @@ int pthread_rwlock_timedwrlock(
const struct timespec *abstime
)
{
- POSIX_RWLock_Control *the_rwlock;
- Objects_Locations location;
- int status;
- Watchdog_Interval ticks;
-
+ POSIX_RWLock_Control *the_rwlock;
+ Objects_Locations location;
+ Watchdog_Interval ticks;
+ boolean do_wait;
+ POSIX_Absolute_timeout_conversion_results_t status;
+
if ( !rwlock )
return EINVAL;
+ /*
+ * 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 );
- if ( status )
- return status;
+ 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;
+ }
the_rwlock = _POSIX_RWLock_Get( rwlock, &location );
switch ( location ) {
@@ -60,12 +78,25 @@ int pthread_rwlock_timedwrlock(
_CORE_RWLock_Obtain_for_writing(
&the_rwlock->RWLock,
*rwlock,
- TRUE, // we are willing to wait up to ticks
+ do_wait,
ticks,
NULL
);
_Thread_Enable_dispatch();
+ if ( !do_wait &&
+ (_Thread_Executing->Wait.return_code == CORE_RWLOCK_UNAVAILABLE) ) {
+ switch (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_RWLock_Translate_core_RWLock_return_code(
(CORE_RWLock_Status) _Thread_Executing->Wait.return_code
);