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

Function bthread_sem_wait_impl

src/bthread/semaphore.cpp:49–109  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

47}
48
49static int bthread_sem_wait_impl(bthread_sem_t* sem, const struct timespec* abstime) {
50 bool queue_lifo = false;
51 bool first_wait = true;
52 size_t sampling_range = bvar::INVALID_SAMPLING_RANGE;
53 // -1: don't sample.
54 // 0: default value.
55 // > 0: Start time of sampling.
56 int64_t start_ns = 0;
57 auto whole = (butil::atomic<unsigned>*)sem->butex;
58 while (true) {
59 unsigned num = whole->load(butil::memory_order_relaxed);
60 if (num > 0) {
61 if (whole->compare_exchange_weak(num, num - 1,
62 butil::memory_order_acquire,
63 butil::memory_order_relaxed)) {
64 if (start_ns > 0) {
65 const int64_t end_ns = butil::cpuwide_time_ns();
66 const bthread_contention_site_t csite{end_ns - start_ns, sampling_range};
67 bthread::submit_contention(csite, end_ns);
68 }
69
70 return 0;
71 }
72 }
73 // Don't sample when contention profiler is off.
74 if (NULL != bthread::g_cp && start_ns == 0 && sem->enable_csite &&
75 !bvar::is_sampling_range_valid(sampling_range)) {
76 // Ask Collector if this (contended) sem waiting should be sampled.
77 sampling_range = bvar::is_collectable(&bthread::g_cp_sl);
78 start_ns = bvar::is_sampling_range_valid(sampling_range) ?
79 butil::cpuwide_time_ns() : -1;
80 } else {
81 start_ns = -1;
82 }
83 if (bthread::butex_wait(sem->butex, 0, abstime, queue_lifo) < 0 &&
84 errno != EWOULDBLOCK && errno != EINTR) {
85 // A sema should ignore interruptions in general since
86 // user code is unlikely to check the return value.
87 if (ETIMEDOUT == errno && start_ns > 0) {
88 // Failed to lock due to ETIMEDOUT, submit the elapse directly.
89 const int64_t end_ns = butil::cpuwide_time_ns();
90 const bthread_contention_site_t csite{end_ns - start_ns, sampling_range};
91 bthread::submit_contention(csite, end_ns);
92 }
93
94 return errno;
95 }
96 // Ignore EWOULDBLOCK and EINTR.
97 if (first_wait && 0 == errno) {
98 first_wait = false;
99 }
100 if (!first_wait) {
101 // Normally, bthreads are queued in FIFO order. But competing with new
102 // arriving bthreads over sema, a woken up bthread has good chances of
103 // losing. Because new arriving bthreads are already running on CPU and
104 // there can be lots of them. In such case, for fairness, to avoid
105 // starvation, it is queued at the head of the waiter queue.
106 queue_lifo = true;

Callers 2

bthread_sem_waitFunction · 0.85
bthread_sem_timedwaitFunction · 0.85

Calls 7

cpuwide_time_nsFunction · 0.85
submit_contentionFunction · 0.85
is_sampling_range_validFunction · 0.85
is_collectableFunction · 0.85
butex_waitFunction · 0.85
loadMethod · 0.45
compare_exchange_weakMethod · 0.45

Tested by

no test coverage detected