diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/pthread_test.cpp | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp index 5dc60ee..c507faa 100644 --- a/tests/pthread_test.cpp +++ b/tests/pthread_test.cpp @@ -33,6 +33,8 @@ #include <time.h> #include <unistd.h> +#include <atomic> + TEST(pthread, pthread_key_create) { pthread_key_t key; ASSERT_EQ(0, pthread_key_create(&key, NULL)); @@ -699,6 +701,79 @@ TEST(pthread, pthread_rwlock_smoke) { ASSERT_EQ(0, pthread_rwlock_destroy(&l)); } +struct RwlockWakeupHelperArg { + pthread_rwlock_t lock; + enum Progress { + LOCK_INITIALIZED, + LOCK_WAITING, + LOCK_RELEASED, + LOCK_ACCESSED + }; + std::atomic<Progress> progress; +}; + +static void pthread_rwlock_reader_wakeup_writer_helper(RwlockWakeupHelperArg* arg) { + ASSERT_EQ(RwlockWakeupHelperArg::LOCK_INITIALIZED, arg->progress); + arg->progress = RwlockWakeupHelperArg::LOCK_WAITING; + + ASSERT_EQ(EBUSY, pthread_rwlock_trywrlock(&arg->lock)); + ASSERT_EQ(0, pthread_rwlock_wrlock(&arg->lock)); + ASSERT_EQ(RwlockWakeupHelperArg::LOCK_RELEASED, arg->progress); + ASSERT_EQ(0, pthread_rwlock_unlock(&arg->lock)); + + arg->progress = RwlockWakeupHelperArg::LOCK_ACCESSED; +} + +TEST(pthread, pthread_rwlock_reader_wakeup_writer) { + RwlockWakeupHelperArg wakeup_arg; + ASSERT_EQ(0, pthread_rwlock_init(&wakeup_arg.lock, NULL)); + ASSERT_EQ(0, pthread_rwlock_rdlock(&wakeup_arg.lock)); + wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_INITIALIZED; + + pthread_t thread; + ASSERT_EQ(0, pthread_create(&thread, NULL, + reinterpret_cast<void* (*)(void*)>(pthread_rwlock_reader_wakeup_writer_helper), &wakeup_arg)); + sleep(1); + ASSERT_EQ(RwlockWakeupHelperArg::LOCK_WAITING, wakeup_arg.progress); + wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_RELEASED; + ASSERT_EQ(0, pthread_rwlock_unlock(&wakeup_arg.lock)); + + ASSERT_EQ(0, pthread_join(thread, NULL)); + ASSERT_EQ(RwlockWakeupHelperArg::LOCK_ACCESSED, wakeup_arg.progress); + ASSERT_EQ(0, pthread_rwlock_destroy(&wakeup_arg.lock)); +} + +static void pthread_rwlock_writer_wakeup_reader_helper(RwlockWakeupHelperArg* arg) { + ASSERT_EQ(RwlockWakeupHelperArg::LOCK_INITIALIZED, arg->progress); + arg->progress = RwlockWakeupHelperArg::LOCK_WAITING; + + ASSERT_EQ(EBUSY, pthread_rwlock_tryrdlock(&arg->lock)); + ASSERT_EQ(0, pthread_rwlock_rdlock(&arg->lock)); + ASSERT_EQ(RwlockWakeupHelperArg::LOCK_RELEASED, arg->progress); + ASSERT_EQ(0, pthread_rwlock_unlock(&arg->lock)); + + arg->progress = RwlockWakeupHelperArg::LOCK_ACCESSED; +} + +TEST(pthread, pthread_rwlock_writer_wakeup_reader) { + RwlockWakeupHelperArg wakeup_arg; + ASSERT_EQ(0, pthread_rwlock_init(&wakeup_arg.lock, NULL)); + ASSERT_EQ(0, pthread_rwlock_wrlock(&wakeup_arg.lock)); + wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_INITIALIZED; + + pthread_t thread; + ASSERT_EQ(0, pthread_create(&thread, NULL, + reinterpret_cast<void* (*)(void*)>(pthread_rwlock_writer_wakeup_reader_helper), &wakeup_arg)); + sleep(1); + ASSERT_EQ(RwlockWakeupHelperArg::LOCK_WAITING, wakeup_arg.progress); + wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_RELEASED; + ASSERT_EQ(0, pthread_rwlock_unlock(&wakeup_arg.lock)); + + ASSERT_EQ(0, pthread_join(thread, NULL)); + ASSERT_EQ(RwlockWakeupHelperArg::LOCK_ACCESSED, wakeup_arg.progress); + ASSERT_EQ(0, pthread_rwlock_destroy(&wakeup_arg.lock)); +} + static int g_once_fn_call_count = 0; static void OnceFn() { ++g_once_fn_call_count; |