MCPcopy Create free account
hub / github.com/apache/brpc / wait_for_butex

Function wait_for_butex

src/bthread/butex.cpp:549–610  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

547};
548
549void wait_for_butex(void* arg) {
550 auto args = static_cast<WaitForButexArgs*>(arg);
551 ButexBthreadWaiter* const bw = args->bw;
552 Butex* const b = bw->initial_butex;
553 // 1: waiter with timeout should have waiter_state == WAITER_STATE_READY
554 // before they're queued, otherwise the waiter is already timedout
555 // and removed by TimerThread, in which case we should stop queueing.
556 //
557 // Visibility of waiter_state:
558 // [bthread] [TimerThread]
559 // waiter_state = TIMED
560 // tt_lock { add task }
561 // tt_lock { get task }
562 // waiter_lock { waiter_state=TIMEDOUT }
563 // waiter_lock { use waiter_state }
564 // tt_lock represents TimerThread::_mutex. Visibility of waiter_state is
565 // sequenced by two locks, both threads are guaranteed to see the correct
566 // value.
567 {
568 BAIDU_SCOPED_LOCK(b->waiter_lock);
569 if (b->value.load(butil::memory_order_relaxed) != bw->expected_value) {
570 bw->waiter_state = WAITER_STATE_UNMATCHEDVALUE;
571 } else if (bw->waiter_state == WAITER_STATE_READY/*1*/ &&
572 !bw->task_meta->interrupted) {
573 if (args->prepend) {
574 b->waiters.Prepend(bw);
575 } else {
576 b->waiters.Append(bw);
577 }
578 bw->container.store(b, butil::memory_order_relaxed);
579#ifdef BRPC_BTHREAD_TRACER
580 bw->control->_task_tracer.set_status(TASK_STATUS_SUSPENDED, bw->task_meta);
581#endif // BRPC_BTHREAD_TRACER
582 if (bw->abstime != NULL) {
583 bw->sleep_id = get_global_timer_thread()->schedule(
584 erase_from_butex_and_wakeup, bw, *bw->abstime);
585 if (!bw->sleep_id) { // TimerThread stopped.
586 errno = ESTOP;
587 erase_from_butex_and_wakeup(bw);
588 }
589 }
590 return;
591 }
592 }
593
594 // b->container is NULL which makes erase_from_butex_and_wakeup() and
595 // TaskGroup::interrupt() no-op, there's no race between following code and
596 // the two functions. The on-stack ButexBthreadWaiter is safe to use and
597 // bw->waiter_state will not change again.
598 // unsleep_if_necessary(bw, get_global_timer_thread());
599 tls_task_group->ready_to_run(bw->task_meta);
600 // FIXME: jump back to original thread is buggy.
601
602 // // Value unmatched or waiter is already woken up by TimerThread, jump
603 // // back to original bthread.
604 // TaskGroup* g = tls_task_group;
605 // ReadyToRunArgs args = { g->current_tid(), false };
606 // g->set_remained(TaskGroup::ready_to_run_in_worker, &args);

Callers

nothing calls this directly

Calls 9

get_global_timer_threadFunction · 0.85
set_statusMethod · 0.80
ready_to_runMethod · 0.80
loadMethod · 0.45
PrependMethod · 0.45
AppendMethod · 0.45
storeMethod · 0.45
scheduleMethod · 0.45

Tested by

no test coverage detected