#include "pthread_impl.h" #include 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; }