From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/5924 Path: news.gmane.org!not-for-mail From: Jens Gustedt Newsgroups: gmane.linux.lib.musl.general Subject: [PATCH 1/2] Let the signaler do all work concerning consistency of the list Date: Wed, 27 Aug 2014 11:56:22 +0200 Message-ID: <1409133300.4476.29.camel@eris.loria.fr> Reply-To: musl@lists.openwall.com NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Transfer-Encoding: 7bit X-Trace: ger.gmane.org 1409133394 10404 80.91.229.3 (27 Aug 2014 09:56:34 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 27 Aug 2014 09:56:34 +0000 (UTC) To: musl@lists.openwall.com Original-X-From: musl-return-5931-gllmg-musl=m.gmane.org@lists.openwall.com Wed Aug 27 11:56:28 2014 Return-path: Envelope-to: gllmg-musl@plane.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by plane.gmane.org with smtp (Exim 4.69) (envelope-from ) id 1XMZxp-0006Fq-6B for gllmg-musl@plane.gmane.org; Wed, 27 Aug 2014 11:56:25 +0200 Original-Received: (qmail 30520 invoked by uid 550); 27 Aug 2014 09:56:24 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Original-Received: (qmail 30512 invoked from network); 27 Aug 2014 09:56:24 -0000 X-IronPort-AV: E=Sophos;i="5.04,409,1406584800"; d="scan'208";a="91655278" Resent-From: Jens Gustedt Resent-To: musl@lists.openwall.com X-Mailer: Evolution 3.4.4-3 Xref: news.gmane.org gmane.linux.lib.musl.general:5924 Archived-At: --- 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