| 203 | |
| 204 | template<typename T> |
| 205 | static void AcquireReleaseThreadB(T id, T other_id, int iters, AtomicInt<T>* control, |
| 206 | T* payload) { |
| 207 | const int DELAY = 100; |
| 208 | for (int it = 0; it < iters; ++it) { |
| 209 | T p; |
| 210 | // Phase 1 |
| 211 | // Wait until ThreadA signaled that payload was updated. |
| 212 | while (control->Load() != id); |
| 213 | // (B-1) This load is not allowed to reorder with the above "load acquire". |
| 214 | p = *payload; |
| 215 | // Verify ordering for both (A-1) and (B-1). |
| 216 | EXPECT_EQ(it, p); |
| 217 | |
| 218 | // Phase 2 |
| 219 | // Payload should not change until we give ThreadA the go-ahead. |
| 220 | for (int i = 0; i < DELAY; ++i) { |
| 221 | AtomicUtil::CompilerBarrier(); |
| 222 | // (B-2) This load is not allowed to reorder with the below "store release". |
| 223 | p = *payload; |
| 224 | } |
| 225 | control->Store(other_id); |
| 226 | // Verify ordering for both (A-2) and (B-2). |
| 227 | EXPECT_EQ(it, p); |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | // Test "acquire" and "release" memory ordering semantics. There are two threads, A and |
| 232 | // B, and each execute phase 1 and phase 2 in lockstep to verify the various |