From 96aacc2279b7b65fc0c8ff707abe3d020c1e8378 Mon Sep 17 00:00:00 2001 From: davidxu Date: Mon, 27 Feb 2012 13:38:52 +0000 Subject: [PATCH] Follow changes made in revision 232144, pass absolute timeout to kernel, this eliminates a clock_gettime() syscall. --- lib/libthr/thread/thr_rwlock.c | 26 +--------- lib/libthr/thread/thr_umtx.c | 35 ++++++++++++-- lib/libthr/thread/thr_umtx.h | 6 ++- sys/kern/kern_umtx.c | 88 ++++++++++++++++++---------------- 4 files changed, 84 insertions(+), 71 deletions(-) diff --git a/lib/libthr/thread/thr_rwlock.c b/lib/libthr/thread/thr_rwlock.c index ebdeae7e6113..397663e9c710 100644 --- a/lib/libthr/thread/thr_rwlock.c +++ b/lib/libthr/thread/thr_rwlock.c @@ -123,7 +123,6 @@ rwlock_rdlock_common(pthread_rwlock_t *rwlock, const struct timespec *abstime) { struct pthread *curthread = _get_curthread(); pthread_rwlock_t prwlock; - struct timespec ts, ts2, *tsp; int flags; int ret; @@ -162,18 +161,8 @@ rwlock_rdlock_common(pthread_rwlock_t *rwlock, const struct timespec *abstime) return (EINVAL); for (;;) { - if (abstime) { - clock_gettime(CLOCK_REALTIME, &ts); - TIMESPEC_SUB(&ts2, abstime, &ts); - if (ts2.tv_sec < 0 || - (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) - return (ETIMEDOUT); - tsp = &ts2; - } else - tsp = NULL; - /* goto kernel and lock it */ - ret = __thr_rwlock_rdlock(&prwlock->lock, flags, tsp); + ret = __thr_rwlock_rdlock(&prwlock->lock, flags, abstime); if (ret != EINTR) break; @@ -255,7 +244,6 @@ rwlock_wrlock_common (pthread_rwlock_t *rwlock, const struct timespec *abstime) { struct pthread *curthread = _get_curthread(); pthread_rwlock_t prwlock; - struct timespec ts, ts2, *tsp; int ret; CHECK_AND_INIT_RWLOCK @@ -275,18 +263,8 @@ rwlock_wrlock_common (pthread_rwlock_t *rwlock, const struct timespec *abstime) return (EINVAL); for (;;) { - if (abstime != NULL) { - clock_gettime(CLOCK_REALTIME, &ts); - TIMESPEC_SUB(&ts2, abstime, &ts); - if (ts2.tv_sec < 0 || - (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) - return (ETIMEDOUT); - tsp = &ts2; - } else - tsp = NULL; - /* goto kernel and lock it */ - ret = __thr_rwlock_wrlock(&prwlock->lock, tsp); + ret = __thr_rwlock_wrlock(&prwlock->lock, abstime); if (ret == 0) { prwlock->owner = curthread; break; diff --git a/lib/libthr/thread/thr_umtx.c b/lib/libthr/thread/thr_umtx.c index 38c3b042b2af..f32596f6eafd 100644 --- a/lib/libthr/thread/thr_umtx.c +++ b/lib/libthr/thread/thr_umtx.c @@ -265,15 +265,42 @@ _thr_ucond_broadcast(struct ucond *cv) } int -__thr_rwlock_rdlock(struct urwlock *rwlock, int flags, struct timespec *tsp) +__thr_rwlock_rdlock(struct urwlock *rwlock, int flags, + const struct timespec *tsp) { - return _umtx_op_err(rwlock, UMTX_OP_RW_RDLOCK, flags, NULL, tsp); + struct _umtx_time timeout, *tm_p; + size_t tm_size; + + if (tsp == NULL) { + tm_p = NULL; + tm_size = 0; + } else { + timeout._timeout = *tsp; + timeout._flags = UMTX_ABSTIME; + timeout._clockid = CLOCK_REALTIME; + tm_p = &timeout; + tm_size = sizeof(timeout); + } + return _umtx_op_err(rwlock, UMTX_OP_RW_RDLOCK, flags, (void *)tm_size, tm_p); } int -__thr_rwlock_wrlock(struct urwlock *rwlock, struct timespec *tsp) +__thr_rwlock_wrlock(struct urwlock *rwlock, const struct timespec *tsp) { - return _umtx_op_err(rwlock, UMTX_OP_RW_WRLOCK, 0, NULL, tsp); + struct _umtx_time timeout, *tm_p; + size_t tm_size; + + if (tsp == NULL) { + tm_p = NULL; + tm_size = 0; + } else { + timeout._timeout = *tsp; + timeout._flags = UMTX_ABSTIME; + timeout._clockid = CLOCK_REALTIME; + tm_p = &timeout; + tm_size = sizeof(timeout); + } + return _umtx_op_err(rwlock, UMTX_OP_RW_WRLOCK, 0, (void *)tm_size, tm_p); } int diff --git a/lib/libthr/thread/thr_umtx.h b/lib/libthr/thread/thr_umtx.h index 0a8034b364e2..61a74a89db6b 100644 --- a/lib/libthr/thread/thr_umtx.h +++ b/lib/libthr/thread/thr_umtx.h @@ -60,8 +60,10 @@ void _thr_ucond_init(struct ucond *cv) __hidden; int _thr_ucond_signal(struct ucond *cv) __hidden; int _thr_ucond_broadcast(struct ucond *cv) __hidden; -int __thr_rwlock_rdlock(struct urwlock *rwlock, int flags, struct timespec *tsp) __hidden; -int __thr_rwlock_wrlock(struct urwlock *rwlock, struct timespec *tsp) __hidden; +int __thr_rwlock_rdlock(struct urwlock *rwlock, int flags, + const struct timespec *tsp) __hidden; +int __thr_rwlock_wrlock(struct urwlock *rwlock, + const struct timespec *tsp) __hidden; int __thr_rwlock_unlock(struct urwlock *rwlock) __hidden; /* Internal used only */ diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c index 790be668bdc9..49b015e9c980 100644 --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -2289,7 +2289,6 @@ do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m, struct timespec *timeout, u_long wflags) { struct umtx_q *uq; - struct timeval tv; struct timespec cts, ets, tts; uint32_t flags; uint32_t clockid; @@ -2345,9 +2344,8 @@ do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m, kern_clock_gettime(td, clockid, &cts); timespecsub(&tts, &cts); } - TIMESPEC_TO_TIMEVAL(&tv, &tts); for (;;) { - error = umtxq_sleep(uq, "ucond", tvtohz(&tv)); + error = umtxq_sleep(uq, "ucond", tstohz(&tts)); if (error != ETIMEDOUT) break; kern_clock_gettime(td, clockid, &cts); @@ -2357,7 +2355,6 @@ do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m, } tts = ets; timespecsub(&tts, &cts); - TIMESPEC_TO_TIMEVAL(&tv, &tts); } } } @@ -2555,27 +2552,30 @@ do_rw_rdlock(struct thread *td, struct urwlock *rwlock, long fflag, int timo) } static int -do_rw_rdlock2(struct thread *td, void *obj, long val, struct timespec *timeout) +do_rw_rdlock2(struct thread *td, void *obj, long val, struct _umtx_time *timeout) { - struct timespec ts, ts2, ts3; - struct timeval tv; + struct timespec cts, ets, tts; int error; - getnanouptime(&ts); - timespecadd(&ts, timeout); - TIMESPEC_TO_TIMEVAL(&tv, timeout); + 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, tvtohz(&tv)); + error = do_rw_rdlock(td, obj, val, tstohz(&tts)); if (error != ETIMEDOUT) break; - getnanouptime(&ts2); - if (timespeccmp(&ts2, &ts, >=)) { - error = ETIMEDOUT; + kern_clock_gettime(td, timeout->_clockid, &cts); + if (timespeccmp(&cts, &ets, >=)) break; - } - ts3 = ts; - timespecsub(&ts3, &ts2); - TIMESPEC_TO_TIMEVAL(&tv, &ts3); + tts = ets; + timespecsub(&tts, &cts); } if (error == ERESTART) error = EINTR; @@ -2692,27 +2692,30 @@ do_rw_wrlock(struct thread *td, struct urwlock *rwlock, int timo) } static int -do_rw_wrlock2(struct thread *td, void *obj, struct timespec *timeout) +do_rw_wrlock2(struct thread *td, void *obj, struct _umtx_time *timeout) { - struct timespec ts, ts2, ts3; - struct timeval tv; + struct timespec cts, ets, tts; int error; - getnanouptime(&ts); - timespecadd(&ts, timeout); - TIMESPEC_TO_TIMEVAL(&tv, timeout); + 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, tvtohz(&tv)); + error = do_rw_wrlock(td, obj, tstohz(&tts)); if (error != ETIMEDOUT) break; - getnanouptime(&ts2); - if (timespeccmp(&ts2, &ts, >=)) { - error = ETIMEDOUT; + kern_clock_gettime(td, timeout->_clockid, &cts); + if (timespeccmp(&cts, &ets, >=)) break; - } - ts3 = ts; - timespecsub(&ts3, &ts2); - TIMESPEC_TO_TIMEVAL(&tv, &ts3); + tts = ets; + timespecsub(&tts, &cts); } if (error == ERESTART) error = EINTR; @@ -3159,14 +3162,15 @@ __umtx_op_cv_broadcast(struct thread *td, struct _umtx_op_args *uap) static int __umtx_op_rw_rdlock(struct thread *td, struct _umtx_op_args *uap) { - struct timespec timeout; + struct _umtx_time timeout; int error; /* Allow a null timespec (wait forever). */ if (uap->uaddr2 == NULL) { error = do_rw_rdlock(td, uap->obj, uap->val, 0); } else { - error = umtx_copyin_timeout(uap->uaddr2, &timeout); + error = umtx_copyin_umtx_time(uap->uaddr2, + (size_t)uap->uaddr1, &timeout); if (error != 0) return (error); error = do_rw_rdlock2(td, uap->obj, uap->val, &timeout); @@ -3177,14 +3181,15 @@ __umtx_op_rw_rdlock(struct thread *td, struct _umtx_op_args *uap) static int __umtx_op_rw_wrlock(struct thread *td, struct _umtx_op_args *uap) { - struct timespec timeout; + struct _umtx_time timeout; int error; /* Allow a null timespec (wait forever). */ if (uap->uaddr2 == NULL) { error = do_rw_wrlock(td, uap->obj, 0); } else { - error = umtx_copyin_timeout(uap->uaddr2, &timeout); + error = umtx_copyin_umtx_time(uap->uaddr2, + (size_t)uap->uaddr1, &timeout); if (error != 0) return (error); @@ -3430,14 +3435,15 @@ __umtx_op_cv_wait_compat32(struct thread *td, struct _umtx_op_args *uap) static int __umtx_op_rw_rdlock_compat32(struct thread *td, struct _umtx_op_args *uap) { - struct timespec timeout; + struct _umtx_time timeout; int error; /* Allow a null timespec (wait forever). */ if (uap->uaddr2 == NULL) { error = do_rw_rdlock(td, uap->obj, uap->val, 0); } else { - error = umtx_copyin_timeout32(uap->uaddr2, &timeout); + error = umtx_copyin_umtx_time32(uap->uaddr2, + (size_t)uap->uaddr1, &timeout); if (error != 0) return (error); error = do_rw_rdlock2(td, uap->obj, uap->val, &timeout); @@ -3448,17 +3454,17 @@ __umtx_op_rw_rdlock_compat32(struct thread *td, struct _umtx_op_args *uap) static int __umtx_op_rw_wrlock_compat32(struct thread *td, struct _umtx_op_args *uap) { - struct timespec timeout; + struct _umtx_time timeout; int error; /* Allow a null timespec (wait forever). */ if (uap->uaddr2 == NULL) { error = do_rw_wrlock(td, uap->obj, 0); } else { - error = umtx_copyin_timeout32(uap->uaddr2, &timeout); + error = umtx_copyin_umtx_time32(uap->uaddr2, + (size_t)uap->uaddr1, &timeout); if (error != 0) return (error); - error = do_rw_wrlock2(td, uap->obj, &timeout); } return (error);