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