summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread/thr_umtx.c
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2010-12-22 05:01:52 +0000
committerdavidxu <davidxu@FreeBSD.org>2010-12-22 05:01:52 +0000
commit437ad27f9c81f522301de0affe1fc5fef37d8828 (patch)
treed717e6b5f295c555e1deef8497d4130bec1843cf /lib/libthr/thread/thr_umtx.c
parent24b08bca030970592bc5241517b0462f603b05b1 (diff)
downloadFreeBSD-src-437ad27f9c81f522301de0affe1fc5fef37d8828.zip
FreeBSD-src-437ad27f9c81f522301de0affe1fc5fef37d8828.tar.gz
MFp4:
- Add flags CVWAIT_ABSTIME and CVWAIT_CLOCKID for umtx kernel based condition variable, this should eliminate an extra system call to get current time. - Add sub-function UMTX_OP_NWAKE_PRIVATE to wake up N channels in single system call. Create userland sleep queue for condition variable, in most cases, thread will wait in the queue, the pthread_cond_signal will defer thread wakeup until the mutex is unlocked, it tries to avoid an extra system call and a extra context switch in time window of pthread_cond_signal and pthread_mutex_unlock. The changes are part of process-shared mutex project.
Diffstat (limited to 'lib/libthr/thread/thr_umtx.c')
-rw-r--r--lib/libthr/thread/thr_umtx.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/lib/libthr/thread/thr_umtx.c b/lib/libthr/thread/thr_umtx.c
index dabfa35..33c3637 100644
--- a/lib/libthr/thread/thr_umtx.c
+++ b/lib/libthr/thread/thr_umtx.c
@@ -74,6 +74,39 @@ __thr_umutex_lock(struct umutex *mtx, uint32_t id)
return _umtx_op_err(mtx, UMTX_OP_MUTEX_LOCK, 0, 0, 0);
}
+#define SPINLOOPS 1000
+
+int
+__thr_umutex_lock_spin(struct umutex *mtx, uint32_t id)
+{
+ uint32_t owner;
+
+ if (!_thr_is_smp)
+ return __thr_umutex_lock(mtx, id);
+
+ if ((mtx->m_flags & (UMUTEX_PRIO_PROTECT | UMUTEX_PRIO_INHERIT)) == 0) {
+ for (;;) {
+ int count = SPINLOOPS;
+ while (count--) {
+ owner = mtx->m_owner;
+ if ((owner & ~UMUTEX_CONTESTED) == 0) {
+ if (atomic_cmpset_acq_32(
+ &mtx->m_owner,
+ owner, id|owner)) {
+ return (0);
+ }
+ }
+ CPU_SPINWAIT;
+ }
+
+ /* wait in kernel */
+ _umtx_op_err(mtx, UMTX_OP_MUTEX_WAIT, 0, 0, 0);
+ }
+ }
+
+ return _umtx_op_err(mtx, UMTX_OP_MUTEX_LOCK, 0, 0, 0);
+}
+
int
__thr_umutex_timedlock(struct umutex *mtx, uint32_t id,
const struct timespec *ets)
@@ -164,6 +197,26 @@ _thr_umtx_wait_uint(volatile u_int *mtx, u_int id, const struct timespec *timeou
}
int
+_thr_umtx_timedwait_uint(volatile u_int *mtx, u_int id, int clockid,
+ const struct timespec *abstime, int shared)
+{
+ struct timespec ts, ts2, *tsp;
+
+ if (abstime != NULL) {
+ clock_gettime(clockid, &ts);
+ TIMESPEC_SUB(&ts2, abstime, &ts);
+ if (ts2.tv_sec < 0 || ts2.tv_nsec <= 0)
+ return (ETIMEDOUT);
+ tsp = &ts2;
+ } else {
+ tsp = NULL;
+ }
+ return _umtx_op_err(__DEVOLATILE(void *, mtx),
+ shared ? UMTX_OP_WAIT_UINT : UMTX_OP_WAIT_UINT_PRIVATE, id, NULL,
+ tsp);
+}
+
+int
_thr_umtx_wake(volatile void *mtx, int nr_wakeup, int shared)
{
return _umtx_op_err(__DEVOLATILE(void *, mtx), shared ? UMTX_OP_WAKE : UMTX_OP_WAKE_PRIVATE,
OpenPOWER on IntegriCloud