summaryrefslogtreecommitdiff
path: root/sysdeps/generic
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2014-11-02 04:20:13 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2014-11-02 04:20:13 +0100
commit46d3992fea0690f81ed3924a0a13f3aecde809ae (patch)
treea6a73015465035a3636cb439720cd2cd07319de1 /sysdeps/generic
parent3360034b7814d90503098700fc18bf07c47838c3 (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.c25
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;
}