#pragma once #include "../relacy/pthread.h" struct test_pthread_thread : rl::test_suite { static size_t const dynamic_thread_count = 2; VAR_T(int) data; static void* func(void* param) { static_cast(param)->VAR(data) += 1; return 0; } void thread(unsigned) { VAR(data) = 0; pthread_t th1; pthread_create(&th1, 0, &test_pthread_thread::func, this); void* res1 = 0; pthread_join(th1, &res1); RL_ASSERT(VAR(data) == 1); pthread_t th2; pthread_create(&th2, 0, &test_pthread_thread::func, this); void* res2 = 0; pthread_join(th2, &res2); RL_ASSERT(VAR(data) == 2); } }; struct test_pthread_mutex : rl::test_suite { pthread_mutex_t mtx; VAR_T(int) data; void before() { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&mtx, &attr); pthread_mutexattr_destroy(&attr); VAR(data) = 0; } void after() { pthread_mutex_destroy(&mtx); } void thread(unsigned /*index*/) { pthread_mutex_lock(&mtx); VAR(data) += 1; pthread_mutex_unlock(&mtx); if (0 == pthread_mutex_try_lock(&mtx)) { VAR(data) += 1; pthread_mutex_unlock(&mtx); } //pthread_mutex_timedlock } }; struct test_pthread_condvar : rl::test_suite { pthread_cond_t cv; pthread_mutex_t mtx; VAR_T(int) stage; void before() { pthread_condattr_t attr; pthread_cond_init(&cv, &attr); pthread_mutex_init(&mtx, 0); VAR(stage) = 0; } void after() { pthread_cond_destroy(&cv); pthread_mutex_destroy(&mtx); } void thread(unsigned index) { if (0 == index) { pthread_mutex_lock(&mtx); VAR(stage) += 1; pthread_cond_broadcast(&cv); while (VAR(stage) != 2) pthread_cond_wait(&cv, &mtx); pthread_mutex_unlock(&mtx); } else if (1 == index) { pthread_mutex_lock(&mtx); while (VAR(stage) != 1) { int ts = 1; pthread_cond_timedwait(&cv, &mtx, &ts); } VAR(stage) += 1; pthread_cond_broadcast(&cv); pthread_mutex_unlock(&mtx); } else if (2 == index) { pthread_mutex_lock(&mtx); while (VAR(stage) != 2) pthread_cond_wait(&cv, &mtx); pthread_mutex_unlock(&mtx); pthread_cond_signal(&cv); } } }; struct test_pthread_condvar2 : rl::test_suite { pthread_cond_t cv1, cv2; pthread_mutex_t mtx1, mtx2; VAR_T(int) stage; void before() { pthread_cond_init(&cv1, 0); pthread_cond_init(&cv2, 0); pthread_mutex_init(&mtx1, 0); pthread_mutex_init(&mtx2, 0); VAR(stage) = 0; } void after() { pthread_cond_destroy(&cv1); pthread_cond_destroy(&cv2); pthread_mutex_destroy(&mtx1); pthread_mutex_destroy(&mtx2); } void thread(unsigned index) { if (0 == index) { pthread_mutex_lock(&mtx1); int ts = 1; pthread_cond_timedwait(&cv1, &mtx1, &ts); pthread_mutex_unlock(&mtx1); } else if (1 == index) { pthread_mutex_lock(&mtx2); int ts = 1; pthread_cond_timedwait(&cv2, &mtx2, &ts); pthread_mutex_unlock(&mtx2); } } }; struct test_pthread_rwlock : rl::test_suite { pthread_rwlock_t mtx; VAR_T(int) data; void before() { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); pthread_rwlock_init(&mtx, &attr); pthread_mutexattr_destroy(&attr); VAR(data) = 0; } void after() { pthread_rwlock_destroy(&mtx); } void thread(unsigned /*index*/) { pthread_rwlock_wrlock(&mtx); VAR(data) += 1; pthread_rwlock_unlock(&mtx); if (0 == pthread_rwlock_trywrlock(&mtx)) { VAR(data) += 1; pthread_rwlock_unlock(&mtx); } pthread_rwlock_rdlock(&mtx); (void)(int)VAR(data); pthread_rwlock_unlock(&mtx); if (0 == pthread_rwlock_tryrdlock(&mtx)) { (void)(int)VAR(data); pthread_rwlock_unlock(&mtx); } } }; struct test_pthread_sem : rl::test_suite { sem_t sem1, sem2; VAR_T(int) data; void before() { sem_init(&sem1, 0, 0); sem_init(&sem2, 0, 0); VAR(data) = 0; } void after() { sem_destroy(&sem1); sem_destroy(&sem2); } void thread(unsigned index) { if (index) { VAR(data) = 1; sem_post(&sem1); while (sem_trywait(&sem2)) { assert(errno == EINTR || errno == EAGAIN); pthread_yield(); } RL_ASSERT(VAR(data) == 2); VAR(data) = 3; int count = -1; sem_getvalue(&sem2, &count); RL_ASSERT(count == 0); sem_post(&sem2); sem_getvalue(&sem2, &count); RL_ASSERT(count == 1); } else { while (sem_wait(&sem1)) assert(errno == EINTR); RL_ASSERT(VAR(data) == 1); VAR(data) = 2; sem_post(&sem2); } } };