From owner-svn-src-user@FreeBSD.ORG Fri Nov 5 01:50:19 2010 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2672D1065672; Fri, 5 Nov 2010 01:50:19 +0000 (UTC) (envelope-from davidxu@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 13FC48FC18; Fri, 5 Nov 2010 01:50:19 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id oA51oITN079975; Fri, 5 Nov 2010 01:50:18 GMT (envelope-from davidxu@svn.freebsd.org) Received: (from davidxu@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oA51oILc079970; Fri, 5 Nov 2010 01:50:18 GMT (envelope-from davidxu@svn.freebsd.org) Message-Id: <201011050150.oA51oILc079970@svn.freebsd.org> From: David Xu Date: Fri, 5 Nov 2010 01:50:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r214818 - user/davidxu/libthr/lib/libthr/thread X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 05 Nov 2010 01:50:19 -0000 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