diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2014-11-02 04:20:13 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2014-11-02 04:20:13 +0100 |
commit | 46d3992fea0690f81ed3924a0a13f3aecde809ae (patch) | |
tree | a6a73015465035a3636cb439720cd2cd07319de1 /sysdeps/generic | |
parent | 3360034b7814d90503098700fc18bf07c47838c3 (diff) |
Wake up queued threads without spin lock held
so that they may have a chance to actually preempt us. Otherwise
they will merely immediately fail to acquire the spin lock, and thus
preemption will have served no purpose.
* sysdeps/generic/pt-rwlock-unlock.c (pthread_rwlock_unlock): Record
an array of __pthread to wake while holding the lock, and wake them
only after unlocking it.
Diffstat (limited to 'sysdeps/generic')
-rw-r--r-- | sysdeps/generic/pt-rwlock-unlock.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/sysdeps/generic/pt-rwlock-unlock.c b/sysdeps/generic/pt-rwlock-unlock.c index 212cca5..dcf1d3e 100644 --- a/sysdeps/generic/pt-rwlock-unlock.c +++ b/sysdeps/generic/pt-rwlock-unlock.c @@ -65,15 +65,26 @@ pthread_rwlock_unlock (pthread_rwlock_t *rwlock) if (rwlock->readerqueue) { - __pthread_dequeuing_iterate (rwlock->readerqueue, wakeup) - { - rwlock->readers ++; - __pthread_wakeup (wakeup); - } + unsigned n = 0; - rwlock->readerqueue = 0; + __pthread_queue_iterate (rwlock->readerqueue, wakeup) + n ++; - __pthread_spin_unlock (&rwlock->__lock); + { + struct __pthread *wakeups[n]; + unsigned i = 0; + + __pthread_dequeuing_iterate (rwlock->readerqueue, wakeup) + wakeups[i ++] = wakeup; + + rwlock->readers += n; + rwlock->readerqueue = 0; + + __pthread_spin_unlock (&rwlock->__lock); + + for (i = 0; i < n; i ++) + __pthread_wakeup (wakeups[i]); + } return 0; } |