Adds sequential misc test cases
authorPeizhao Ou <peizhaoo@uci.edu>
Thu, 18 Jan 2018 23:35:38 +0000 (15:35 -0800)
committerPeizhao Ou <peizhaoo@uci.edu>
Thu, 18 Jan 2018 23:35:38 +0000 (15:35 -0800)
test/stress/sequential/CMakeLists.txt
test/stress/sequential/sequential-misc/CMakeLists.txt [new file with mode: 0644]
test/stress/sequential/sequential-misc/common.h [new file with mode: 0644]
test/stress/sequential/sequential-misc/deque_driver.cpp [new file with mode: 0644]
test/stress/sequential/sequential-misc/mcslock_driver.cpp [new file with mode: 0644]
test/stress/sequential/sequential-misc/rwlock_driver.cpp [new file with mode: 0644]
test/stress/sequential/sequential-misc/seqlock_driver.cpp [new file with mode: 0644]
test/stress/sequential/sequential-misc/spinlock_driver.cpp [new file with mode: 0644]

index 059bb6f4cfec6ceb5362bc9a2c83b61b1bd15157..39ca90f754ae84d7cd381d8630eff9682f04b1eb 100644 (file)
@@ -1,5 +1,6 @@
 set(PACKAGE_NAME stress-sequential)
 
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sequential-misc)
 add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sequential-set)
 add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sequential-map)
 
