diff options
author | davidxu <davidxu@FreeBSD.org> | 2012-02-25 02:12:17 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2012-02-25 02:12:17 +0000 |
commit | 61033245ae03eb18451a20806786ac41f6bad7ee (patch) | |
tree | 5f0ee0973e89656c6bff9bc1ab050eff9e1ee496 /lib/libthr | |
parent | 1754fd0691ea56d59cc2527d2867e5b0f681e569 (diff) | |
download | FreeBSD-src-61033245ae03eb18451a20806786ac41f6bad7ee.zip FreeBSD-src-61033245ae03eb18451a20806786ac41f6bad7ee.tar.gz |
In revision 231989, we pass a 16-bit clock ID into kernel, however
according to POSIX document, the clock ID may be dynamically allocated,
it unlikely will be in 64K forever. To make it future compatible, we
pack all timeout information into a new structure called _umtx_time, and
use fourth argument as a size indication, a zero means it is old code
using timespec as timeout value, but the new structure also includes flags
and a clock ID, so the size argument is different than before, and it is
non-zero. With this change, it is possible that a thread can sleep
on any supported clock, though current kernel code does not have such a
POSIX clock driver system.
Diffstat (limited to 'lib/libthr')
-rw-r--r-- | lib/libthr/thread/thr_umtx.c | 49 |
1 files changed, 32 insertions, 17 deletions
diff --git a/lib/libthr/thread/thr_umtx.c b/lib/libthr/thread/thr_umtx.c index f7acac3..38c3b04 100644 --- a/lib/libthr/thread/thr_umtx.c +++ b/lib/libthr/thread/thr_umtx.c @@ -109,23 +109,30 @@ __thr_umutex_lock_spin(struct umutex *mtx, uint32_t id) int __thr_umutex_timedlock(struct umutex *mtx, uint32_t id, - const struct timespec *ets) + const struct timespec *abstime) { - struct timespec timo, cts; + struct _umtx_time *tm_p, timeout; + size_t tm_size; uint32_t owner; int ret; - clock_gettime(CLOCK_REALTIME, &cts); - TIMESPEC_SUB(&timo, ets, &cts); - - if (timo.tv_sec < 0) - return (ETIMEDOUT); + if (abstime == NULL) { + tm_p = NULL; + tm_size = 0; + } else { + timeout._clockid = CLOCK_REALTIME; + timeout._flags = UMTX_ABSTIME; + timeout._timeout = *abstime; + tm_p = &timeout; + tm_size = sizeof(timeout); + } for (;;) { if ((mtx->m_flags & (UMUTEX_PRIO_PROTECT | UMUTEX_PRIO_INHERIT)) == 0) { /* wait in kernel */ - ret = _umtx_op_err(mtx, UMTX_OP_MUTEX_WAIT, 0, 0, &timo); + ret = _umtx_op_err(mtx, UMTX_OP_MUTEX_WAIT, 0, + (void *)tm_size, __DECONST(void *, tm_p)); /* now try to lock it */ owner = mtx->m_owner; @@ -133,18 +140,13 @@ __thr_umutex_timedlock(struct umutex *mtx, uint32_t id, atomic_cmpset_acq_32(&mtx->m_owner, owner, id|owner)) return (0); } else { - ret = _umtx_op_err(mtx, UMTX_OP_MUTEX_LOCK, 0, 0, &timo); + ret = _umtx_op_err(mtx, UMTX_OP_MUTEX_LOCK, 0, + (void *)tm_size, __DECONST(void *, tm_p)); if (ret == 0) break; } if (ret == ETIMEDOUT) break; - clock_gettime(CLOCK_REALTIME, &cts); - TIMESPEC_SUB(&timo, ets, &cts); - if (timo.tv_sec < 0 || (timo.tv_sec == 0 && timo.tv_nsec == 0)) { - ret = ETIMEDOUT; - break; - } } return (ret); } @@ -200,10 +202,23 @@ int _thr_umtx_timedwait_uint(volatile u_int *mtx, u_int id, int clockid, const struct timespec *abstime, int shared) { + struct _umtx_time *tm_p, timeout; + size_t tm_size; + + if (abstime == NULL) { + tm_p = NULL; + tm_size = 0; + } else { + timeout._clockid = CLOCK_REALTIME; + timeout._flags = UMTX_ABSTIME; + timeout._timeout = *abstime; + tm_p = &timeout; + tm_size = sizeof(timeout); + } + return _umtx_op_err(__DEVOLATILE(void *, mtx), shared ? UMTX_OP_WAIT_UINT : UMTX_OP_WAIT_UINT_PRIVATE, id, - abstime != NULL ? (void *)(uintptr_t)((clockid << 16) | UMTX_WAIT_ABSTIME) : 0, - __DECONST(void *, abstime)); + (void *)tm_size, __DECONST(void *, tm_p)); } int |