From: Peizhao Ou Date: Thu, 18 Jan 2018 23:35:38 +0000 (-0800) Subject: Adds sequential misc test cases X-Git-Url: http://plrg.eecs.uci.edu/git/?p=libcds.git;a=commitdiff_plain;h=bbdab38eb8ae6ee2237a03d8600a63d7481c37e6 Adds sequential misc test cases --- diff --git a/test/stress/sequential/CMakeLists.txt b/test/stress/sequential/CMakeLists.txt index 059bb6f4..39ca90f7 100644 --- a/test/stress/sequential/CMakeLists.txt +++ b/test/stress/sequential/CMakeLists.txt @@ -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 index 00000000..6b48b52a --- /dev/null +++ b/test/stress/sequential/sequential-misc/CMakeLists.txt @@ -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 index 00000000..e297f166 --- /dev/null +++ b/test/stress/sequential/sequential-misc/common.h @@ -0,0 +1,17 @@ +#ifndef _CDS_STRESS_TEST_COMMON_H +#define _CDS_STRESS_TEST_COMMON_H + +#include + +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 index 00000000..cd47986c --- /dev/null +++ b/test/stress/sequential/sequential-misc/deque_driver.cpp @@ -0,0 +1,89 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include + +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 index 00000000..5914f559 --- /dev/null +++ b/test/stress/sequential/sequential-misc/mcslock_driver.cpp @@ -0,0 +1,56 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include + +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 index 00000000..61dc9893 --- /dev/null +++ b/test/stress/sequential/sequential-misc/rwlock_driver.cpp @@ -0,0 +1,73 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include + +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 index 00000000..f3680b64 --- /dev/null +++ b/test/stress/sequential/sequential-misc/seqlock_driver.cpp @@ -0,0 +1,52 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include + +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 index 00000000..bd2c42a3 --- /dev/null +++ b/test/stress/sequential/sequential-misc/spinlock_driver.cpp @@ -0,0 +1,73 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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