6bccc11739edd84ad478406b8867fc3c541ec4ce
[libcds.git] / test / stress / misc / spinlock_driver.cpp
1 #include "common.h"
2 #include <atomic>
3 #include <cds/gc/dhp.h>
4 #include <cds/gc/hp.h>
5 #include <cds/sync/spinlock.h>
6 #include <cds/misc/ticket_lock.h>
7 #include <cds_test/stress_test.h>
8 #include <iostream>
9 #include <iostream>
10 #include <memory>
11 #include <thread>
12
13 using namespace std;
14
15 namespace {
16
17 typedef cds_others::TicketLock TicketLock;
18 typedef cds::sync::spin SpinLock;
19 typedef cds::sync::reentrant_spin32 Reentrant32;
20 typedef cds::sync::reentrant_spin64 Reentrant64;
21 static size_t s_nSpinLockThreadCount = 4;
22 static size_t s_nSpinLockPassCount = 2500000000;
23 static size_t s_nReentrantLockPassCount = 2500000000;
24 static size_t s_nTicketLockPassCount = 4000000;
25
26 #define TASK(lock_type, lock_ptr, pass_cnt)                                    \
27   static void Thread##lock_type() {                                            \
28     for (size_t i = 0; i < pass_cnt; i++) {                                    \
29       lock_ptr->lock();                                                        \
30       x++;                                                                     \
31       lock_ptr->unlock();                                                      \
32     }                                                                          \
33   }
34
35 #define LOCK_TEST(lock_type, lock_ptr, pass_cnt)                               \
36   TEST_F(SpinLockTest, lock_type) {                                            \
37     lock_ptr = new lock_type();                                                \
38     x = 0;                                                                     \
39     std::unique_ptr<std::thread[]>(new std::thread[s_nSpinLockThreadCount]);   \
40     std::thread *threads = new std::thread[s_nSpinLockThreadCount];            \
41     for (size_t i = 0; i < s_nSpinLockThreadCount; i++) {                      \
42       threads[i] = std::thread(Thread##lock_type);                             \
43     }                                                                          \
44     for (size_t i = 0; i < s_nSpinLockThreadCount; i++) {                      \
45       threads[i].join();                                                       \
46     }                                                                          \
47     if (x != s_nSpinLockThreadCount * pass_cnt) {                              \
48       cout << "Incorrect " << #lock_type << "\n";                              \
49       cout << "x=" << x << "\nThreadCount=" << s_nSpinLockThreadCount          \
50            << "\nPassCount=" << pass_cnt                                       \
51            << "\t&&\tSupposed times=" << s_nSpinLockThreadCount * pass_cnt     \
52            << "\n";                                                            \
53     }                                                                          \
54   }
55
56 class SpinLockTest : public cds_test::stress_fixture {
57 protected:
58   static size_t x;
59   static TicketLock *ticket_mutex;
60   static SpinLock *spin_mutex;
61   static Reentrant32 *reentrant_mutex32;
62   static Reentrant64 *reentrant_mutex64;
63
64   static void SetUpTestCase() {
65     cds_test::config const &cfg = get_config("Misc");
66     GetConfig(SpinLockThreadCount);
67     GetConfig(SpinLockPassCount);
68     GetConfig(ReentrantLockPassCount);
69     GetConfig(TicketLockPassCount);
70   }
71
72   TASK(TicketLock, ticket_mutex, s_nTicketLockPassCount)
73   TASK(SpinLock, spin_mutex, s_nSpinLockPassCount)
74   TASK(Reentrant32, reentrant_mutex32, s_nReentrantLockPassCount)
75   TASK(Reentrant64, reentrant_mutex64, s_nReentrantLockPassCount)
76 };
77
78 size_t SpinLockTest::x;
79 TicketLock *SpinLockTest::ticket_mutex;
80 SpinLock *SpinLockTest::spin_mutex;
81 Reentrant32 *SpinLockTest::reentrant_mutex32;
82 Reentrant64 *SpinLockTest::reentrant_mutex64;
83
84 LOCK_TEST(TicketLock, ticket_mutex, s_nTicketLockPassCount)
85 LOCK_TEST(SpinLock, spin_mutex, s_nSpinLockPassCount)
86 LOCK_TEST(Reentrant32, reentrant_mutex32, s_nReentrantLockPassCount)
87 LOCK_TEST(Reentrant64, reentrant_mutex64, s_nReentrantLockPassCount)
88
89 } // namespace