| //===-- tsan_sync_test.cc -------------------------------------------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file is a part of ThreadSanitizer (TSan), a race detector. |
| // |
| //===----------------------------------------------------------------------===// |
| #include "tsan_sync.h" |
| #include "tsan_rtl.h" |
| #include "tsan_mman.h" |
| #include "gtest/gtest.h" |
| |
| #include <stdlib.h> |
| #include <stdint.h> |
| #include <map> |
| |
| namespace __tsan { |
| |
| TEST(Sync, Table) { |
| const uintptr_t kIters = 512*1024; |
| const uintptr_t kRange = 10000; |
| |
| ScopedInRtl in_rtl; |
| ThreadState *thr = cur_thread(); |
| uptr pc = 0; |
| |
| SyncTab tab; |
| SyncVar *golden[kRange] = {}; |
| unsigned seed = 0; |
| for (uintptr_t i = 0; i < kIters; i++) { |
| uintptr_t addr = rand_r(&seed) % (kRange - 1) + 1; |
| if (rand_r(&seed) % 2) { |
| // Get or add. |
| SyncVar *v = tab.GetOrCreateAndLock(thr, pc, addr, true); |
| EXPECT_TRUE(golden[addr] == 0 || golden[addr] == v); |
| EXPECT_EQ(v->addr, addr); |
| golden[addr] = v; |
| v->mtx.Unlock(); |
| } else { |
| // Remove. |
| SyncVar *v = tab.GetAndRemove(thr, pc, addr); |
| EXPECT_EQ(golden[addr], v); |
| if (v) { |
| EXPECT_EQ(v->addr, addr); |
| golden[addr] = 0; |
| DestroyAndFree(v); |
| } |
| } |
| } |
| for (uintptr_t addr = 0; addr < kRange; addr++) { |
| if (golden[addr] == 0) |
| continue; |
| SyncVar *v = tab.GetAndRemove(thr, pc, addr); |
| EXPECT_EQ(v, golden[addr]); |
| EXPECT_EQ(v->addr, addr); |
| DestroyAndFree(v); |
| } |
| } |
| |
| } // namespace __tsan |