fix ABA race in cond vars, improve them overall
[musl] / src / thread / pthread_cond_timedwait.c
1 #include "pthread_impl.h"
2
3 struct cm {
4         pthread_cond_t *c;
5         pthread_mutex_t *m;
6 };
7
8 static void cleanup(void *p)
9 {
10         struct cm *cm = p;
11         a_dec(&cm->c->_c_waiters);
12         pthread_mutex_lock(cm->m);
13 }
14
15 int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, const struct timespec *ts)
16 {
17         struct cm cm = { .c=c, .m=m };
18         int r, e, tid;
19
20         if (ts && ts->tv_nsec >= 1000000000UL)
21                 return EINVAL;
22
23         pthread_testcancel();
24
25         a_inc(&c->_c_waiters);
26         c->_c_block = tid = pthread_self()->tid;
27
28         if ((r=pthread_mutex_unlock(m))) return r;
29
30         do e = __timedwait(&c->_c_block, tid, c->_c_clock, ts, cleanup, &cm, 0);
31         while (c->_c_block == tid && (!e || e==EINTR));
32         if (e == EINTR) e = 0;
33
34         a_dec(&c->_c_waiters);
35
36         if ((r=pthread_mutex_lock(m))) return r;
37
38         pthread_testcancel();
39         return e;
40 }