diff options
author | Neal H. Walfield <neal@gnu.org> | 2008-05-27 18:29:48 +0000 |
---|---|---|
committer | Thomas Schwinge <tschwinge@gnu.org> | 2009-04-07 23:15:57 +0200 |
commit | b79685960d731cffd6661449bb95cea79b5fc706 (patch) | |
tree | 62b2bd9025f277255ba4484554517b4aa35bd994 | |
parent | e6bf1e24afbac43b084f1cd1f24de6ba587d2d90 (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.
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | pthread/pt-internal.h | 19 | ||||
-rw-r--r-- | sysdeps/l4/hurd/pt-wakeup.c | 18 |
3 files changed, 38 insertions, 8 deletions
@@ -1,3 +1,12 @@ +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. + 2008-05-21 Neal H. Walfield <neal@gnu.org> * sysdeps/l4/hurd/bits/pthread-np.h: New file. diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h index 41fbc83..853d739 100644 --- a/pthread/pt-internal.h +++ b/pthread/pt-internal.h @@ -122,15 +122,22 @@ __pthread_dequeue (struct __pthread *thread) } /* Iterate over QUEUE storing each element in ELEMENT. */ -#define __pthread_queue_iterate(queue, element) \ - for (element = queue; element; element = element->next) +#define __pthread_queue_iterate(queue, element) \ + for (struct __pthread *__pdi_next = (queue); \ + ((element) = __pdi_next) \ + && ((__pdi_next = __pdi_next->next), \ + true); \ + ) /* Iterate over QUEUE dequeuing each element, storing it in ELEMENT. */ -#define __pthread_dequeuing_iterate(queue, element) \ - for (element = queue; \ - element && ((element->prevp = 0), 1); \ - element = element->next) +#define __pthread_dequeuing_iterate(queue, element) \ + for (struct __pthread *__pdi_next = (queue); \ + ((element) = __pdi_next) \ + && ((__pdi_next = __pdi_next->next), \ + ((element)->prevp = 0), \ + true); \ + ) /* The total number of threads currently active. */ extern atomic_fast32_t __pthread_total; 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); } |