YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/util/rwc_lock-test.cc
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
33
#include <mutex>
34
#include <string>
35
#include <thread>
36
#include <vector>
37
38
#include "yb/gutil/atomicops.h"
39
#include "yb/util/rwc_lock.h"
40
#include "yb/util/test_util.h"
41
#include "yb/util/locks.h"
42
43
namespace yb {
44
45
using base::subtle::NoBarrier_Load;
46
using base::subtle::Release_Store;
47
using std::string;
48
using std::vector;
49
50
class RWCLockTest : public YBTest {};
51
52
// Holds counters of how many threads hold the lock in each of the
53
// provided modes.
54
struct LockHoldersCount {
55
  LockHoldersCount()
56
    : num_readers(0),
57
      num_writers(0),
58
1
      num_committers(0) {
59
1
  }
60
61
  // Check the invariants of the lock counts.
62
167k
  void CheckInvariants() {
63
    // At no time should we have more than one writer or committer.
64
167k
    CHECK_LE(num_writers, 1);
65
167k
    CHECK_LE(num_committers, 1);
66
67
    // If we have any readers, then we should not have any committers.
68
167k
    if (num_readers > 0) {
69
128k
      CHECK_EQ(num_committers, 0);
70
128k
    }
71
167k
  }
72
73
165k
  void AdjustReaders(int delta) {
74
165k
    std::lock_guard<simple_spinlock> l(lock);
75
165k
    num_readers += delta;
76
165k
    CheckInvariants();
77
165k
  }
78
79
824
  void AdjustWriters(int delta) {
80
824
    std::lock_guard<simple_spinlock> l(lock);
81
824
    num_writers += delta;
82
824
    CheckInvariants();
83
824
  }
84
85
824
  void AdjustCommitters(int delta) {
86
824
    std::lock_guard<simple_spinlock> l(lock);
87
824
    num_committers += delta;
88
824
    CheckInvariants();
89
824
  }
90
91
  int num_readers;
92
  int num_writers;
93
  int num_committers;
94
  simple_spinlock lock;
95
};
96
97
struct SharedState {
98
  LockHoldersCount counts;
99
  RWCLock rwc_lock;
100
  Atomic32 stop;
101
};
102
103
5
void ReaderThread(SharedState* state) {
104
82.8k
  while (!NoBarrier_Load(&state->stop)) {
105
82.8k
    state->rwc_lock.ReadLock();
106
82.8k
    state->counts.AdjustReaders(1);
107
82.8k
    state->counts.AdjustReaders(-1);
108
82.8k
    state->rwc_lock.ReadUnlock();
109
82.8k
  }
110
5
}
111
112
5
void WriterThread(SharedState* state) {
113
5
  string local_str;
114
417
  while (!NoBarrier_Load(&state->stop)) {
115
412
    state->rwc_lock.WriteLock();
116
412
    state->counts.AdjustWriters(1);
117
118
412
    state->rwc_lock.UpgradeToCommitLock();
119
412
    state->counts.AdjustWriters(-1);
120
412
    state->counts.AdjustCommitters(1);
121
122
412
    state->counts.AdjustCommitters(-1);
123
412
    state->rwc_lock.CommitUnlock();
124
412
  }
125
5
}
126
127
128
1
TEST_F(RWCLockTest, TestCorrectBehavior) {
129
1
  SharedState state;
130
1
  Release_Store(&state.stop, 0);
131
132
1
  std::vector<std::thread> threads;
133
134
1
  const int kNumWriters = 5;
135
1
  const int kNumReaders = 5;
136
137
6
  for (int i = 0; i < kNumWriters; i++) {
138
5
    threads.emplace_back(std::bind(WriterThread, &state));
139
5
  }
140
6
  for (int i = 0; i < kNumReaders; i++) {
141
5
    threads.emplace_back(std::bind(ReaderThread, &state));
142
5
  }
143
144
1
  if (AllowSlowTests()) {
145
0
    SleepFor(MonoDelta::FromSeconds(1));
146
1
  } else {
147
1
    SleepFor(MonoDelta::FromMilliseconds(100));
148
1
  }
149
150
1
  Release_Store(&state.stop, 1);
151
152
10
  for (auto& t : threads) {
153
10
    t.join();
154
10
  }
155
156
1
}
157
158
} // namespace yb