summaryrefslogtreecommitdiff
path: root/sysdeps/l4
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@gnu.org>2008-05-27 18:29:48 +0000
committerThomas Schwinge <tschwinge@gnu.org>2009-04-07 23:15:57 +0200
commitb79685960d731cffd6661449bb95cea79b5fc706 (patch)
tree62b2bd9025f277255ba4484554517b4aa35bd994 /sysdeps/l4
parente6bf1e24afbac43b084f1cd1f24de6ba587d2d90 (diff)
2008-05-27 Neal H. Walfield <neal@gnu.org>
* pthread/pt-internal.h (__pthread_queue_iterate): Before returning the current element, save its next pointer. (__pthread_dequeuing_iterate): Likewise. * sysdeps/l4/hurd/pt-wakeup.c (__pthread_wakeup): Loop until we successfully wake THREAD.
Diffstat (limited to 'sysdeps/l4')
-rw-r--r--sysdeps/l4/hurd/pt-wakeup.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/sysdeps/l4/hurd/pt-wakeup.c b/sysdeps/l4/hurd/pt-wakeup.c
index 2225cca..e568a6f 100644
--- a/sysdeps/l4/hurd/pt-wakeup.c
+++ b/sysdeps/l4/hurd/pt-wakeup.c
@@ -27,6 +27,20 @@
void
__pthread_wakeup (struct __pthread *thread)
{
- long ret = futex_wake (&thread->threadid, INT_MAX);
- assert (ret == 1);
+ /* We need to loop here as the blocked thread may not yet be
+ blocked! Here's what happens when a thread blocks: it registers
+ itself as blocked, drops the relevant lock and then actually
+ blocks (via __pthread_block). This means that after dropping the
+ lock and before blocking, it may be interrupted and another
+ thread may try to wake it. */
+ long ret;
+ do
+ {
+ ret = futex_wake (&thread->threadid, INT_MAX);
+ assertx (ret <= 1, "tid: %x, ret: %d", thread->threadid, ret);
+
+ if (ret == 0)
+ l4_thread_switch (thread->threadid);
+ }
+ while (ret == 0);
}