1 #pragma once 2 3 #include "../relacy/relacy_std.hpp" 4 5 6 7 struct test_mutex : rl::test_suite<test_mutex, 3> 8 { 9 rl::mutex mtx; 10 rl::var<int> data; 11 beforetest_mutex12 void before() 13 { 14 data($) = 0; 15 } 16 aftertest_mutex17 void after() 18 { 19 RL_ASSERT(data($) == 3); 20 } 21 threadtest_mutex22 void thread(unsigned /*index*/) 23 { 24 mtx.lock($); 25 data($) += 1; 26 mtx.unlock($); 27 } 28 }; 29 30 31 32 33 struct test_deadlock : rl::test_suite<test_deadlock, 2, rl::test_result_deadlock> 34 { 35 rl::mutex mtx1; 36 rl::mutex mtx2; 37 threadtest_deadlock38 void thread(unsigned index) 39 { 40 if (0 == index) 41 { 42 mtx1.lock($); 43 mtx2.lock($); 44 mtx1.unlock($); 45 mtx2.unlock($); 46 } 47 else 48 { 49 mtx2.lock($); 50 mtx1.lock($); 51 mtx1.unlock($); 52 mtx2.unlock($); 53 } 54 } 55 }; 56 57 58 59 struct test_deadlock2 : rl::test_suite<test_deadlock2, 2, rl::test_result_deadlock> 60 { 61 std::mutex m; 62 std::atomic<int> f; 63 beforetest_deadlock264 void before() 65 { 66 f($) = 0; 67 } 68 threadtest_deadlock269 void thread(unsigned index) 70 { 71 if (index) 72 { 73 m.lock($); 74 f($) = 1; 75 for (int i = 0; i != 100; ++i) 76 rl::yield(1, $); 77 } 78 else 79 { 80 while (0 == f($)) 81 rl::yield(1, $); 82 m.lock($); 83 } 84 } 85 }; 86 87 88 89 struct test_mutex_destuction : rl::test_suite<test_mutex_destuction, 1, rl::test_result_destroying_owned_mutex> 90 { threadtest_mutex_destuction91 void thread(unsigned) 92 { 93 std::mutex* m = new std::mutex; 94 m->lock($); 95 delete m; 96 } 97 }; 98 99 100 struct test_mutex_destuction2 : rl::test_suite<test_mutex_destuction2, 2, rl::test_result_destroying_owned_mutex> 101 { 102 std::mutex* m; 103 std::atomic<int> f; 104 beforetest_mutex_destuction2105 void before() 106 { 107 m = new std::mutex; 108 f($) = 0; 109 } 110 threadtest_mutex_destuction2111 void thread(unsigned index) 112 { 113 if (0 == index) 114 { 115 m->lock($); 116 f($) = 1; 117 while (1 == f($)) 118 rl::yield(1, $); 119 m->unlock($); 120 } 121 else 122 { 123 while (0 == f($)) 124 rl::yield(1, $); 125 delete m; 126 f($) = 2; 127 } 128 } 129 }; 130 131 132 struct test_mutex_recursion : rl::test_suite<test_mutex_recursion, 2> 133 { 134 std::recursive_mutex mtx; 135 rl::var<int> data; 136 beforetest_mutex_recursion137 void before() 138 { 139 data($) = 0; 140 } 141 aftertest_mutex_recursion142 void after() 143 { 144 RL_ASSERT(data($) == 2); 145 } 146 threadtest_mutex_recursion147 void thread(unsigned /*index*/) 148 { 149 mtx.lock($); 150 mtx.lock($); 151 data($) += 1; 152 mtx.unlock($); 153 mtx.unlock($); 154 } 155 }; 156 157 158 159 struct test_mutex_try_lock : rl::test_suite<test_mutex_try_lock, 2> 160 { 161 std::recursive_mutex mtx; 162 rl::var<int> data; 163 beforetest_mutex_try_lock164 void before() 165 { 166 data($) = 0; 167 } 168 aftertest_mutex_try_lock169 void after() 170 { 171 RL_ASSERT(data($) == 2); 172 } 173 threadtest_mutex_try_lock174 void thread(unsigned /*index*/) 175 { 176 while (false == mtx.try_lock($)) 177 rl::yield(1, $); 178 RL_ASSERT(mtx.try_lock($)); 179 data($) += 1; 180 mtx.unlock($); 181 mtx.unlock($); 182 } 183 }; 184 185 186 187 struct test_mutex_recursion_error : rl::test_suite<test_mutex_recursion_error, 1, rl::test_result_recursion_on_nonrecursive_mutex> 188 { threadtest_mutex_recursion_error189 void thread(unsigned) 190 { 191 std::mutex m; 192 m.lock($); 193 m.lock($); 194 } 195 }; 196 197 198 199 struct test_mutex_unlock_error : rl::test_suite<test_mutex_unlock_error, 1, rl::test_result_unlocking_mutex_wo_ownership> 200 { threadtest_mutex_unlock_error201 void thread(unsigned) 202 { 203 std::mutex m; 204 m.lock($); 205 m.unlock($); 206 m.unlock($); 207 } 208 }; 209 210 211 struct test_mutex_leak : rl::test_suite<test_mutex_leak, 1, rl::test_result_resource_leak> 212 { threadtest_mutex_leak213 void thread(unsigned) 214 { 215 char* p = new char [sizeof(std::mutex)]; 216 new (p) std::mutex(); 217 delete [] p; 218 } 219 }; 220 221 222