For reading.
| 40 | |
| 41 | // For reading. |
| 42 | static int rwlock_rdlock_impl(bthread_rwlock_t* __restrict rwlock, |
| 43 | const struct timespec* __restrict abstime) { |
| 44 | int reader_count = ((butil::atomic<int>*)&rwlock->reader_count) |
| 45 | ->fetch_add(1, butil::memory_order_acquire) + 1; |
| 46 | // Fast path. |
| 47 | if (reader_count >= 0) { |
| 48 | CHECK_LT(reader_count, RWLockMaxReaders); |
| 49 | return 0; |
| 50 | } |
| 51 | |
| 52 | // Slow path. |
| 53 | |
| 54 | // Don't sample when contention profiler is off. |
| 55 | if (NULL == bthread::g_cp) { |
| 56 | return bthread_sem_timedwait(&rwlock->reader_sema, abstime); |
| 57 | } |
| 58 | // Ask Collector if this (contended) locking should be sampled. |
| 59 | const size_t sampling_range = bvar::is_collectable(&bthread::g_cp_sl); |
| 60 | if (!bvar::is_sampling_range_valid(sampling_range)) { // Don't sample. |
| 61 | return bthread_sem_timedwait(&rwlock->reader_sema, abstime); |
| 62 | } |
| 63 | |
| 64 | // Sample. |
| 65 | const int64_t start_ns = butil::cpuwide_time_ns(); |
| 66 | int rc = bthread_sem_timedwait(&rwlock->reader_sema, abstime); |
| 67 | const int64_t end_ns = butil::cpuwide_time_ns(); |
| 68 | const bthread_contention_site_t csite{end_ns - start_ns, sampling_range}; |
| 69 | // Submit `csite' for each reader immediately after |
| 70 | // owning rdlock to avoid the contention of `csite'. |
| 71 | bthread::submit_contention(csite, end_ns); |
| 72 | |
| 73 | return rc; |
| 74 | } |
| 75 | |
| 76 | static inline int rwlock_rdlock(bthread_rwlock_t* rwlock) { |
| 77 | return rwlock_rdlock_impl(rwlock, NULL); |
no test coverage detected