Index: sys/sys/umtx.h =================================================================== --- sys/sys/umtx.h (revision 253951) +++ sys/sys/umtx.h (working copy) @@ -40,10 +40,12 @@ #define UMUTEX_UNOWNED 0x0 #define UMUTEX_CONTESTED 0x80000000U +#define UMUTEX_LOCK_BIT 1 #define UMUTEX_ERROR_CHECK 0x0002 /* Error-checking mutex */ #define UMUTEX_PRIO_INHERIT 0x0004 /* Priority inherited mutex */ #define UMUTEX_PRIO_PROTECT 0x0008 /* Priority protect mutex */ +#define UMUTEX_NO_TID 0x0010 /* Do not use thread id */ /* urwlock flags */ #define URWLOCK_PREFER_READER 0x0002 Index: sys/kern/kern_umtx.c =================================================================== --- sys/kern/kern_umtx.c (revision 253951) +++ sys/kern/kern_umtx.c (working copy) @@ -1271,7 +1271,7 @@ uint32_t owner, old, id; int error = 0; - id = td->td_tid; + id = (flags & UMUTEX_NO_TID) ? UMUTEX_LOCK_BIT : td->td_tid; uq = td->td_umtxq; if (timeout != NULL) @@ -1394,7 +1394,7 @@ int error; int count; - id = td->td_tid; + id = (flags & UMUTEX_NO_TID) ? UMUTEX_LOCK_BIT : td->td_tid; /* * Make sure we own this mtx. */ @@ -1402,7 +1402,7 @@ if (owner == -1) return (EFAULT); - if ((owner & ~UMUTEX_CONTESTED) != id) + if ((flags & UMUTEX_NO_TID) == 0 && (owner & ~UMUTEX_CONTESTED) != id) return (EPERM); if ((owner & UMUTEX_CONTESTED) == 0) { @@ -1424,23 +1424,38 @@ count = umtxq_count(&key); umtxq_unlock(&key); - /* - * When unlocking the umtx, it must be marked as unowned if - * there is zero or one thread only waiting for it. - * Otherwise, it must be marked as contested. - */ - old = casuword32(&m->m_owner, owner, - count <= 1 ? UMUTEX_UNOWNED : UMUTEX_CONTESTED); + for (;;) { + if ((flags & UMUTEX_NO_TID) == 0 && (owner & ~UMUTEX_CONTESTED) != id) { + error = EINVAL; + break; + } + /* + * When unlocking the umtx, it must be marked as unowned if + * there is zero or one thread only waiting for it. + * Otherwise, it must be marked as contested. + */ + old = casuword32(&m->m_owner, owner, + count <= 1 ? UMUTEX_UNOWNED : UMUTEX_CONTESTED); + if (old == -1) { + error = EFAULT; + break; + } + if (old == owner) + break; + error = umtxq_check_susp(td); + if (error) { + error = ERESTART; + break; + } + owner = old; + } + umtxq_lock(&key); umtxq_signal(&key,1); umtxq_unbusy(&key); umtxq_unlock(&key); umtx_key_release(&key); - if (old == -1) - return (EFAULT); - if (old != owner) - return (EINVAL); - return (0); + return (error); } /* Index: lib/libthr/thread/thr_mutex.c =================================================================== --- lib/libthr/thread/thr_mutex.c (revision 253951) +++ lib/libthr/thread/thr_mutex.c (working copy) @@ -154,7 +154,7 @@ switch(attr->m_protocol) { case PTHREAD_PRIO_NONE: pmutex->m_lock.m_owner = UMUTEX_UNOWNED; - pmutex->m_lock.m_flags = 0; + pmutex->m_lock.m_flags = UMUTEX_NO_TID; break; case PTHREAD_PRIO_INHERIT: pmutex->m_lock.m_owner = UMUTEX_UNOWNED; @@ -281,6 +281,8 @@ #define ENQUEUE_MUTEX(curthread, m) \ do { \ (m)->m_owner = curthread; \ + if ((m)->m_lock.m_flags & UMUTEX_NO_TID) \ + break; \ /* Add to the list of owned mutexes: */ \ MUTEX_ASSERT_NOT_OWNED((m)); \ if (((m)->m_lock.m_flags & UMUTEX_PRIO_PROTECT) == 0) \ @@ -290,7 +292,10 @@ } while (0) #define DEQUEUE_MUTEX(curthread, m) \ + do { \ (m)->m_owner = NULL; \ + if ((m)->m_lock.m_flags & UMUTEX_NO_TID) \ + break; \ MUTEX_ASSERT_IS_OWNED(m); \ if (__predict_true(((m)->m_lock.m_flags & UMUTEX_PRIO_PROTECT) == 0)) \ TAILQ_REMOVE(&curthread->mutexq, (m), m_qe); \ @@ -298,7 +303,8 @@ TAILQ_REMOVE(&curthread->pp_mutexq, (m), m_qe); \ set_inherited_priority(curthread, m); \ } \ - MUTEX_INIT_LINK(m); + MUTEX_INIT_LINK(m); \ + } while(0) #define CHECK_AND_INIT_MUTEX \ if (__predict_false((m = *mutex) <= THR_MUTEX_DESTROYED)) { \ @@ -319,7 +325,10 @@ uint32_t id; int ret; - id = TID(curthread); + if (m->m_lock.m_flags & UMUTEX_NO_TID) + id = UMUTEX_LOCK_BIT; + else + id = TID(curthread); if (m->m_flags & PMUTEX_FLAG_PRIVATE) THR_CRITICAL_ENTER(curthread); ret = _thr_umutex_trylock(&m->m_lock, id); @@ -354,7 +363,10 @@ if (m->m_owner == curthread) return mutex_self_lock(m, abstime); - id = TID(curthread); + if (m->m_lock.m_flags & UMUTEX_NO_TID) + id = UMUTEX_LOCK_BIT; + else + id = TID(curthread); /* * For adaptive mutexes, spin for a bit in the expectation * that if the application requests this mutex type then @@ -416,11 +428,16 @@ const struct timespec *abstime, int cvattach) { struct pthread *curthread = _get_curthread(); - int ret; + int ret, id; + if (m->m_lock.m_flags & UMUTEX_NO_TID) + id = UMUTEX_LOCK_BIT; + else + id = TID(curthread); + if (!cvattach && m->m_flags & PMUTEX_FLAG_PRIVATE) THR_CRITICAL_ENTER(curthread); - if (_thr_umutex_trylock2(&m->m_lock, TID(curthread)) == 0) { + if (_thr_umutex_trylock2(&m->m_lock, id) == 0) { ENQUEUE_MUTEX(curthread, m); ret = 0; } else { @@ -647,7 +664,10 @@ if (__predict_false(m->m_owner != curthread)) return (EPERM); - id = TID(curthread); + if (m->m_lock.m_flags & UMUTEX_NO_TID) + id = UMUTEX_LOCK_BIT; + else + id = TID(curthread); if (__predict_false( PMUTEX_TYPE(m->m_flags) == PTHREAD_MUTEX_RECURSIVE && m->m_count > 0)) {