123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- #include <errno.h>
- #include <sysdep.h>
- #include <lowlevellock.h>
- #include <pthread.h>
- #include <pthreadP.h>
- int
- pthread_rwlock_timedwrlock (
- pthread_rwlock_t *rwlock,
- const struct timespec *abstime)
- {
- int result = 0;
-
- lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
- while (1)
- {
- int err;
-
- if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0)
- {
-
- rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid);
- break;
- }
-
- if (__builtin_expect (rwlock->__data.__writer
- == THREAD_GETMEM (THREAD_SELF, tid), 0))
- {
- result = EDEADLK;
- break;
- }
-
- if (__builtin_expect (abstime->tv_nsec >= 1000000000
- || abstime->tv_nsec < 0, 0))
- {
- result = EINVAL;
- break;
- }
-
- struct timeval tv;
- (void) gettimeofday (&tv, NULL);
-
- struct timespec rt;
- rt.tv_sec = abstime->tv_sec - tv.tv_sec;
- rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
- if (rt.tv_nsec < 0)
- {
- rt.tv_nsec += 1000000000;
- --rt.tv_sec;
- }
-
- if (rt.tv_sec < 0)
- {
- result = ETIMEDOUT;
- break;
- }
-
- if (++rwlock->__data.__nr_writers_queued == 0)
- {
-
- --rwlock->__data.__nr_writers_queued;
- result = EAGAIN;
- break;
- }
- int waitval = rwlock->__data.__writer_wakeup;
-
- lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared);
-
- err = lll_futex_timed_wait (&rwlock->__data.__writer_wakeup,
- waitval, &rt, rwlock->__data.__shared);
-
- lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
-
- --rwlock->__data.__nr_writers_queued;
-
- if (err == -ETIMEDOUT)
- {
- result = ETIMEDOUT;
- break;
- }
- }
-
- lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared);
- return result;
- }
|