1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| | #include "pthread_impl.h"
#include <threads.h>
int cnd_signal(cnd_t * cond) {
int ret = thrd_success;
/* Avoid fight for critical section if there is nothing to
do. */
if (!cond || !cond->_cx_cnd) return ret;
/* Critical section protected by lock */
__lock(&cond->_cx_lock);
__cnd_t * c = cond->_cx_cnd;
if (c) {
if (c->wts) {
++c->seq;
/* Move one waiter to the ones to be woken up, later. */
--c->wts;
/* If this was the last waiter, unlink. */
if (!c->wts) cond->_cx_cnd = 0;
else __cnd_addref(c);
} else {
c = 0;
}
}
__unlock(&cond->_cx_lock);
/* If c is 0, there haven't been any waiters, yet, nothing to do. */
if (c) {
/* Do the delayed work. */
a_inc(&c->tok);
/* Move the threads of the previous sequence point to the token queue. */
int ret0 = __syscall(SYS_futex, &c->seq, FUTEX_REQUEUE|THRD_PRIVATE,
0,
INT_MAX, &c->tok);
int ret1 = __syscall(SYS_futex, &c->tok, FUTEX_WAKE|THRD_PRIVATE, 1);
ret = ((ret0 < 0) || (ret1 < 0)) ? thrd_error : thrd_success;
__cnd_unref(c);
}
return ret;
}
|