summaryrefslogtreecommitdiff
path: root/src/thread/pthread_cond_timedwait.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2011-09-22 21:08:55 -0400
committerRich Felker <dalias@aerifal.cx>2011-09-22 21:08:55 -0400
commit4b153ac42428447a148e6da543ebe6df017078db (patch)
treed9a5b8035f98b8cec47fc6044e38305ea5cdb91a /src/thread/pthread_cond_timedwait.c
parent2eff02e4a032323a45541c79967638d8c77d79e4 (diff)
downloadmusl-4b153ac42428447a148e6da543ebe6df017078db.tar.gz
fix deadlock in condition wait whenever there are multiple waiters
it's amazing none of the conformance tests i've run even bothered to check whether something so basic works...
Diffstat (limited to 'src/thread/pthread_cond_timedwait.c')
-rw-r--r--src/thread/pthread_cond_timedwait.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c
index ee874a36..ec5aa6f4 100644
--- a/src/thread/pthread_cond_timedwait.c
+++ b/src/thread/pthread_cond_timedwait.c
@@ -1,12 +1,20 @@
#include "pthread_impl.h"
-static void relock(void *m)
+struct cm {
+ pthread_cond_t *c;
+ pthread_mutex_t *m;
+};
+
+static void cleanup(void *p)
{
- pthread_mutex_lock(m);
+ struct cm *cm = p;
+ a_dec(&cm->c->_c_waiters);
+ pthread_mutex_lock(cm->m);
}
int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, const struct timespec *ts)
{
+ struct cm cm = { .c=c, .m=m };
int r, e=0;
if (ts && ts->tv_nsec >= 1000000000UL)
@@ -17,8 +25,10 @@ int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, const struct t
c->_c_block = 1;
if ((r=pthread_mutex_unlock(m))) return r;
- do e = __timedwait(&c->_c_block, 1, c->_c_clock, ts, relock, m, 0);
+ a_inc(&c->_c_waiters);
+ do e = __timedwait(&c->_c_block, 1, c->_c_clock, ts, cleanup, &cm, 0);
while (e == EINTR);
+ a_dec(&c->_c_waiters);
if ((r=pthread_mutex_lock(m))) return r;