| 610 | } |
| 611 | |
| 612 | static int butex_wait_from_pthread(TaskGroup* g, Butex* b, int expected_value, |
| 613 | const timespec* abstime, bool prepend) { |
| 614 | TaskMeta* task = NULL; |
| 615 | ButexPthreadWaiter pw; |
| 616 | pw.tid = 0; |
| 617 | pw.sig.store(PTHREAD_NOT_SIGNALLED, butil::memory_order_relaxed); |
| 618 | int rc = 0; |
| 619 | |
| 620 | if (g) { |
| 621 | task = g->current_task(); |
| 622 | task->current_waiter.store(&pw, butil::memory_order_release); |
| 623 | } |
| 624 | b->waiter_lock.lock(); |
| 625 | if (b->value.load(butil::memory_order_relaxed) != expected_value) { |
| 626 | b->waiter_lock.unlock(); |
| 627 | errno = EWOULDBLOCK; |
| 628 | rc = -1; |
| 629 | } else if (task != NULL && task->interrupted) { |
| 630 | b->waiter_lock.unlock(); |
| 631 | // Race with set and may consume multiple interruptions, which are OK. |
| 632 | task->interrupted = false; |
| 633 | errno = EINTR; |
| 634 | rc = -1; |
| 635 | } else { |
| 636 | if (prepend) { |
| 637 | b->waiters.Prepend(&pw); |
| 638 | } else { |
| 639 | b->waiters.Append(&pw); |
| 640 | } |
| 641 | pw.container.store(b, butil::memory_order_relaxed); |
| 642 | b->waiter_lock.unlock(); |
| 643 | |
| 644 | #ifdef SHOW_BTHREAD_BUTEX_WAITER_COUNT_IN_VARS |
| 645 | bvar::Adder<int64_t>& num_waiters = butex_waiter_count(); |
| 646 | num_waiters << 1; |
| 647 | #endif |
| 648 | rc = wait_pthread(pw, abstime); |
| 649 | #ifdef SHOW_BTHREAD_BUTEX_WAITER_COUNT_IN_VARS |
| 650 | num_waiters << -1; |
| 651 | #endif |
| 652 | } |
| 653 | if (task) { |
| 654 | // If current_waiter is NULL, TaskGroup::interrupt() is running and |
| 655 | // using pw, spin until current_waiter != NULL. |
| 656 | BT_LOOP_WHEN(task->current_waiter.exchange( |
| 657 | NULL, butil::memory_order_acquire) == NULL, |
| 658 | 30/*nops before sched_yield*/); |
| 659 | if (task->interrupted) { |
| 660 | task->interrupted = false; |
| 661 | if (rc == 0) { |
| 662 | errno = EINTR; |
| 663 | return -1; |
| 664 | } |
| 665 | } |
| 666 | } |
| 667 | return rc; |
| 668 | } |
| 669 |
no test coverage detected