|
Message-ID: <1409133300.4476.29.camel@eris.loria.fr> Date: Wed, 27 Aug 2014 11:56:22 +0200 From: Jens Gustedt <Jens.Gustedt@...ia.fr> To: musl@...ts.openwall.com Subject: [PATCH 1/2] Let the signaler do all work concerning consistency of the list --- src/thread/pthread_cond_timedwait.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c index 2d192b0..52b1026 100644 --- a/src/thread/pthread_cond_timedwait.c +++ b/src/thread/pthread_cond_timedwait.c @@ -84,18 +84,26 @@ static void unwait(void *arg) * via the futex notify below. */ pthread_cond_t *c = node->cond; + int * ref; + lock(&c->_c_lock); - - if (c->_c_head == node) c->_c_head = node->next; - else if (node->prev) node->prev->next = node->next; - if (c->_c_tail == node) c->_c_tail = node->prev; - else if (node->next) node->next->prev = node->prev; - + /* Our membership to the list may have changed while waiting for the lock. */ + /* Ensure that the notify field is only read while we hold the lock. */ + ref = node->notify; + + /* If there has been no race with a signaler, splice us out of the list. */ + /* Otherwise, the signaler has already taken care of it. */ + if (!ref) { + if (c->_c_head == node) c->_c_head = node->next; + else if (node->prev) node->prev->next = node->next; + if (c->_c_tail == node) c->_c_tail = node->prev; + else if (node->next) node->next->prev = node->prev; + } unlock(&c->_c_lock); - if (node->notify) { - if (a_fetch_add(node->notify, -1)==1) - __wake(node->notify, 1, 1); + if (ref) { + if (a_fetch_add(ref, -1)==1) + __wake(ref, 1, 1); } } else { /* Lock barrier first to control wake order. */ @@ -172,6 +180,11 @@ int __private_cond_signal(pthread_cond_t *c, int n) if (a_cas(&p->state, WAITING, SIGNALED) != WAITING) { ref++; p->notify = &ref; + /* Let the signaler do all work concerning consistency of the list. */ + if (c->_c_head == p) c->_c_head = p->next; + else if (p->prev) p->prev->next = p->next; + if (c->_c_tail == p) c->_c_tail = p->prev; + else if (p->next) p->next->prev = p->prev; } else { n--; if (!first) first=p; -- 1.7.10.4
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.