proxygen
SmallLocksTest.cpp File Reference
#include <folly/synchronization/SmallLocks.h>
#include <cassert>
#include <condition_variable>
#include <cstdio>
#include <mutex>
#include <string>
#include <thread>
#include <vector>
#include <glog/logging.h>
#include <folly/Random.h>
#include <folly/portability/Asm.h>
#include <folly/portability/GTest.h>
#include <folly/portability/PThread.h>
#include <folly/portability/Unistd.h>

Go to the source code of this file.

Classes

struct  FOLLY_PACK_POP::SimpleBarrier
 

Namespaces

 FOLLY_PACK_POP
 

Functions

 TEST (SmallLocks, SpinLockCorrectness)
 
 TEST (SmallLocks, RegClobber)
 
 TEST (SmallLocks, MicroLock)
 
 TEST (SmallLocks, MicroLockTryLock)
 

Variables

 FOLLY_PACK_PUSH
 

Function Documentation

TEST ( SmallLocks  ,
SpinLockCorrectness   
)

Definition at line 148 of file SmallLocksTest.cpp.

References EXPECT_EQ, folly::gen::guard(), i, nthrs, folly::pushmi::detail::t, threads, and val.

148  {
149  EXPECT_EQ(sizeof(MicroSpinLock), 1);
150 
151  int nthrs = sysconf(_SC_NPROCESSORS_ONLN) * 2;
152  std::vector<std::thread> threads;
153  for (int i = 0; i < nthrs; ++i) {
154  threads.push_back(std::thread(splock_test));
155  }
156  for (auto& t : threads) {
157  t.join();
158  }
159 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
std::vector< std::thread::id > threads
const int nthrs
TEST ( SmallLocks  ,
RegClobber   
)

Definition at line 187 of file SmallLocksTest.cpp.

References FOLLY_PACK_PUSH.

187  {
188  TestClobber().go();
189 }
TEST ( SmallLocks  ,
MicroLock   
)

Definition at line 228 of file SmallLocksTest.cpp.

References a, b, EXPECT_EQ, i, threads, uint64_t, uint8_t, and x.

228  {
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;
234 
235  assert(iterPerThread % 4 == 0);
236 
237  // Embed the lock in a larger structure to ensure that we do not
238  // affect bits outside the ones MicroLock is defined to affect.
239  struct {
240  uint8_t a;
241  std::atomic<uint8_t> b;
242  MicroLock alock;
243  std::atomic<uint8_t> d;
244  } x;
245 
246  uint8_t origB = 'b';
247  uint8_t origD = 'd';
248 
249  x.a = 'a';
250  x.b = origB;
251  x.alock.init();
252  x.d = origD;
253 
254  // This thread touches other parts of the host word to show that
255  // MicroLock does not interfere with memory outside of the byte
256  // it owns.
257  std::thread adjacentMemoryToucher = std::thread([&] {
258  startBarrier.wait();
259  for (unsigned iter = 0; iter < iterPerThread; ++iter) {
260  if (iter % 2) {
261  x.b++;
262  } else {
263  x.d++;
264  }
265  }
266  });
267 
268  for (unsigned i = 0; i < nrThreads; ++i) {
269  threads.emplace_back([&] {
270  startBarrier.wait();
271  for (unsigned iter = 0; iter < iterPerThread; ++iter) {
272  unsigned slotNo = iter % 4;
273  x.alock.lock(slotNo);
274  counters[slotNo] += 1;
275  // The occasional sleep makes it more likely that we'll
276  // exercise the futex-wait path inside MicroLock.
277  if (iter % 1000 == 0) {
278  struct timespec ts = {0, 10000};
279  (void)nanosleep(&ts, nullptr);
280  }
281  x.alock.unlock(slotNo);
282  }
283  });
284  }
285 
286  startBarrier.run();
287 
288  for (auto it = threads.begin(); it != threads.end(); ++it) {
289  it->join();
290  }
291 
292  adjacentMemoryToucher.join();
293 
294  EXPECT_EQ(x.a, 'a');
295  EXPECT_EQ(x.b, (uint8_t)(origB + iterPerThread / 2));
296  EXPECT_EQ(x.d, (uint8_t)(origD + iterPerThread / 2));
297  for (unsigned i = 0; i < 4; ++i) {
298  EXPECT_EQ(counters[i], ((uint64_t)nrThreads * iterPerThread) / 4);
299  }
300 }
Definition: InvokeTest.cpp:58
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
const int x
std::vector< std::thread::id > threads
char a
MicroLockBase MicroLock
Definition: MicroLock.h:233
TEST ( SmallLocks  ,
MicroLockTryLock   
)

Definition at line 302 of file SmallLocksTest.cpp.

References EXPECT_FALSE, EXPECT_TRUE, and folly::detail::lock().

302  {
303  MicroLock lock;
304  lock.init();
305  EXPECT_TRUE(lock.try_lock());
306  EXPECT_FALSE(lock.try_lock());
307  lock.unlock();
308 }
auto lock(SynchronizedLocker...lockersIn) -> std::tuple< typename SynchronizedLocker::LockedPtr... >
Definition: Synchronized.h:871
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
MicroLockBase MicroLock
Definition: MicroLock.h:233
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862

Variable Documentation

FOLLY_PACK_PUSH

Definition at line 196 of file SmallLocksTest.cpp.

Referenced by folly::exception_wrapper::ExceptionPtr::as_int_(), and TEST().