diff options
author | davidxu <davidxu@FreeBSD.org> | 2012-03-30 05:40:26 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2012-03-30 05:40:26 +0000 |
commit | 5faf75d34c8ad355303128c8e1f609133ad784f8 (patch) | |
tree | cd1d1346663560b38a2f37314722378439a07481 /sys/kern | |
parent | 4b53a41d86ee212a0d5a384d5990bf0f4391af54 (diff) | |
download | FreeBSD-src-5faf75d34c8ad355303128c8e1f609133ad784f8.zip FreeBSD-src-5faf75d34c8ad355303128c8e1f609133ad784f8.tar.gz |
Merge umtxq_sleep and umtxq_nanosleep into a single function by using
an abs_timeout structure which describes timeout info.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_umtx.c | 436 |
1 files changed, 172 insertions, 264 deletions
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c index b550f48..7e21335 100644 --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -187,6 +187,12 @@ struct umtxq_chain { #define BUSY_SPINS 200 +struct abs_timeout { + int clockid; + struct timespec cur; + struct timespec end; +}; + static uma_zone_t umtx_pi_zone; static struct umtxq_chain umtxq_chains[2][UMTX_CHAINS]; static MALLOC_DEFINE(M_UMTX, "umtx", "UMTX queue memory"); @@ -211,7 +217,7 @@ static void umtxq_busy(struct umtx_key *key); static void umtxq_unbusy(struct umtx_key *key); static void umtxq_insert_queue(struct umtx_q *uq, int q); static void umtxq_remove_queue(struct umtx_q *uq, int q); -static int umtxq_sleep(struct umtx_q *uq, const char *wmesg, int timo); +static int umtxq_sleep(struct umtx_q *uq, const char *wmesg, struct abs_timeout *); static int umtxq_count(struct umtx_key *key); static struct umtx_pi *umtx_pi_alloc(int); static void umtx_pi_free(struct umtx_pi *pi); @@ -547,23 +553,84 @@ umtxq_signal_thread(struct umtx_q *uq) wakeup(uq); } +static inline int +tstohz(const struct timespec *tsp) +{ + struct timeval tv; + + TIMESPEC_TO_TIMEVAL(&tv, tsp); + return tvtohz(&tv); +} + +static void +abs_timeout_init(struct abs_timeout *timo, int clockid, int absolute, + const struct timespec *timeout) +{ + + timo->clockid = clockid; + if (!absolute) { + kern_clock_gettime(curthread, clockid, &timo->end); + timo->cur = timo->end; + timespecadd(&timo->end, timeout); + } else { + timo->end = *timeout; + kern_clock_gettime(curthread, clockid, &timo->cur); + } +} + +static void +abs_timeout_init2(struct abs_timeout *timo, const struct _umtx_time *umtxtime) +{ + + abs_timeout_init(timo, umtxtime->_clockid, + (umtxtime->_flags & UMTX_ABSTIME) != 0, + &umtxtime->_timeout); +} + +static int +abs_timeout_update(struct abs_timeout *timo) +{ + kern_clock_gettime(curthread, timo->clockid, &timo->cur); + return (timespeccmp(&timo->cur, &timo->end, >=)); +} + +static int +abs_timeout_gethz(struct abs_timeout *timo) +{ + struct timespec tts; + + tts = timo->end; + timespecsub(&tts, &timo->cur); + return (tstohz(&tts)); +} + /* * Put thread into sleep state, before sleeping, check if * thread was removed from umtx queue. */ static inline int -umtxq_sleep(struct umtx_q *uq, const char *wmesg, int timo) +umtxq_sleep(struct umtx_q *uq, const char *wmesg, struct abs_timeout *timo) { struct umtxq_chain *uc; int error; uc = umtxq_getchain(&uq->uq_key); UMTXQ_LOCKED_ASSERT(uc); - if (!(uq->uq_flags & UQF_UMTXQ)) - return (0); - error = msleep(uq, &uc->uc_lock, PCATCH, wmesg, timo); - if (error == EWOULDBLOCK) - error = ETIMEDOUT; + for (;;) { + if (!(uq->uq_flags & UQF_UMTXQ)) + return (0); + error = msleep(uq, &uc->uc_lock, PCATCH, wmesg, + timo == NULL ? 0 : abs_timeout_gethz(timo)); + if (error != EWOULDBLOCK) + break; + umtxq_unlock(&uq->uq_key); + if (abs_timeout_update(timo)) { + error = ETIMEDOUT; + umtxq_lock(&uq->uq_key); + break; + } + umtxq_lock(&uq->uq_key); + } return (error); } @@ -627,14 +694,18 @@ umtx_key_release(struct umtx_key *key) * Lock a umtx object. */ static int -_do_lock_umtx(struct thread *td, struct umtx *umtx, u_long id, int timo) +do_lock_umtx(struct thread *td, struct umtx *umtx, u_long id, + const struct timespec *timeout) { + struct abs_timeout timo; struct umtx_q *uq; u_long owner; u_long old; int error = 0; uq = td->td_umtxq; + if (timeout != NULL) + abs_timeout_init(&timo, CLOCK_REALTIME, 0, timeout); /* * Care must be exercised when dealing with umtx structure. It @@ -675,7 +746,7 @@ _do_lock_umtx(struct thread *td, struct umtx *umtx, u_long id, int timo) * exit immediately. */ if (error != 0) - return (error); + break; if ((error = umtx_key_get(umtx, TYPE_SIMPLE_LOCK, AUTO_SHARE, &uq->uq_key)) != 0) @@ -711,48 +782,18 @@ _do_lock_umtx(struct thread *td, struct umtx *umtx, u_long id, int timo) */ umtxq_lock(&uq->uq_key); if (old == owner) - error = umtxq_sleep(uq, "umtx", timo); + error = umtxq_sleep(uq, "umtx", timeout == NULL ? NULL : + &timo); umtxq_remove(uq); umtxq_unlock(&uq->uq_key); umtx_key_release(&uq->uq_key); } - return (0); -} - -/* - * Lock a umtx object. - */ -static int -do_lock_umtx(struct thread *td, struct umtx *umtx, u_long id, - struct timespec *timeout) -{ - struct timespec ts, ts2, ts3; - struct timeval tv; - int error; - if (timeout == NULL) { - error = _do_lock_umtx(td, umtx, id, 0); /* Mutex locking is restarted if it is interrupted. */ if (error == EINTR) error = ERESTART; } else { - getnanouptime(&ts); - timespecadd(&ts, timeout); - TIMESPEC_TO_TIMEVAL(&tv, timeout); - for (;;) { - error = _do_lock_umtx(td, umtx, id, tvtohz(&tv)); - if (error != ETIMEDOUT) - break; - getnanouptime(&ts2); - if (timespeccmp(&ts2, &ts, >=)) { - error = ETIMEDOUT; - break; - } - ts3 = ts; - timespecsub(&ts3, &ts2); - TIMESPEC_TO_TIMEVAL(&tv, &ts3); - } /* Timed-locking is not restarted. */ if (error == ERESTART) error = EINTR; @@ -827,8 +868,10 @@ do_unlock_umtx(struct thread *td, struct umtx *umtx, u_long id) * Lock a umtx object. */ static int -_do_lock_umtx32(struct thread *td, uint32_t *m, uint32_t id, int timo) +do_lock_umtx32(struct thread *td, uint32_t *m, uint32_t id, + const struct timespec *timeout) { + struct abs_timeout timo; struct umtx_q *uq; uint32_t owner; uint32_t old; @@ -836,6 +879,9 @@ _do_lock_umtx32(struct thread *td, uint32_t *m, uint32_t id, int timo) uq = td->td_umtxq; + if (timeout != NULL) + abs_timeout_init(&timo, CLOCK_REALTIME, 0, timeout); + /* * Care must be exercised when dealing with umtx structure. It * can fault on any access. @@ -910,48 +956,18 @@ _do_lock_umtx32(struct thread *td, uint32_t *m, uint32_t id, int timo) */ umtxq_lock(&uq->uq_key); if (old == owner) - error = umtxq_sleep(uq, "umtx", timo); + error = umtxq_sleep(uq, "umtx", timeout == NULL ? + NULL : timo); umtxq_remove(uq); umtxq_unlock(&uq->uq_key); umtx_key_release(&uq->uq_key); } - return (0); -} - -/* - * Lock a umtx object. - */ -static int -do_lock_umtx32(struct thread *td, void *m, uint32_t id, - struct timespec *timeout) -{ - struct timespec ts, ts2, ts3; - struct timeval tv; - int error; - if (timeout == NULL) { - error = _do_lock_umtx32(td, m, id, 0); /* Mutex locking is restarted if it is interrupted. */ if (error == EINTR) error = ERESTART; } else { - getnanouptime(&ts); - timespecadd(&ts, timeout); - TIMESPEC_TO_TIMEVAL(&tv, timeout); - for (;;) { - error = _do_lock_umtx32(td, m, id, tvtohz(&tv)); - if (error != ETIMEDOUT) - break; - getnanouptime(&ts2); - if (timespeccmp(&ts2, &ts, >=)) { - error = ETIMEDOUT; - break; - } - ts3 = ts; - timespecsub(&ts3, &ts2); - TIMESPEC_TO_TIMEVAL(&tv, &ts3); - } /* Timed-locking is not restarted. */ if (error == ERESTART) error = EINTR; @@ -1021,51 +1037,6 @@ do_unlock_umtx32(struct thread *td, uint32_t *m, uint32_t id) } #endif -static inline int -tstohz(const struct timespec *tsp) -{ - struct timeval tv; - - TIMESPEC_TO_TIMEVAL(&tv, tsp); - return tvtohz(&tv); -} - -static int -umtxq_nanosleep(struct thread *td, int clockid, int absolute, - struct timespec *timeout, const char *mesg) -{ - struct umtx_q *uq; - struct timespec ets, cts, tts; - int error; - - uq = td->td_umtxq; - umtxq_unlock(&uq->uq_key); - if (!absolute) { - kern_clock_gettime(td, clockid, &ets); - timespecadd(&ets, timeout); - tts = *timeout; - } else { /* absolute time */ - ets = *timeout; - tts = *timeout; - kern_clock_gettime(td, clockid, &cts); - timespecsub(&tts, &cts); - } - umtxq_lock(&uq->uq_key); - for (;;) { - error = umtxq_sleep(uq, mesg, tstohz(&tts)); - if (error != ETIMEDOUT) - break; - kern_clock_gettime(td, clockid, &cts); - if (timespeccmp(&cts, &ets, >=)) { - error = ETIMEDOUT; - break; - } - tts = ets; - timespecsub(&tts, &cts); - } - return (error); -} - /* * Fetch and compare value, sleep on the address if value is not changed. */ @@ -1073,6 +1044,7 @@ static int do_wait(struct thread *td, void *addr, u_long id, struct _umtx_time *timeout, int compat32, int is_private) { + struct abs_timeout timo; struct umtx_q *uq; u_long tmp; int error = 0; @@ -1082,6 +1054,9 @@ do_wait(struct thread *td, void *addr, u_long id, is_private ? THREAD_SHARE : AUTO_SHARE, &uq->uq_key)) != 0) return (error); + if (timeout != NULL) + abs_timeout_init2(&timo, timeout); + umtxq_lock(&uq->uq_key); umtxq_insert(uq); umtxq_unlock(&uq->uq_key); @@ -1090,15 +1065,9 @@ do_wait(struct thread *td, void *addr, u_long id, else tmp = (unsigned int)fuword32(addr); umtxq_lock(&uq->uq_key); - if (tmp == id) { - if (timeout == NULL) - error = umtxq_sleep(uq, "uwait", 0); - else - error = umtxq_nanosleep(td, timeout->_clockid, - ((timeout->_flags & UMTX_ABSTIME) != 0), - &timeout->_timeout, "uwait"); - } - + if (tmp == id) + error = umtxq_sleep(uq, "uwait", timeout == NULL ? + NULL : &timo); if ((uq->uq_flags & UQF_UMTXQ) == 0) error = 0; else @@ -1133,9 +1102,10 @@ kern_umtx_wake(struct thread *td, void *uaddr, int n_wake, int is_private) * Lock PTHREAD_PRIO_NONE protocol POSIX mutex. */ static int -_do_lock_normal(struct thread *td, struct umutex *m, uint32_t flags, int timo, - int mode) +do_lock_normal(struct thread *td, struct umutex *m, uint32_t flags, + struct _umtx_time *timeout, int mode) { + struct abs_timeout timo; struct umtx_q *uq; uint32_t owner, old, id; int error = 0; @@ -1143,6 +1113,9 @@ _do_lock_normal(struct thread *td, struct umutex *m, uint32_t flags, int timo, id = td->td_tid; uq = td->td_umtxq; + if (timeout != NULL) + abs_timeout_init2(&timo, timeout); + /* * Care must be exercised when dealing with umtx structure. It * can fault on any access. @@ -1194,7 +1167,7 @@ _do_lock_normal(struct thread *td, struct umutex *m, uint32_t flags, int timo, * If we caught a signal, we have retried and now * exit immediately. */ - if (error != 0) + if (error != 0) return (error); if ((error = umtx_key_get(m, TYPE_NORMAL_UMUTEX, @@ -1232,7 +1205,8 @@ _do_lock_normal(struct thread *td, struct umutex *m, uint32_t flags, int timo, umtxq_lock(&uq->uq_key); umtxq_unbusy(&uq->uq_key); if (old == owner) - error = umtxq_sleep(uq, "umtxn", timo); + error = umtxq_sleep(uq, "umtxn", timeout == NULL ? + NULL : &timo); umtxq_remove(uq); umtxq_unlock(&uq->uq_key); umtx_key_release(&uq->uq_key); @@ -1574,7 +1548,7 @@ umtx_pi_adjust(struct thread *td, u_char oldpri) */ static int umtxq_sleep_pi(struct umtx_q *uq, struct umtx_pi *pi, - uint32_t owner, const char *wmesg, int timo) + uint32_t owner, const char *wmesg, struct abs_timeout *timo) { struct umtxq_chain *uc; struct thread *td, *td1; @@ -1620,14 +1594,9 @@ umtxq_sleep_pi(struct umtx_q *uq, struct umtx_pi *pi, mtx_unlock_spin(&umtx_lock); umtxq_unbusy(&uq->uq_key); - if (uq->uq_flags & UQF_UMTXQ) { - error = msleep(uq, &uc->uc_lock, PCATCH, wmesg, timo); - if (error == EWOULDBLOCK) - error = ETIMEDOUT; - if (uq->uq_flags & UQF_UMTXQ) { - umtxq_remove(uq); - } - } + error = umtxq_sleep(uq, wmesg, timo); + umtxq_remove(uq); + mtx_lock_spin(&umtx_lock); uq->uq_pi_blocked = NULL; thread_lock(td); @@ -1718,9 +1687,10 @@ umtx_pi_insert(struct umtx_pi *pi) * Lock a PI mutex. */ static int -_do_lock_pi(struct thread *td, struct umutex *m, uint32_t flags, int timo, - int try) +do_lock_pi(struct thread *td, struct umutex *m, uint32_t flags, + struct _umtx_time *timeout, int try) { + struct abs_timeout timo; struct umtx_q *uq; struct umtx_pi *pi, *new_pi; uint32_t id, owner, old; @@ -1732,6 +1702,10 @@ _do_lock_pi(struct thread *td, struct umutex *m, uint32_t flags, int timo, if ((error = umtx_key_get(m, TYPE_PI_UMUTEX, GET_SHARE(flags), &uq->uq_key)) != 0) return (error); + + if (timeout != NULL) + abs_timeout_init2(&timo, timeout); + umtxq_lock(&uq->uq_key); pi = umtx_pi_lookup(&uq->uq_key); if (pi == NULL) { @@ -1848,7 +1822,7 @@ _do_lock_pi(struct thread *td, struct umutex *m, uint32_t flags, int timo, */ if (old == owner) error = umtxq_sleep_pi(uq, pi, owner & ~UMUTEX_CONTESTED, - "umtxpi", timo); + "umtxpi", timeout == NULL ? NULL : &timo); else { umtxq_unbusy(&uq->uq_key); umtxq_unlock(&uq->uq_key); @@ -1967,9 +1941,10 @@ do_unlock_pi(struct thread *td, struct umutex *m, uint32_t flags) * Lock a PP mutex. */ static int -_do_lock_pp(struct thread *td, struct umutex *m, uint32_t flags, int timo, - int try) +do_lock_pp(struct thread *td, struct umutex *m, uint32_t flags, + struct _umtx_time *timeout, int try) { + struct abs_timeout timo; struct umtx_q *uq, *uq2; struct umtx_pi *pi; uint32_t ceiling; @@ -1981,6 +1956,10 @@ _do_lock_pp(struct thread *td, struct umutex *m, uint32_t flags, int timo, if ((error = umtx_key_get(m, TYPE_PP_UMUTEX, GET_SHARE(flags), &uq->uq_key)) != 0) return (error); + + if (timeout != NULL) + abs_timeout_init2(&timo, timeout); + su = (priv_check(td, PRIV_SCHED_RTPRIO) == 0); for (;;) { old_inherited_pri = uq->uq_inherited_pri; @@ -2044,7 +2023,8 @@ _do_lock_pp(struct thread *td, struct umutex *m, uint32_t flags, int timo, umtxq_lock(&uq->uq_key); umtxq_insert(uq); umtxq_unbusy(&uq->uq_key); - error = umtxq_sleep(uq, "umtxpp", timo); + error = umtxq_sleep(uq, "umtxpp", timeout == NULL ? + NULL : &timo); umtxq_remove(uq); umtxq_unlock(&uq->uq_key); @@ -2244,7 +2224,7 @@ do_set_ceiling(struct thread *td, struct umutex *m, uint32_t ceiling, umtxq_lock(&uq->uq_key); umtxq_insert(uq); umtxq_unbusy(&uq->uq_key); - error = umtxq_sleep(uq, "umtxpp", 0); + error = umtxq_sleep(uq, "umtxpp", NULL); umtxq_remove(uq); umtxq_unlock(&uq->uq_key); } @@ -2259,29 +2239,13 @@ do_set_ceiling(struct thread *td, struct umutex *m, uint32_t ceiling, return (error); } -static int -_do_lock_umutex(struct thread *td, struct umutex *m, int flags, int timo, - int mode) -{ - switch(flags & (UMUTEX_PRIO_INHERIT | UMUTEX_PRIO_PROTECT)) { - case 0: - return (_do_lock_normal(td, m, flags, timo, mode)); - case UMUTEX_PRIO_INHERIT: - return (_do_lock_pi(td, m, flags, timo, mode)); - case UMUTEX_PRIO_PROTECT: - return (_do_lock_pp(td, m, flags, timo, mode)); - } - return (EINVAL); -} - /* * Lock a userland POSIX mutex. */ static int do_lock_umutex(struct thread *td, struct umutex *m, - struct _umtx_time *timeout, int mode) + struct _umtx_time *timeout, int mode) { - struct timespec cts, ets, tts; uint32_t flags; int error; @@ -2289,32 +2253,23 @@ do_lock_umutex(struct thread *td, struct umutex *m, if (flags == -1) return (EFAULT); + switch(flags & (UMUTEX_PRIO_INHERIT | UMUTEX_PRIO_PROTECT)) { + case 0: + error = do_lock_normal(td, m, flags, timeout, mode); + break; + case UMUTEX_PRIO_INHERIT: + error = do_lock_pi(td, m, flags, timeout, mode); + break; + case UMUTEX_PRIO_PROTECT: + error = do_lock_pp(td, m, flags, timeout, mode); + break; + default: + return (EINVAL); + } if (timeout == NULL) { - error = _do_lock_umutex(td, m, flags, 0, mode); - /* Mutex locking is restarted if it is interrupted. */ if (error == EINTR && mode != _UMUTEX_WAIT) error = ERESTART; } else { - kern_clock_gettime(td, timeout->_clockid, &cts); - if ((timeout->_flags & UMTX_ABSTIME) == 0) { - ets = cts; - timespecadd(&ets, &timeout->_timeout); - tts = timeout->_timeout; - } else { - ets = timeout->_timeout; - tts = timeout->_timeout; - timespecsub(&tts, &cts); - } - for (;;) { - error = _do_lock_umutex(td, m, flags, tstohz(&tts), mode); - if (error != ETIMEDOUT) - break; - kern_clock_gettime(td, timeout->_clockid, &cts); - if (timespeccmp(&cts, &ets, >=)) - break; - tts = ets; - timespecsub(&tts, &cts); - } /* Timed-locking is not restarted. */ if (error == ERESTART) error = EINTR; @@ -2350,6 +2305,7 @@ static int do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m, struct timespec *timeout, u_long wflags) { + struct abs_timeout timo; struct umtx_q *uq; uint32_t flags; uint32_t clockid; @@ -2389,15 +2345,15 @@ do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m, umtxq_unlock(&uq->uq_key); error = do_unlock_umutex(td, m); + + if (timeout != NULL); + abs_timeout_init(&timo, clockid, ((wflags & CVWAIT_ABSTIME) != 0), + timeout); umtxq_lock(&uq->uq_key); if (error == 0) { - if (timeout == NULL) - error = umtxq_sleep(uq, "ucond", 0); - else - error = umtxq_nanosleep(td, clockid, - ((wflags & CVWAIT_ABSTIME) != 0), - timeout, "ucond"); + error = umtxq_sleep(uq, "ucond", timeout == NULL ? + NULL : &timo); } if ((uq->uq_flags & UQF_UMTXQ) == 0) @@ -2486,8 +2442,9 @@ do_cv_broadcast(struct thread *td, struct ucond *cv) } static int -do_rw_rdlock(struct thread *td, struct urwlock *rwlock, long fflag, int timo) +do_rw_rdlock(struct thread *td, struct urwlock *rwlock, long fflag, struct _umtx_time *timeout) { + struct abs_timeout timo; struct umtx_q *uq; uint32_t flags, wrflags; int32_t state, oldstate; @@ -2500,6 +2457,9 @@ do_rw_rdlock(struct thread *td, struct urwlock *rwlock, long fflag, int timo) if (error != 0) return (error); + if (timeout != NULL) + abs_timeout_init2(&timo, timeout); + wrflags = URWLOCK_WRITE_OWNER; if (!(fflag & URWLOCK_PREFER_READER) && !(flags & URWLOCK_PREFER_READER)) wrflags |= URWLOCK_WRITE_WAITERS; @@ -2560,7 +2520,8 @@ sleep: umtxq_insert(uq); umtxq_unbusy(&uq->uq_key); - error = umtxq_sleep(uq, "urdlck", timo); + error = umtxq_sleep(uq, "urdlck", timeout == NULL ? + NULL : &timo); umtxq_busy(&uq->uq_key); umtxq_remove(uq); @@ -2589,43 +2550,15 @@ sleep: umtxq_unlock(&uq->uq_key); } umtx_key_release(&uq->uq_key); - return (error); -} - -static int -do_rw_rdlock2(struct thread *td, void *obj, long val, struct _umtx_time *timeout) -{ - struct timespec cts, ets, tts; - int error; - - kern_clock_gettime(td, timeout->_clockid, &cts); - if ((timeout->_flags & UMTX_ABSTIME) == 0) { - ets = cts; - timespecadd(&ets, &timeout->_timeout); - tts = timeout->_timeout; - } else { - ets = timeout->_timeout; - tts = timeout->_timeout; - timespecsub(&tts, &cts); - } - for (;;) { - error = do_rw_rdlock(td, obj, val, tstohz(&tts)); - if (error != ETIMEDOUT) - break; - kern_clock_gettime(td, timeout->_clockid, &cts); - if (timespeccmp(&cts, &ets, >=)) - break; - tts = ets; - timespecsub(&tts, &cts); - } if (error == ERESTART) error = EINTR; return (error); } static int -do_rw_wrlock(struct thread *td, struct urwlock *rwlock, int timo) +do_rw_wrlock(struct thread *td, struct urwlock *rwlock, struct _umtx_time *timeout) { + struct abs_timeout timo; struct umtx_q *uq; uint32_t flags; int32_t state, oldstate; @@ -2639,6 +2572,9 @@ do_rw_wrlock(struct thread *td, struct urwlock *rwlock, int timo) if (error != 0) return (error); + if (timeout != NULL) + abs_timeout_init2(&timo, timeout); + blocked_readers = 0; for (;;) { state = fuword32(__DEVOLATILE(int32_t *, &rwlock->rw_state)); @@ -2698,7 +2634,8 @@ sleep: umtxq_insert_queue(uq, UMTX_EXCLUSIVE_QUEUE); umtxq_unbusy(&uq->uq_key); - error = umtxq_sleep(uq, "uwrlck", timo); + error = umtxq_sleep(uq, "uwrlck", timeout == NULL ? + NULL : &timo); umtxq_busy(&uq->uq_key); umtxq_remove_queue(uq, UMTX_EXCLUSIVE_QUEUE); @@ -2729,35 +2666,6 @@ sleep: } umtx_key_release(&uq->uq_key); - return (error); -} - -static int -do_rw_wrlock2(struct thread *td, void *obj, struct _umtx_time *timeout) -{ - struct timespec cts, ets, tts; - int error; - - kern_clock_gettime(td, timeout->_clockid, &cts); - if ((timeout->_flags & UMTX_ABSTIME) == 0) { - ets = cts; - timespecadd(&ets, &timeout->_timeout); - tts = timeout->_timeout; - } else { - ets = timeout->_timeout; - tts = timeout->_timeout; - timespecsub(&tts, &cts); - } - for (;;) { - error = do_rw_wrlock(td, obj, tstohz(&tts)); - if (error != ETIMEDOUT) - break; - kern_clock_gettime(td, timeout->_clockid, &cts); - if (timespeccmp(&cts, &ets, >=)) - break; - tts = ets; - timespecsub(&tts, &cts); - } if (error == ERESTART) error = EINTR; return (error); @@ -2845,6 +2753,7 @@ out: static int do_sem_wait(struct thread *td, struct _usem *sem, struct _umtx_time *timeout) { + struct abs_timeout timo; struct umtx_q *uq; uint32_t flags, count; int error; @@ -2854,6 +2763,10 @@ do_sem_wait(struct thread *td, struct _usem *sem, struct _umtx_time *timeout) error = umtx_key_get(sem, TYPE_SEM, GET_SHARE(flags), &uq->uq_key); if (error != 0) return (error); + + if (timeout != NULL) + abs_timeout_init2(&timo, timeout); + umtxq_lock(&uq->uq_key); umtxq_busy(&uq->uq_key); umtxq_insert(uq); @@ -2873,12 +2786,7 @@ do_sem_wait(struct thread *td, struct _usem *sem, struct _umtx_time *timeout) umtxq_lock(&uq->uq_key); umtxq_unbusy(&uq->uq_key); - if (timeout == NULL) - error = umtxq_sleep(uq, "usem", 0); - else - error = umtxq_nanosleep(td, timeout->_clockid, - ((timeout->_flags & UMTX_ABSTIME) != 0), - &timeout->_timeout, "usem"); + error = umtxq_sleep(uq, "usem", timeout == NULL ? NULL : &timo); if ((uq->uq_flags & UQF_UMTXQ) == 0) error = 0; @@ -2925,7 +2833,7 @@ int sys__umtx_lock(struct thread *td, struct _umtx_lock_args *uap) /* struct umtx *umtx */ { - return _do_lock_umtx(td, uap->umtx, td->td_tid, 0); + return do_lock_umtx(td, uap->umtx, td->td_tid, 0); } int @@ -3191,7 +3099,7 @@ __umtx_op_rw_rdlock(struct thread *td, struct _umtx_op_args *uap) (size_t)uap->uaddr1, &timeout); if (error != 0) return (error); - error = do_rw_rdlock2(td, uap->obj, uap->val, &timeout); + error = do_rw_rdlock(td, uap->obj, uap->val, &timeout); } return (error); } @@ -3211,7 +3119,7 @@ __umtx_op_rw_wrlock(struct thread *td, struct _umtx_op_args *uap) if (error != 0) return (error); - error = do_rw_wrlock2(td, uap->obj, &timeout); + error = do_rw_wrlock(td, uap->obj, &timeout); } return (error); } |