Skip to content

Commit 82d7cec

Browse files
shanhe72101heshan
authored andcommitted
Restore read_count when the rwlock acquisition timeout
1 parent d0f8f8f commit 82d7cec

3 files changed

Lines changed: 42 additions & 9 deletions

File tree

src/bthread/rwlock.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ const int RWLockMaxReaders = 1 << 30;
4141
// For reading.
4242
static int rwlock_rdlock_impl(bthread_rwlock_t* __restrict rwlock,
4343
const struct timespec* __restrict abstime) {
44-
int reader_count = ((butil::atomic<int>*)&rwlock->reader_count)
44+
auto* reader_count_atomic = (butil::atomic<int>*)&rwlock->reader_count;
45+
int reader_count = reader_count_atomic
4546
->fetch_add(1, butil::memory_order_acquire) + 1;
4647
// Fast path.
4748
if (reader_count >= 0) {
@@ -53,18 +54,32 @@ static int rwlock_rdlock_impl(bthread_rwlock_t* __restrict rwlock,
5354

5455
// Don't sample when contention profiler is off.
5556
if (NULL == bthread::g_cp) {
56-
return bthread_sem_timedwait(&rwlock->reader_sema, abstime);
57+
int rc = bthread_sem_timedwait(&rwlock->reader_sema, abstime);
58+
if (rc != 0){
59+
reader_count_atomic->fetch_add(-1, butil::memory_order_relaxed);
60+
}
61+
return rc;
5762
}
5863
// Ask Collector if this (contended) locking should be sampled.
5964
const size_t sampling_range = bvar::is_collectable(&bthread::g_cp_sl);
6065
if (!bvar::is_sampling_range_valid(sampling_range)) { // Don't sample.
61-
return bthread_sem_timedwait(&rwlock->reader_sema, abstime);
66+
int rc = bthread_sem_timedwait(&rwlock->reader_sema, abstime);
67+
if (rc != 0){
68+
reader_count_atomic->fetch_add(-1, butil::memory_order_relaxed);
69+
}
70+
return rc;
6271
}
6372

6473
// Sample.
6574
const int64_t start_ns = butil::cpuwide_time_ns();
6675
int rc = bthread_sem_timedwait(&rwlock->reader_sema, abstime);
76+
if (rc != 0){
77+
reader_count_atomic->fetch_add(-1, butil::memory_order_relaxed);
78+
}
6779
const int64_t end_ns = butil::cpuwide_time_ns();
80+
if (rc != 0){
81+
((butil::atomic<int>*)&rwlock->reader_count)->fetch_add(-1, butil::memory_order_relaxed);
82+
}
6883
const bthread_contention_site_t csite{end_ns - start_ns, sampling_range};
6984
// Submit `csite' for each reader immediately after
7085
// owning rdlock to avoid the contention of `csite'.
@@ -189,7 +204,8 @@ static inline int rwlock_wrlock_impl(bthread_rwlock_t* __restrict rwlock,
189204
}
190205

191206
// Announce to readers there is a pending writer.
192-
int reader_count = ((butil::atomic<int>*)&rwlock->reader_count)
207+
auto* reader_count_atomic = (butil::atomic<int>*)&rwlock->reader_count;
208+
int reader_count = reader_count_atomic
193209
->fetch_add(-RWLockMaxReaders, butil::memory_order_release);
194210
// Wait for active readers.
195211
if (reader_count != 0 &&
@@ -204,6 +220,7 @@ static inline int rwlock_wrlock_impl(bthread_rwlock_t* __restrict rwlock,
204220
rc = bthread_sem_timedwait(&rwlock->writer_sema, abstime);
205221
if (0 != rc) {
206222
SUBMIT_CSITE_IF_NEED;
223+
reader_count_atomic->fetch_add(RWLockMaxReaders, butil::memory_order_release);
207224
bthread_mutex_unlock(&rwlock->write_queue_mutex);
208225
return rc;
209226
}

test/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ cc_test(
238238
# glog CHECK die with a fatal error
239239
"bthread_key_unittest.cpp",
240240
"bthread_butex_multi_tag_unittest.cpp",
241-
"bthread_rwlock_unittest.cpp",
241+
#"bthread_rwlock_unittest.cpp",
242242
"bthread_semaphore_unittest.cpp",
243243
],
244244
),

test/bthread_rwlock_unittest.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,26 +85,27 @@ TEST(RWLockTest, used_in_pthread) {
8585
}
8686

8787
void* do_timedrdlock(void *arg) {
88-
struct timespec t = { -2, 0 };
88+
struct timespec t = { 0, 100 };
8989
EXPECT_EQ(ETIMEDOUT, bthread_rwlock_timedrdlock((bthread_rwlock_t*)arg, &t));
9090
return NULL;
9191
}
9292

9393
void* do_timedwrlock(void *arg) {
94-
struct timespec t = { -2, 0 };
94+
struct timespec t = { 0, 100 };
9595
EXPECT_EQ(ETIMEDOUT, bthread_rwlock_timedwrlock((bthread_rwlock_t*)arg, &t));
96-
LOG(INFO) << 10;
9796
return NULL;
9897
}
9998

10099
TEST(RWLockTest, timedlock) {
101100
bthread_rwlock_t rw;
102101
ASSERT_EQ(0, bthread_rwlock_init(&rw, NULL));
102+
bthread_t th;
103103

104104
ASSERT_EQ(0, bthread_rwlock_rdlock(&rw));
105-
bthread_t th;
106105
ASSERT_EQ(0, bthread_start_urgent(&th, NULL, do_timedwrlock, &rw));
107106
ASSERT_EQ(0, bthread_join(th, NULL));
107+
ASSERT_EQ(0, bthread_start_urgent(&th, NULL, rdlocker, &rw));
108+
ASSERT_EQ(0, bthread_join(th, NULL));
108109
ASSERT_EQ(0, bthread_rwlock_unlock(&rw));
109110

110111
ASSERT_EQ(0, bthread_rwlock_wrlock(&rw));
@@ -113,6 +114,21 @@ TEST(RWLockTest, timedlock) {
113114
ASSERT_EQ(0, bthread_start_urgent(&th, NULL, do_timedrdlock, &rw));
114115
ASSERT_EQ(0, bthread_join(th, NULL));
115116
ASSERT_EQ(0, bthread_rwlock_unlock(&rw));
117+
118+
ASSERT_EQ(0, bthread_rwlock_wrlock(&rw));
119+
ASSERT_EQ(0, bthread_start_urgent(&th, NULL, do_timedrdlock, &rw));
120+
ASSERT_EQ(0, bthread_join(th, NULL));
121+
ASSERT_EQ(0, bthread_start_urgent(&th, NULL, do_timedwrlock, &rw));
122+
ASSERT_EQ(0, bthread_join(th, NULL));
123+
ASSERT_EQ(0, bthread_rwlock_unlock(&rw));
124+
125+
ASSERT_EQ(0, bthread_rwlock_rdlock(&rw));
126+
ASSERT_EQ(0, bthread_start_urgent(&th, NULL, do_timedwrlock, &rw));
127+
ASSERT_EQ(0, bthread_join(th, NULL));
128+
ASSERT_EQ(0, bthread_start_urgent(&th, NULL, rdlocker, &rw));
129+
ASSERT_EQ(0, bthread_join(th, NULL));
130+
ASSERT_EQ(0, bthread_rwlock_unlock(&rw));
131+
116132
ASSERT_EQ(0, bthread_rwlock_destroy(&rw));
117133
}
118134

0 commit comments

Comments
 (0)