1 //===-- tsan_clock_test.cpp -----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of ThreadSanitizer (TSan), a race detector. 10 // 11 //===----------------------------------------------------------------------===// 12 #include "tsan_vector_clock.h" 13 14 #include "gtest/gtest.h" 15 #include "tsan_rtl.h" 16 17 namespace __tsan { 18 19 TEST(VectorClock, GetSet) { 20 // Compiler won't ensure alignment on stack. 21 VectorClock *vc = New<VectorClock>(); 22 for (uptr i = 0; i < kThreadSlotCount; i++) 23 ASSERT_EQ(vc->Get(static_cast<Sid>(i)), kEpochZero); 24 for (uptr i = 0; i < kThreadSlotCount; i++) 25 vc->Set(static_cast<Sid>(i), static_cast<Epoch>(i)); 26 for (uptr i = 0; i < kThreadSlotCount; i++) 27 ASSERT_EQ(vc->Get(static_cast<Sid>(i)), static_cast<Epoch>(i)); 28 vc->Reset(); 29 for (uptr i = 0; i < kThreadSlotCount; i++) 30 ASSERT_EQ(vc->Get(static_cast<Sid>(i)), kEpochZero); 31 DestroyAndFree(vc); 32 } 33 34 TEST(VectorClock, VectorOps) { 35 VectorClock *vc1 = New<VectorClock>(); 36 VectorClock *vc2 = nullptr; 37 VectorClock *vc3 = nullptr; 38 39 vc1->Acquire(vc2); 40 for (uptr i = 0; i < kThreadSlotCount; i++) 41 ASSERT_EQ(vc1->Get(static_cast<Sid>(i)), kEpochZero); 42 vc1->Release(&vc2); 43 EXPECT_NE(vc2, nullptr); 44 vc1->Acquire(vc2); 45 for (uptr i = 0; i < kThreadSlotCount; i++) 46 ASSERT_EQ(vc1->Get(static_cast<Sid>(i)), kEpochZero); 47 48 for (uptr i = 0; i < kThreadSlotCount; i++) { 49 vc1->Set(static_cast<Sid>(i), static_cast<Epoch>(i)); 50 vc2->Set(static_cast<Sid>(i), static_cast<Epoch>(kThreadSlotCount - i)); 51 } 52 vc1->Acquire(vc2); 53 for (uptr i = 0; i < kThreadSlotCount; i++) { 54 ASSERT_EQ(vc1->Get(static_cast<Sid>(i)), 55 static_cast<Epoch>(i < kThreadSlotCount / 2 ? kThreadSlotCount - i 56 : i)); 57 ASSERT_EQ(vc2->Get(static_cast<Sid>(i)), 58 static_cast<Epoch>(kThreadSlotCount - i)); 59 } 60 vc2->ReleaseStore(&vc3); 61 for (uptr i = 0; i < kThreadSlotCount; i++) { 62 ASSERT_EQ(vc3->Get(static_cast<Sid>(i)), 63 static_cast<Epoch>(kThreadSlotCount - i)); 64 ASSERT_EQ(vc2->Get(static_cast<Sid>(i)), 65 static_cast<Epoch>(kThreadSlotCount - i)); 66 } 67 68 vc1->Reset(); 69 vc2->Reset(); 70 for (uptr i = 0; i < kThreadSlotCount; i++) { 71 vc1->Set(static_cast<Sid>(i), static_cast<Epoch>(i)); 72 vc2->Set(static_cast<Sid>(i), static_cast<Epoch>(kThreadSlotCount - i)); 73 } 74 vc1->ReleaseAcquire(&vc2); 75 for (uptr i = 0; i < kThreadSlotCount; i++) { 76 Epoch expect = 77 static_cast<Epoch>(i < kThreadSlotCount / 2 ? kThreadSlotCount - i : i); 78 ASSERT_EQ(vc1->Get(static_cast<Sid>(i)), expect); 79 ASSERT_EQ(vc2->Get(static_cast<Sid>(i)), expect); 80 } 81 82 vc1->Reset(); 83 vc2->Reset(); 84 for (uptr i = 0; i < kThreadSlotCount; i++) { 85 vc1->Set(static_cast<Sid>(i), static_cast<Epoch>(i)); 86 vc2->Set(static_cast<Sid>(i), static_cast<Epoch>(kThreadSlotCount - i)); 87 } 88 vc1->ReleaseStoreAcquire(&vc2); 89 for (uptr i = 0; i < kThreadSlotCount; i++) { 90 ASSERT_EQ(vc1->Get(static_cast<Sid>(i)), 91 static_cast<Epoch>(i < kThreadSlotCount / 2 ? kThreadSlotCount - i 92 : i)); 93 ASSERT_EQ(vc2->Get(static_cast<Sid>(i)), static_cast<Epoch>(i)); 94 } 95 96 DestroyAndFree(vc1); 97 DestroyAndFree(vc2); 98 DestroyAndFree(vc3); 99 } 100 101 } // namespace __tsan 102