svn commit: r214818 - user/davidxu/libthr/lib/libthr/thread
David Xu
davidxu at FreeBSD.org
Fri Nov 5 01:50:19 UTC 2010
Author: davidxu
Date: Fri Nov 5 01:50:18 2010
New Revision: 214818
URL: http://svn.freebsd.org/changeset/base/214818
Log:
To reduce the size of condition variable, use a simple integer as lock,
Also none timesharing thread use kernel based cv, because the simple lock
can not protect priority inversion, and no intention to make it
PI or PP mutex which is too heavy for normal use.
Modified:
user/davidxu/libthr/lib/libthr/thread/thr_cond.c
user/davidxu/libthr/lib/libthr/thread/thr_private.h
user/davidxu/libthr/lib/libthr/thread/thr_umtx.c
user/davidxu/libthr/lib/libthr/thread/thr_umtx.h
Modified: user/davidxu/libthr/lib/libthr/thread/thr_cond.c
==============================================================================
--- user/davidxu/libthr/lib/libthr/thread/thr_cond.c Fri Nov 5 00:56:21 2010 (r214817)
+++ user/davidxu/libthr/lib/libthr/thread/thr_cond.c Fri Nov 5 01:50:18 2010 (r214818)
@@ -80,7 +80,6 @@ cond_init(pthread_cond_t *cond, const pt
pcond->c_kerncv.c_flags |= USYNC_PROCESS_SHARED;
pcond->c_kerncv.c_clockid = (*cond_attr)->c_clockid;
}
- _thr_umutex_init(&pcond->c_lock);
pcond->c_kerncv.c_flags |= UCOND_BIND_MUTEX;
*cond = pcond;
}
@@ -215,19 +214,19 @@ cond_wait_user(pthread_cond_t *cond, pth
uint64_t seq, bseq;
cv = *cond;
- THR_UMUTEX_LOCK(curthread, &cv->c_lock);
+ THR_UMTX_ACQUIRE(curthread, &cv->c_lock);
cv->c_waiters++;
ret = _mutex_cv_unlock(mutex, &recurse);
if (__predict_false(ret != 0)) {
cv->c_waiters--;
- THR_UMUTEX_UNLOCK(curthread, &cv->c_lock);
+ THR_UMTX_RELEASE(curthread, &cv->c_lock);
return (ret);
}
bseq = cv->c_broadcast_seq;
for(;;) {
seq = cv->c_seq;
- THR_UMUTEX_UNLOCK(curthread, &cv->c_lock);
+ THR_UMTX_RELEASE(curthread, &cv->c_lock);
if (abstime != NULL) {
clock_gettime(cv->c_kerncv.c_clockid, &ts);
@@ -246,7 +245,7 @@ cond_wait_user(pthread_cond_t *cond, pth
(u_int)seq, tsp, 0);
}
- THR_UMUTEX_LOCK(curthread, &cv->c_lock);
+ THR_UMTX_ACQUIRE(curthread, &cv->c_lock);
if (cv->c_broadcast_seq != bseq) {
ret = 0;
break;
@@ -259,11 +258,11 @@ cond_wait_user(pthread_cond_t *cond, pth
break;
} else if (cancel && SHOULD_CANCEL(curthread) &&
!THR_IN_CRITICAL(curthread)) {
- THR_UMUTEX_UNLOCK(curthread, &cv->c_lock);
+ THR_UMTX_RELEASE(curthread, &cv->c_lock);
_pthread_exit(PTHREAD_CANCELED);
}
}
- THR_UMUTEX_UNLOCK(curthread, &cv->c_lock);
+ THR_UMTX_RELEASE(curthread, &cv->c_lock);
_mutex_cv_lock(mutex, recurse);
return (ret);
}
@@ -293,7 +292,8 @@ cond_wait_common(pthread_cond_t *cond, p
(cv->c_kerncv.c_flags & USYNC_PROCESS_SHARED))
return (EINVAL);
- if (m->m_lock.m_flags & (UMUTEX_PRIO_PROTECT|UMUTEX_PRIO_INHERIT))
+ if (curthread->attr.sched_policy != SCHED_OTHER ||
+ (m->m_lock.m_flags & (UMUTEX_PRIO_PROTECT|UMUTEX_PRIO_INHERIT)) != 0)
return cond_wait_kernel(cond, mutex, abstime, cancel);
else
return cond_wait_user(cond, mutex, abstime, cancel);
@@ -340,7 +340,7 @@ __pthread_cond_timedwait(pthread_cond_t
static int
cond_signal_common(pthread_cond_t *cond, int broadcast)
{
- struct pthread *curthread = _get_curthread();
+ struct pthread *curthread = _get_curthread();
pthread_cond_t cv;
/*
@@ -357,7 +357,7 @@ cond_signal_common(pthread_cond_t *cond,
if (cv->c_waiters == 0)
return (0);
- THR_UMUTEX_LOCK(curthread, &cv->c_lock);
+ THR_UMTX_ACQUIRE(curthread, &cv->c_lock);
if (cv->c_waiters > 0) {
if (!broadcast) {
cv->c_seq++;
@@ -372,7 +372,7 @@ cond_signal_common(pthread_cond_t *cond,
_thr_umtx_wake(&cv->c_seq, INT_MAX, 0);
}
}
- THR_UMUTEX_UNLOCK(curthread, &cv->c_lock);
+ THR_UMTX_RELEASE(curthread, &cv->c_lock);
return (0);
}
Modified: user/davidxu/libthr/lib/libthr/thread/thr_private.h
==============================================================================
--- user/davidxu/libthr/lib/libthr/thread/thr_private.h Fri Nov 5 00:56:21 2010 (r214817)
+++ user/davidxu/libthr/lib/libthr/thread/thr_private.h Fri Nov 5 01:50:18 2010 (r214818)
@@ -173,7 +173,7 @@ struct pthread_cond {
* Following is userlevel condition variable which is
* used for time-sharing scheduling, it is a bit fast.
*/
- struct umutex c_lock;
+ uint32_t c_lock;
int c_waiters;
int c_signaled;
uint32_t c_seq;
@@ -553,6 +553,22 @@ do { \
#define THR_THREAD_LOCK(curthrd, thr) THR_LOCK_ACQUIRE(curthrd, &(thr)->lock)
#define THR_THREAD_UNLOCK(curthrd, thr) THR_LOCK_RELEASE(curthrd, &(thr)->lock)
+
+#define THR_UMTX_ACQUIRE(thrd, lck) \
+do { \
+ (thrd)->locklevel++; \
+ _thr_umtx_lock_spin(lck); \
+} while (0)
+
+#define THR_UMTX_RELEASE(thrd, lck) \
+do { \
+ THR_ASSERT_LOCKLEVEL(thrd); \
+ _thr_umtx_unlock((lck)); \
+ (thrd)->locklevel--; \
+ _thr_ast(thrd); \
+} while (0)
+
+
#define THREAD_LIST_RDLOCK(curthrd) \
do { \
(curthrd)->locklevel++; \
Modified: user/davidxu/libthr/lib/libthr/thread/thr_umtx.c
==============================================================================
--- user/davidxu/libthr/lib/libthr/thread/thr_umtx.c Fri Nov 5 00:56:21 2010 (r214817)
+++ user/davidxu/libthr/lib/libthr/thread/thr_umtx.c Fri Nov 5 01:50:18 2010 (r214818)
@@ -251,3 +251,58 @@ _thr_rwl_unlock(struct urwlock *rwlock)
if (_thr_rwlock_unlock(rwlock))
PANIC("unlock error");
}
+
+int
+__thr_umtx_lock(volatile umtx_t *mtx)
+{
+ int v;
+
+ do {
+ v = *mtx;
+ if (v == 2 || atomic_cmpset_acq_int(mtx, 1, 2))
+ _thr_umtx_wait_uint(mtx, 2, NULL, 0);
+ } while (!atomic_cmpset_acq_int(mtx, 0, 2));
+ return (0);
+}
+
+#define LOOPS 500
+
+int
+__thr_umtx_lock_spin(volatile umtx_t *mtx)
+{
+ int v;
+ int i;
+
+ if (!_thr_is_smp)
+ return _thr_umtx_lock(mtx);
+
+ do {
+ i = LOOPS;
+ while (i-- > 0) {
+ if (*mtx == 0)
+ break;
+ CPU_SPINWAIT;
+ }
+ v = *mtx;
+ if (v == 2 || atomic_cmpset_acq_int(mtx, 1, 2))
+ _thr_umtx_wait_uint(mtx, 2, NULL, 0);
+ } while (!atomic_cmpset_acq_int(mtx, 0, 2));
+ return (0);
+}
+
+void
+__thr_umtx_unlock(volatile umtx_t *mtx)
+{
+ int v;
+
+ for (;;) {
+ v = *mtx;
+ if (atomic_cmpset_acq_int(mtx, v, v-1)) {
+ if (v != 1) {
+ *mtx = 0;
+ _thr_umtx_wake(mtx, 1, 0);
+ }
+ break;
+ }
+ }
+}
Modified: user/davidxu/libthr/lib/libthr/thread/thr_umtx.h
==============================================================================
--- user/davidxu/libthr/lib/libthr/thread/thr_umtx.h Fri Nov 5 00:56:21 2010 (r214817)
+++ user/davidxu/libthr/lib/libthr/thread/thr_umtx.h Fri Nov 5 01:50:18 2010 (r214818)
@@ -35,6 +35,8 @@
#define DEFAULT_UMUTEX {0,0,{0,0},{0,0,0,0}}
#define DEFAULT_URWLOCK {0,0,0,0,{0,0,0,0}}
+typedef uint32_t umtx_t;
+
int __thr_umutex_lock(struct umutex *mtx, uint32_t id) __hidden;
int __thr_umutex_timedlock(struct umutex *mtx, uint32_t id,
const struct timespec *timeout) __hidden;
@@ -66,6 +68,10 @@ void _thr_rwl_rdlock(struct urwlock *rwl
void _thr_rwl_wrlock(struct urwlock *rwlock) __hidden;
void _thr_rwl_unlock(struct urwlock *rwlock) __hidden;
+int __thr_umtx_lock(volatile umtx_t *mtx);
+int __thr_umtx_lock_spin(volatile umtx_t *mtx);
+void __thr_umtx_unlock(volatile umtx_t *mtx);
+
static inline int
_thr_umutex_trylock(struct umutex *mtx, uint32_t id)
{
@@ -193,4 +199,28 @@ _thr_rwlock_unlock(struct urwlock *rwloc
}
return (__thr_rwlock_unlock(rwlock));
}
+
+static inline int
+_thr_umtx_lock(volatile umtx_t *mtx)
+{
+ if (atomic_cmpset_acq_int(mtx, 0, 1))
+ return (0);
+ return (__thr_umtx_lock(mtx));
+}
+
+static inline int
+_thr_umtx_lock_spin(volatile umtx_t *mtx)
+{
+ if (atomic_cmpset_acq_int(mtx, 0, 1))
+ return (0);
+ return (__thr_umtx_lock_spin(mtx));
+}
+
+static inline void
+_thr_umtx_unlock(volatile umtx_t *mtx)
+{
+ if (atomic_cmpset_acq_int(mtx, 1, 0))
+ return;
+ __thr_umtx_unlock(mtx);
+}
#endif
More information about the svn-src-user
mailing list