diff --git a/test/stress/sequential/sequential-misc/CMakeLists.txt b/test/stress/sequential/sequential-misc/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6b48b52
--- /dev/null
@@ -0,0 +1,19 @@
+set(PACKAGE_NAME stress-sequential-misc)
+
+set(CDSSTRESS_STACK_SOURCES
+    ../../main.cpp
+    spinlock_driver.cpp
+    deque_driver.cpp
+    seqlock_driver.cpp
+    rwlock_driver.cpp
+    mcslock_driver.cpp
+)
+
+include_directories(
+    ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+add_executable(${PACKAGE_NAME} ${CDSSTRESS_STACK_SOURCES})
+target_link_libraries(${PACKAGE_NAME} ${CDS_TEST_LIBRARIES} ${CDSSTRESS_FRAMEWORK_LIBRARY})
+
+add_test(NAME ${PACKAGE_NAME} COMMAND ${PACKAGE_NAME} WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
diff --git a/test/stress/sequential/sequential-misc/common.h b/test/stress/sequential/sequential-misc/common.h
new file mode 100644 (file)
index 0000000..e297f16
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _CDS_STRESS_TEST_COMMON_H
+#define _CDS_STRESS_TEST_COMMON_H
+
+#include <cds_test/stress_test.h>
+
+typedef unsigned long long ullong;
+
+#define GetConfig(field) s_n##field = cfg.get_size_t(#field, s_n##field)
+
+
+#ifdef PERFORMANCE
+#define DEBUG(stmt)
+#else
+#define DEBUG(stmt) stmt
+#endif
+
+#endif
diff --git a/test/stress/sequential/sequential-misc/deque_driver.cpp b/test/stress/sequential/sequential-misc/deque_driver.cpp
new file mode 100644 (file)
index 0000000..cd47986
--- /dev/null
@@ -0,0 +1,89 @@
+#include "common.h"
+#include <cds/container/chase-lev-deque.h>
+#include <cds_test/stress_test.h>
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+using namespace std;
+
+namespace {
+
+typedef cds_others::ChaseLevDeque Deque;
+static size_t s_nDequePassCount = 1000;
+static size_t s_nDequeStealerThreadCount = 5;
+static size_t s_nDequeMainPassCount = 100000000;
+
+class ChaseLevDequeTest : public cds_test::stress_fixture {
+protected:
+  static Deque *deque;
+  static atomic_int terminate_stealer;
+  static ullong *sums;
+  static ullong *succ_counts;
+  static ullong push_sum;
+  static ullong push_count;
+
+  static void SetUpTestCase() {
+    cds_test::config const &cfg = get_config("SequentialMisc");
+    GetConfig(DequePassCount);
+    GetConfig(DequeStealerThreadCount);
+    GetConfig(DequeMainPassCount);
+  }
+
+  static void StealerThread(int index) {
+    while (!terminate_stealer.load(memory_order_relaxed)) {
+      int res = deque->steal();
+      if (res != EMPTY && res != ABORT) {
+        sums[index] += res;
+        succ_counts[index]++;
+      }
+    }
+  }
+
+  static void MainThread(int index, int push_percentage) {
+    for (ullong i = 0; i < s_nDequeMainPassCount; i++) {
+      if ((::rand() % 100) < push_percentage) {
+        int item = ::rand() % 100;
+        deque->push(item);
+        push_sum += item;
+        push_count++;
+      } else {
+        int res = deque->take();
+        if (res != EMPTY) {
+          sums[index] += res;
+          succ_counts[index]++;
+        }
+      }
+    }
+    while (true) {
+      int res = deque->take();
+      if (res != EMPTY) {
+        sums[index] += res;
+        succ_counts[index]++;
+      } else {
+        break;
+      }
+    }
+  }
+};
+
+atomic_int ChaseLevDequeTest::terminate_stealer;
+ullong *ChaseLevDequeTest::sums;
+ullong *ChaseLevDequeTest::succ_counts;
+ullong ChaseLevDequeTest::push_count;
+ullong ChaseLevDequeTest::push_sum;
+Deque *ChaseLevDequeTest::deque;
+
+TEST_F(ChaseLevDequeTest, ChaseLevDeque) {
+  deque = new Deque();
+  for (size_t i = 0; i < s_nDequePassCount; ++i) {
+    deque->push(i);
+    int res = deque->take();
+    deque->push(i);
+    res = deque->steal();
+  }
+}
+
+} // namespace
diff --git a/test/stress/sequential/sequential-misc/mcslock_driver.cpp b/test/stress/sequential/sequential-misc/mcslock_driver.cpp
new file mode 100644 (file)
index 0000000..5914f55
--- /dev/null
@@ -0,0 +1,56 @@
+#include "common.h"
+#include <atomic>
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/sync/mcs-lock.h>
+#include <cds_test/stress_test.h>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+using namespace std;
+
+namespace {
+
+static size_t s_nMCSLockThreadCount = 6;
+static size_t s_nMCSLockPassCount = 3000000;
+
+class MCSLockTest : public cds_test::stress_fixture {
+protected:
+  static ullong x;
+  static cds_others::mcs_mutex *my_mutex;
+
+  static void SetUpTestCase() {
+    cds_test::config const &cfg = get_config("SequentialMisc");
+    GetConfig(MCSLockPassCount);
+    GetConfig(MCSLockThreadCount);
+  }
+
+  static void Thread() {
+    cds_others::mcs_mutex::guard g(my_mutex);
+    my_mutex->unlock(&g);
+    for (ullong i = 0; i < s_nMCSLockPassCount; i++) {
+      my_mutex->lock(&g);
+      x++;
+      my_mutex->unlock(&g);
+    }
+    my_mutex->lock(&g);
+  }
+};
+
+ullong MCSLockTest::x;
+cds_others::mcs_mutex *MCSLockTest::my_mutex;
+
+TEST_F(MCSLockTest, MCSLock) {
+  my_mutex = new cds_others::mcs_mutex();
+  cds_others::mcs_mutex::guard g(my_mutex);
+  my_mutex->unlock(&g);
+  for (size_t i = 0; i < s_nMCSLockPassCount; i++) {
+    my_mutex->lock(&g);
+    x++;
+    my_mutex->unlock(&g);
+  }
+  my_mutex->lock(&g);
+}
+
+} // namespace
diff --git a/test/stress/sequential/sequential-misc/rwlock_driver.cpp b/test/stress/sequential/sequential-misc/rwlock_driver.cpp
new file mode 100644 (file)
index 0000000..61dc989
--- /dev/null
@@ -0,0 +1,73 @@
+#include "common.h"
+#include <atomic>
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/sync/rwlock.h>
+#include <cds_test/stress_test.h>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+using namespace std;
+
+namespace {
+
+static size_t s_nRWLockThreadCount = 6;
+static size_t s_nRWLockPassCount = 200000;
+
+typedef cds_others::RWLock RWLock;
+class RWLockTest : public cds_test::stress_fixture {
+protected:
+  static size_t sum;
+  static size_t x;
+  static RWLock *rwlock;
+
+  static void SetUpTestCase() {
+    cds_test::config const &cfg = get_config("SequentialMisc");
+    GetConfig(RWLockThreadCount);
+    GetConfig(RWLockPassCount);
+  }
+
+  static void ReaderWriterThread(int write_percentage) {
+    for (size_t i = 0; i < s_nRWLockPassCount; i++) {
+      if (rand(100) < write_percentage) {
+        if (rwlock->read_can_lock()) {
+          if (!rwlock->read_trylock()) {
+            rwlock->read_lock();
+          }
+          sum += x;
+          rwlock->read_unlock();
+        } else {
+          rwlock->read_lock();
+          sum += x;
+          rwlock->read_unlock();
+        }
+      } else {
+        if (rwlock->write_can_lock()) {
+          if (!rwlock->write_trylock()) {
+            rwlock->write_lock();
+          }
+          x++;
+          rwlock->write_unlock();
+        } else {
+          rwlock->write_lock();
+          x++;
+          rwlock->write_unlock();
+        }
+      }
+    }
+  }
+};
+
+size_t RWLockTest::x;
+size_t RWLockTest::sum;
+RWLock *RWLockTest::rwlock;
+
+TEST_F(RWLockTest, ReadWriteLock) {
+  rwlock = new RWLock();
+  for (int write_percentage = 5; write_percentage < 40; write_percentage += 5) {
+    ReaderWriterThread(write_percentage);
+  }
+}
+
+} // namespace
diff --git a/test/stress/sequential/sequential-misc/seqlock_driver.cpp b/test/stress/sequential/sequential-misc/seqlock_driver.cpp
new file mode 100644 (file)
index 0000000..f3680b6
--- /dev/null
@@ -0,0 +1,52 @@
+#include "common.h"
+#include <atomic>
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/sync/seqlock.h>
+#include <cds_test/stress_test.h>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+using namespace std;
+
+namespace {
+
+typedef cds_others::SeqLock SeqLock;
+
+static size_t s_nSeqLockReaderWriterThreadCount = 6;
+static size_t s_nSeqLockPassCount = 2000000;
+
+class SeqLockTest : public cds_test::stress_fixture {
+protected:
+  static size_t sum;
+  static SeqLock *seqlock;
+
+  static void SetUpTestCase() {
+    cds_test::config const &cfg = get_config("SequentialMisc");
+    GetConfig(SeqLockReaderWriterThreadCount);
+    GetConfig(SeqLockPassCount);
+  }
+
+  static void ReaderWriterThread(int write_percentage) {
+    for (size_t i = 0; i < s_nSeqLockPassCount; i++) {
+      if (rand(100) < write_percentage) {
+        sum += seqlock->read();
+      } else {
+        seqlock->write(rand(10));
+      }
+    }
+  }
+};
+
+size_t SeqLockTest::sum;
+SeqLock *SeqLockTest::seqlock;
+
+TEST_F(SeqLockTest, SeqLock) {
+  seqlock = new SeqLock();
+  for (int write_percentage = 5; write_percentage < 50; write_percentage += 5) {
+    ReaderWriterThread(write_percentage);
+  }
+}
+
+} // namespace
diff --git a/test/stress/sequential/sequential-misc/spinlock_driver.cpp b/test/stress/sequential/sequential-misc/spinlock_driver.cpp
new file mode 100644 (file)
index 0000000..bd2c42a
--- /dev/null
@@ -0,0 +1,73 @@
+#include "common.h"
+#include <atomic>
+#include <cds/gc/dhp.h>
+#include <cds/gc/hp.h>
+#include <cds/sync/spinlock.h>
+#include <cds/sync/ticket_lock.h>
+#include <cds_test/stress_test.h>
+#include <iostream>
+#include <iostream>
+#include <memory>
+#include <thread>
+
+using namespace std;
+
+namespace {
+
+typedef cds_others::TicketLock TicketLock;
+typedef cds::sync::spin SpinLock;
+typedef cds::sync::reentrant_spin32 Reentrant32;
+typedef cds::sync::reentrant_spin64 Reentrant64;
+static size_t s_nSpinLockThreadCount = 6;
+static size_t s_nSpinLockPassCount = 2500000000;
+static size_t s_nTicketLockPassCount = 4000000;
+
+#define TASK(lock_type, lock_ptr, pass_cnt)                                    \
+  static void Thread##lock_type() {                                            \
+    for (size_t i = 0; i < pass_cnt; i++) {                                    \
+      lock_ptr->lock();                                                        \
+      x++;                                                                     \
+      lock_ptr->unlock();                                                      \
+    }                                                                          \
+  }
+
+#define LOCK_TEST(lock_type, lock_ptr, pass_cnt)                               \
+  TEST_F(SpinLockTest, lock_type) {                                            \
+    lock_ptr = new lock_type();                                                \
+    x = 0;                                                                     \
+    Thread##lock_type();                                                       \
+  }
+
+class SpinLockTest : public cds_test::stress_fixture {
+protected:
+  static size_t x;
+  static TicketLock *ticket_mutex;
+  static SpinLock *spin_mutex;
+  static Reentrant32 *reentrant_mutex32;
+  static Reentrant64 *reentrant_mutex64;
+
+  static void SetUpTestCase() {
+    cds_test::config const &cfg = get_config("SequentialMisc");
+    GetConfig(SpinLockThreadCount);
+    GetConfig(SpinLockPassCount);
+    GetConfig(TicketLockPassCount);
+  }
+
+  TASK(TicketLock, ticket_mutex, s_nTicketLockPassCount)
+  TASK(SpinLock, spin_mutex, s_nSpinLockPassCount)
+  TASK(Reentrant32, reentrant_mutex32, s_nSpinLockPassCount)
+  TASK(Reentrant64, reentrant_mutex64, s_nSpinLockPassCount)
+};
+
+size_t SpinLockTest::x;
+TicketLock *SpinLockTest::ticket_mutex;
+SpinLock *SpinLockTest::spin_mutex;
+Reentrant32 *SpinLockTest::reentrant_mutex32;
+Reentrant64 *SpinLockTest::reentrant_mutex64;
+
+LOCK_TEST(TicketLock, ticket_mutex, s_nTicketLockPassCount)
+LOCK_TEST(SpinLock, spin_mutex, s_nSpinLockPassCount)
+LOCK_TEST(Reentrant32, reentrant_mutex32, s_nSpinLockPassCount)
+LOCK_TEST(Reentrant64, reentrant_mutex64, s_nSpinLockPassCount)
+
+} // namespace