| 117 | } |
| 118 | |
| 119 | int bthread_cond_timedwait(bthread_cond_t* __restrict c, |
| 120 | bthread_mutex_t* __restrict m, |
| 121 | const struct timespec* __restrict abstime) { |
| 122 | bthread::CondInternal* ic = reinterpret_cast<bthread::CondInternal*>(c); |
| 123 | const int expected_seq = ic->seq->load(butil::memory_order_relaxed); |
| 124 | if (ic->m.load(butil::memory_order_relaxed) != m) { |
| 125 | // bind m to c |
| 126 | bthread_mutex_t* expected_m = NULL; |
| 127 | if (!ic->m.compare_exchange_strong( |
| 128 | expected_m, m, butil::memory_order_relaxed)) { |
| 129 | return EINVAL; |
| 130 | } |
| 131 | } |
| 132 | bthread_mutex_unlock(m); |
| 133 | int rc1 = 0; |
| 134 | if (bthread::butex_wait(ic->seq, expected_seq, abstime) < 0 && |
| 135 | errno != EWOULDBLOCK && errno != EINTR/*note*/) { |
| 136 | // note: see comments in bthread_cond_wait on EINTR. |
| 137 | rc1 = errno; |
| 138 | } |
| 139 | const int rc2 = bthread_mutex_lock_contended(m); |
| 140 | return (rc2 ? rc2 : rc1); |
| 141 | } |
| 142 | |
| 143 | } // extern "C" |