/*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <folly/SmallLocks.h>
-#include <folly/Random.h>
+#include <pthread.h>
#include <cassert>
+#include <condition_variable>
#include <cstdio>
#include <mutex>
-#include <condition_variable>
#include <string>
-#include <vector>
-#include <pthread.h>
-#include <unistd.h>
-
#include <thread>
+#include <vector>
-#include <gtest/gtest.h>
+#include <folly/Random.h>
+#include <folly/portability/Asm.h>
+#include <folly/portability/GTest.h>
+#include <folly/portability/Unistd.h>
using folly::MSLGuard;
using folly::MicroLock;
const int max = 1000;
auto rng = folly::ThreadLocalPRNG();
for (int i = 0; i < max; i++) {
- folly::asm_pause();
+ folly::asm_volatile_pause();
MSLGuard g(v.lock);
int first = v.ar[0];
- for (size_t i = 1; i < sizeof v.ar / sizeof i; ++i) {
- EXPECT_EQ(first, v.ar[i]);
+ for (size_t j = 1; j < sizeof v.ar / sizeof j; ++j) {
+ EXPECT_EQ(first, v.ar[j]);
}
int byte = folly::Random::rand32(rng);
PslTest() { lock.init(); }
void doTest() {
- T ourVal = rand() % (T(1) << (sizeof(T) * 8 - 1));
- for (int i = 0; i < 10000; ++i) {
+ using UT = typename std::make_unsigned<T>::type;
+ T ourVal = rand() % T(UT(1) << (sizeof(UT) * 8 - 1));
+ for (int i = 0; i < 100; ++i) {
std::lock_guard<PicoSpinLock<T>> guard(lock);
lock.setData(ourVal);
for (int n = 0; n < 10; ++n) {
}
FOLLY_PACK_PUSH
+#if defined(__SANITIZE_ADDRESS__) && !defined(__clang__) && \
+ (defined(__GNUC__) || defined(__GNUG__))
+static_assert(sizeof(MicroLock) == 4, "Size check failed");
+#else
static_assert(sizeof(MicroLock) == 1, "Size check failed");
+#endif
FOLLY_PACK_POP
namespace {
};
}
-static void runMicroLockTest() {
+TEST(SmallLocks, MicroLock) {
volatile uint64_t counters[4] = {0, 0, 0, 0};
std::vector<std::thread> threads;
static const unsigned nrThreads = 20;
// affect bits outside the ones MicroLock is defined to affect.
struct {
uint8_t a;
- volatile uint8_t b;
- union {
- MicroLock alock;
- uint8_t c;
- };
- volatile uint8_t d;
+ std::atomic<uint8_t> b;
+ MicroLock alock;
+ std::atomic<uint8_t> d;
} x;
uint8_t origB = 'b';
x.a = 'a';
x.b = origB;
- x.c = 0;
+ x.alock.init();
x.d = origD;
// This thread touches other parts of the host word to show that
EXPECT_EQ(x.a, 'a');
EXPECT_EQ(x.b, (uint8_t)(origB + iterPerThread / 2));
- EXPECT_EQ(x.c, 0);
EXPECT_EQ(x.d, (uint8_t)(origD + iterPerThread / 2));
for (unsigned i = 0; i < 4; ++i) {
EXPECT_EQ(counters[i], ((uint64_t)nrThreads * iterPerThread) / 4);
}
}
-TEST(SmallLocks, MicroLock) { runMicroLockTest(); }
TEST(SmallLocks, MicroLockTryLock) {
MicroLock lock;
lock.init();
EXPECT_TRUE(lock.try_lock());
EXPECT_FALSE(lock.try_lock());
+ lock.unlock();
}