1 #pragma once 2 3 #include "../relacy/pthread.h" 4 5 6 7 struct test_pthread_thread : rl::test_suite<test_pthread_thread, 1> 8 { 9 static size_t const dynamic_thread_count = 2; 10 11 VAR_T(int) data; 12 functest_pthread_thread13 static void* func(void* param) 14 { 15 static_cast<test_pthread_thread*>(param)->VAR(data) += 1; 16 return 0; 17 } 18 threadtest_pthread_thread19 void thread(unsigned) 20 { 21 VAR(data) = 0; 22 23 pthread_t th1; 24 pthread_create(&th1, 0, &test_pthread_thread::func, this); 25 void* res1 = 0; 26 pthread_join(th1, &res1); 27 28 RL_ASSERT(VAR(data) == 1); 29 30 pthread_t th2; 31 pthread_create(&th2, 0, &test_pthread_thread::func, this); 32 void* res2 = 0; 33 pthread_join(th2, &res2); 34 35 RL_ASSERT(VAR(data) == 2); 36 } 37 }; 38 39 40 41 42 struct test_pthread_mutex : rl::test_suite<test_pthread_mutex, 2> 43 { 44 pthread_mutex_t mtx; 45 VAR_T(int) data; 46 beforetest_pthread_mutex47 void before() 48 { 49 pthread_mutexattr_t attr; 50 pthread_mutexattr_init(&attr); 51 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 52 pthread_mutex_init(&mtx, &attr); 53 pthread_mutexattr_destroy(&attr); 54 VAR(data) = 0; 55 } 56 aftertest_pthread_mutex57 void after() 58 { 59 pthread_mutex_destroy(&mtx); 60 } 61 threadtest_pthread_mutex62 void thread(unsigned /*index*/) 63 { 64 pthread_mutex_lock(&mtx); 65 VAR(data) += 1; 66 pthread_mutex_unlock(&mtx); 67 68 if (0 == pthread_mutex_try_lock(&mtx)) 69 { 70 VAR(data) += 1; 71 pthread_mutex_unlock(&mtx); 72 } 73 74 //pthread_mutex_timedlock 75 } 76 }; 77 78 79 80 81 struct test_pthread_condvar : rl::test_suite<test_pthread_condvar, 3> 82 { 83 pthread_cond_t cv; 84 pthread_mutex_t mtx; 85 VAR_T(int) stage; 86 beforetest_pthread_condvar87 void before() 88 { 89 pthread_condattr_t attr; 90 pthread_cond_init(&cv, &attr); 91 pthread_mutex_init(&mtx, 0); 92 VAR(stage) = 0; 93 } 94 aftertest_pthread_condvar95 void after() 96 { 97 pthread_cond_destroy(&cv); 98 pthread_mutex_destroy(&mtx); 99 } 100 threadtest_pthread_condvar101 void thread(unsigned index) 102 { 103 if (0 == index) 104 { 105 pthread_mutex_lock(&mtx); 106 VAR(stage) += 1; 107 pthread_cond_broadcast(&cv); 108 while (VAR(stage) != 2) 109 pthread_cond_wait(&cv, &mtx); 110 pthread_mutex_unlock(&mtx); 111 } 112 else if (1 == index) 113 { 114 pthread_mutex_lock(&mtx); 115 while (VAR(stage) != 1) 116 { 117 int ts = 1; 118 pthread_cond_timedwait(&cv, &mtx, &ts); 119 } 120 VAR(stage) += 1; 121 pthread_cond_broadcast(&cv); 122 pthread_mutex_unlock(&mtx); 123 } 124 else if (2 == index) 125 { 126 pthread_mutex_lock(&mtx); 127 while (VAR(stage) != 2) 128 pthread_cond_wait(&cv, &mtx); 129 pthread_mutex_unlock(&mtx); 130 pthread_cond_signal(&cv); 131 } 132 } 133 }; 134 135 136 137 138 struct test_pthread_condvar2 : rl::test_suite<test_pthread_condvar2, 2> 139 { 140 pthread_cond_t cv1, cv2; 141 pthread_mutex_t mtx1, mtx2; 142 VAR_T(int) stage; 143 beforetest_pthread_condvar2144 void before() 145 { 146 pthread_cond_init(&cv1, 0); 147 pthread_cond_init(&cv2, 0); 148 pthread_mutex_init(&mtx1, 0); 149 pthread_mutex_init(&mtx2, 0); 150 VAR(stage) = 0; 151 } 152 aftertest_pthread_condvar2153 void after() 154 { 155 pthread_cond_destroy(&cv1); 156 pthread_cond_destroy(&cv2); 157 pthread_mutex_destroy(&mtx1); 158 pthread_mutex_destroy(&mtx2); 159 } 160 threadtest_pthread_condvar2161 void thread(unsigned index) 162 { 163 if (0 == index) 164 { 165 pthread_mutex_lock(&mtx1); 166 int ts = 1; 167 pthread_cond_timedwait(&cv1, &mtx1, &ts); 168 pthread_mutex_unlock(&mtx1); 169 } 170 else if (1 == index) 171 { 172 pthread_mutex_lock(&mtx2); 173 int ts = 1; 174 pthread_cond_timedwait(&cv2, &mtx2, &ts); 175 pthread_mutex_unlock(&mtx2); 176 } 177 } 178 }; 179 180 181 182 183 struct test_pthread_rwlock : rl::test_suite<test_pthread_rwlock, 3> 184 { 185 pthread_rwlock_t mtx; 186 VAR_T(int) data; 187 beforetest_pthread_rwlock188 void before() 189 { 190 pthread_mutexattr_t attr; 191 pthread_mutexattr_init(&attr); 192 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); 193 pthread_rwlock_init(&mtx, &attr); 194 pthread_mutexattr_destroy(&attr); 195 VAR(data) = 0; 196 } 197 aftertest_pthread_rwlock198 void after() 199 { 200 pthread_rwlock_destroy(&mtx); 201 } 202 threadtest_pthread_rwlock203 void thread(unsigned /*index*/) 204 { 205 pthread_rwlock_wrlock(&mtx); 206 VAR(data) += 1; 207 pthread_rwlock_unlock(&mtx); 208 209 if (0 == pthread_rwlock_trywrlock(&mtx)) 210 { 211 VAR(data) += 1; 212 pthread_rwlock_unlock(&mtx); 213 } 214 215 pthread_rwlock_rdlock(&mtx); 216 (void)(int)VAR(data); 217 pthread_rwlock_unlock(&mtx); 218 219 if (0 == pthread_rwlock_tryrdlock(&mtx)) 220 { 221 (void)(int)VAR(data); 222 pthread_rwlock_unlock(&mtx); 223 } 224 } 225 }; 226 227 228 229 230 struct test_pthread_sem : rl::test_suite<test_pthread_sem, 2> 231 { 232 sem_t sem1, sem2; 233 VAR_T(int) data; 234 beforetest_pthread_sem235 void before() 236 { 237 sem_init(&sem1, 0, 0); 238 sem_init(&sem2, 0, 0); 239 VAR(data) = 0; 240 } 241 aftertest_pthread_sem242 void after() 243 { 244 sem_destroy(&sem1); 245 sem_destroy(&sem2); 246 } 247 threadtest_pthread_sem248 void thread(unsigned index) 249 { 250 if (index) 251 { 252 VAR(data) = 1; 253 sem_post(&sem1); 254 while (sem_trywait(&sem2)) 255 { 256 assert(errno == EINTR || errno == EAGAIN); 257 pthread_yield(); 258 } 259 RL_ASSERT(VAR(data) == 2); 260 VAR(data) = 3; 261 int count = -1; 262 sem_getvalue(&sem2, &count); 263 RL_ASSERT(count == 0); 264 sem_post(&sem2); 265 sem_getvalue(&sem2, &count); 266 RL_ASSERT(count == 1); 267 } 268 else 269 { 270 while (sem_wait(&sem1)) 271 assert(errno == EINTR); 272 RL_ASSERT(VAR(data) == 1); 273 VAR(data) = 2; 274 sem_post(&sem2); 275 } 276 } 277 }; 278 279 280 281 282