Skip to content

Commit e54b4a6

Browse files
author
heshan
committed
Restore reader_count in case of failure in rwlock_rdlock_impl
1 parent 54a40d3 commit e54b4a6

3 files changed

Lines changed: 27 additions & 9 deletions

File tree

src/bthread/rwlock.cpp

Lines changed: 10 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) {
@@ -55,7 +56,7 @@ static int rwlock_rdlock_impl(bthread_rwlock_t* __restrict rwlock,
5556
if (NULL == bthread::g_cp) {
5657
int rc = bthread_sem_timedwait(&rwlock->reader_sema, abstime);
5758
if (rc != 0){
58-
((butil::atomic<int>*)&rwlock->reader_count)->fetch_add(-1, butil::memory_order_relaxed);
59+
reader_count_atomic->fetch_add(-1, butil::memory_order_relaxed);
5960
}
6061
return rc;
6162
}
@@ -64,14 +65,17 @@ static int rwlock_rdlock_impl(bthread_rwlock_t* __restrict rwlock,
6465
if (!bvar::is_sampling_range_valid(sampling_range)) { // Don't sample.
6566
int rc = bthread_sem_timedwait(&rwlock->reader_sema, abstime);
6667
if (rc != 0){
67-
((butil::atomic<int>*)&rwlock->reader_count)->fetch_add(-1, butil::memory_order_relaxed);
68+
reader_count_atomic->fetch_add(-1, butil::memory_order_relaxed);
6869
}
6970
return rc;
7071
}
7172

7273
// Sample.
7374
const int64_t start_ns = butil::cpuwide_time_ns();
7475
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+
}
7579
const int64_t end_ns = butil::cpuwide_time_ns();
7680
if (rc != 0){
7781
((butil::atomic<int>*)&rwlock->reader_count)->fetch_add(-1, butil::memory_order_relaxed);
@@ -200,7 +204,8 @@ static inline int rwlock_wrlock_impl(bthread_rwlock_t* __restrict rwlock,
200204
}
201205

202206
// Announce to readers there is a pending writer.
203-
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
204209
->fetch_add(-RWLockMaxReaders, butil::memory_order_release);
205210
// Wait for active readers.
206211
if (reader_count != 0 &&
@@ -215,6 +220,7 @@ static inline int rwlock_wrlock_impl(bthread_rwlock_t* __restrict rwlock,
215220
rc = bthread_sem_timedwait(&rwlock->writer_sema, abstime);
216221
if (0 != rc) {
217222
SUBMIT_CSITE_IF_NEED;
223+
reader_count_atomic->fetch_add(RWLockMaxReaders, butil::memory_order_release);
218224
bthread_mutex_unlock(&rwlock->write_queue_mutex);
219225
return rc;
220226
}

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: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,24 +85,23 @@ 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));
108107
ASSERT_EQ(0, bthread_rwlock_unlock(&rw));
@@ -113,6 +112,19 @@ TEST(RWLockTest, timedlock) {
113112
ASSERT_EQ(0, bthread_start_urgent(&th, NULL, do_timedrdlock, &rw));
114113
ASSERT_EQ(0, bthread_join(th, NULL));
115114
ASSERT_EQ(0, bthread_rwlock_unlock(&rw));
115+
116+
ASSERT_EQ(0, bthread_rwlock_wrlock(&rw));
117+
ASSERT_EQ(0, bthread_start_urgent(&th, NULL, do_timedrdlock, &rw));
118+
ASSERT_EQ(0, bthread_join(th, NULL));
119+
ASSERT_EQ(0, bthread_start_urgent(&th, NULL, do_timedwrlock, &rw));
120+
ASSERT_EQ(0, bthread_join(th, NULL));
121+
ASSERT_EQ(0, bthread_rwlock_unlock(&rw));
122+
123+
ASSERT_EQ(0, bthread_rwlock_rdlock(&rw));
124+
ASSERT_EQ(0, bthread_start_urgent(&th, NULL, do_timedwrlock, &rw));
125+
ASSERT_EQ(0, bthread_join(th, NULL));
126+
ASSERT_EQ(0, bthread_rwlock_unlock(&rw));
127+
116128
ASSERT_EQ(0, bthread_rwlock_destroy(&rw));
117129
}
118130

0 commit comments

Comments
 (0)