From f5fb20b0e934770c37093105524ea644dcaba5e2 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 25 Aug 2014 20:24:07 -0400 Subject: [PATCH] refrain from spinning on locks when there is already a waiter if there is already a waiter for a lock, spinning on the lock is essentially an attempt to steal it from whichever waiter would obtain it via any priority rules in place, and is therefore undesirable. in the current implementation, there is always an inherent race window at unlock during which a newly-arriving thread may steal the lock from the existing waiters, but we should aim to keep this window minimal rather than enlarging it. --- src/thread/__wait.c | 2 +- src/thread/pthread_mutex_timedlock.c | 2 +- src/thread/pthread_rwlock_timedrdlock.c | 2 +- src/thread/pthread_rwlock_timedwrlock.c | 2 +- src/thread/sem_timedwait.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/thread/__wait.c b/src/thread/__wait.c index c1d6b61c..01ee5982 100644 --- a/src/thread/__wait.c +++ b/src/thread/__wait.c @@ -4,7 +4,7 @@ void __wait(volatile int *addr, volatile int *waiters, int val, int priv) { int spins=100; if (priv) priv = 128; - while (spins--) { + while (spins-- && (!waiters || !*waiters)) { if (*addr==val) a_spin(); else return; } diff --git a/src/thread/pthread_mutex_timedlock.c b/src/thread/pthread_mutex_timedlock.c index 116a8b7b..ae883f90 100644 --- a/src/thread/pthread_mutex_timedlock.c +++ b/src/thread/pthread_mutex_timedlock.c @@ -12,7 +12,7 @@ int pthread_mutex_timedlock(pthread_mutex_t *restrict m, const struct timespec * if (r != EBUSY) return r; int spins = 100; - while (spins-- && m->_m_lock) a_spin(); + while (spins-- && m->_m_lock && !m->_m_waiters) a_spin(); while ((r=pthread_mutex_trylock(m)) == EBUSY) { if (!(r=m->_m_lock) || ((r&0x40000000) && (m->_m_type&4))) diff --git a/src/thread/pthread_rwlock_timedrdlock.c b/src/thread/pthread_rwlock_timedrdlock.c index 884b7a1e..ea50da4a 100644 --- a/src/thread/pthread_rwlock_timedrdlock.c +++ b/src/thread/pthread_rwlock_timedrdlock.c @@ -8,7 +8,7 @@ int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rw, const struct times if (r != EBUSY) return r; int spins = 100; - while (spins-- && rw->_rw_lock) a_spin(); + while (spins-- && rw->_rw_lock && !rw->_rw_waiters) a_spin(); while ((r=pthread_rwlock_tryrdlock(rw))==EBUSY) { if (!(r=rw->_rw_lock) || (r&0x7fffffff)!=0x7fffffff) continue; diff --git a/src/thread/pthread_rwlock_timedwrlock.c b/src/thread/pthread_rwlock_timedwrlock.c index f02b174b..8d04f561 100644 --- a/src/thread/pthread_rwlock_timedwrlock.c +++ b/src/thread/pthread_rwlock_timedwrlock.c @@ -8,7 +8,7 @@ int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rw, const struct times if (r != EBUSY) return r; int spins = 100; - while (spins-- && rw->_rw_lock) a_spin(); + while (spins-- && rw->_rw_lock && !rw->_rw_waiters) a_spin(); while ((r=pthread_rwlock_trywrlock(rw))==EBUSY) { if (!(r=rw->_rw_lock)) continue; diff --git a/src/thread/sem_timedwait.c b/src/thread/sem_timedwait.c index df5f3a6c..b5a60add 100644 --- a/src/thread/sem_timedwait.c +++ b/src/thread/sem_timedwait.c @@ -11,7 +11,7 @@ int sem_timedwait(sem_t *restrict sem, const struct timespec *restrict at) if (!sem_trywait(sem)) return 0; int spins = 100; - while (spins-- && sem->__val[0] <= 0) a_spin(); + while (spins-- && sem->__val[0] <= 0 && !sem->__val[1]) a_spin(); while (sem_trywait(sem)) { int r; -- 2.25.1