20 #include <condition_variable> 27 #include <glog/logging.h> 40 #ifdef FOLLY_PICO_SPIN_LOCK_H_ 52 memset(ar, 0,
sizeof ar);
63 static_assert(
sizeof(ignore1) == 3,
"Size check failed");
64 static_assert(
sizeof(
MicroSpinLock) == 1,
"Size check failed");
65 #ifdef FOLLY_PICO_SPIN_LOCK_H_ 67 PicoSpinLock<uint32_t> psl;
70 static_assert(
sizeof(ignore2) == 6,
"Size check failed");
78 for (
int i = 0;
i <
max;
i++) {
83 for (
size_t j = 1; j <
sizeof v.ar /
sizeof j; ++j) {
88 memset(v.ar,
char(byte),
sizeof v.ar);
92 #ifdef FOLLY_PICO_SPIN_LOCK_H_ 103 T ourVal = rand() %
T(UT(1) << (
sizeof(UT) * 8 - 1));
104 for (
int i = 0;
i < 100; ++
i) {
105 std::lock_guard<PicoSpinLock<T>>
guard(lock);
106 lock.setData(ourVal);
107 for (
int n = 0; n < 10; ++n) {
119 const int nthrs = 17;
120 std::vector<std::thread>
threads;
122 threads.push_back(std::thread(&PslTest<T>::doTest, &testObj));
124 for (
auto&
t : threads) {
136 std::lock_guard<MicroSpinLock>
g(lock_);
139 DCHECK(!lock_.try_lock());
148 TEST(SmallLocks, SpinLockCorrectness) {
151 int nthrs = sysconf(_SC_NPROCESSORS_ONLN) * 2;
152 std::vector<std::thread>
threads;
154 threads.push_back(std::thread(splock_test));
156 for (
auto&
t : threads) {
161 #ifdef FOLLY_PICO_SPIN_LOCK_H_ 162 TEST(SmallLocks, PicoSpinCorrectness) {
163 doPslTest<int16_t>();
164 doPslTest<uint16_t>();
165 doPslTest<int32_t>();
166 doPslTest<uint32_t>();
167 doPslTest<int64_t>();
168 doPslTest<uint64_t>();
171 TEST(SmallLocks, PicoSpinSigned) {
172 typedef PicoSpinLock<int16_t, 0> Lock;
178 std::lock_guard<Lock>
guard(val);
192 #if defined(__SANITIZE_ADDRESS__) && !defined(__clang__) && \ 193 (defined(__GNUC__) || defined(__GNUG__)) 194 static_assert(
sizeof(
MicroLock) == 4,
"Size check failed");
196 static_assert(
sizeof(
MicroLock) == 1,
"Size check failed");
206 std::unique_lock<std::mutex> lockHeld(lock_);
214 std::unique_lock<std::mutex> lockHeld(lock_);
223 std::condition_variable
cv_;
229 volatile uint64_t counters[4] = {0, 0, 0, 0};
230 std::vector<std::thread>
threads;
231 static const unsigned nrThreads = 20;
232 static const unsigned iterPerThread = 10000;
233 SimpleBarrier startBarrier;
235 assert(iterPerThread % 4 == 0);
241 std::atomic<uint8_t>
b;
243 std::atomic<uint8_t> d;
257 std::thread adjacentMemoryToucher = std::thread([&] {
259 for (
unsigned iter = 0; iter < iterPerThread; ++iter) {
268 for (
unsigned i = 0;
i < nrThreads; ++
i) {
269 threads.emplace_back([&] {
271 for (
unsigned iter = 0; iter < iterPerThread; ++iter) {
272 unsigned slotNo = iter % 4;
273 x.alock.lock(slotNo);
274 counters[slotNo] += 1;
277 if (iter % 1000 == 0) {
278 struct timespec ts = {0, 10000};
279 (void)nanosleep(&ts,
nullptr);
281 x.alock.unlock(slotNo);
288 for (
auto it = threads.begin(); it != threads.end(); ++it) {
292 adjacentMemoryToucher.join();
297 for (
unsigned i = 0;
i < 4; ++
i) {
302 TEST(SmallLocks, MicroLockTryLock) {
#define EXPECT_EQ(val1, val2)
std::lock_guard< MicroSpinLock > MSLGuard
TEST(SmallLocks, SpinLockCorrectness)
std::condition_variable cv_
std::vector< std::thread::id > threads
auto lock(SynchronizedLocker...lockersIn) -> std::tuple< typename SynchronizedLocker::LockedPtr... >
GuardImpl guard(ErrorHandler &&handler)
std::condition_variable cv_
#define EXPECT_TRUE(condition)
#define EXPECT_FALSE(condition)
constexpr detail::First first
void asm_volatile_pause()