1 //===-- tsan_sync_test.cc -------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of ThreadSanitizer (TSan), a race detector. 11 // 12 //===----------------------------------------------------------------------===// 13 #include "tsan_sync.h" 14 #include "tsan_rtl.h" 15 #include "gtest/gtest.h" 16 17 namespace __tsan { 18 19 TEST(MetaMap, Basic) { 20 ThreadState *thr = cur_thread(); 21 MetaMap *m = &ctx->metamap; 22 u64 block[1] = {}; // fake malloc block 23 m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64)); 24 MBlock *mb = m->GetBlock((uptr)&block[0]); 25 EXPECT_NE(mb, (MBlock*)0); 26 EXPECT_EQ(mb->siz, 1 * sizeof(u64)); 27 EXPECT_EQ(mb->tid, thr->tid); 28 uptr sz = m->FreeBlock(thr, 0, (uptr)&block[0]); 29 EXPECT_EQ(sz, 1 * sizeof(u64)); 30 mb = m->GetBlock((uptr)&block[0]); 31 EXPECT_EQ(mb, (MBlock*)0); 32 } 33 34 TEST(MetaMap, FreeRange) { 35 ThreadState *thr = cur_thread(); 36 MetaMap *m = &ctx->metamap; 37 u64 block[4] = {}; // fake malloc block 38 m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64)); 39 m->AllocBlock(thr, 0, (uptr)&block[1], 3 * sizeof(u64)); 40 MBlock *mb1 = m->GetBlock((uptr)&block[0]); 41 EXPECT_EQ(mb1->siz, 1 * sizeof(u64)); 42 MBlock *mb2 = m->GetBlock((uptr)&block[1]); 43 EXPECT_EQ(mb2->siz, 3 * sizeof(u64)); 44 m->FreeRange(thr, 0, (uptr)&block[0], 4 * sizeof(u64)); 45 mb1 = m->GetBlock((uptr)&block[0]); 46 EXPECT_EQ(mb1, (MBlock*)0); 47 mb2 = m->GetBlock((uptr)&block[1]); 48 EXPECT_EQ(mb2, (MBlock*)0); 49 } 50 51 TEST(MetaMap, Sync) { 52 ThreadState *thr = cur_thread(); 53 MetaMap *m = &ctx->metamap; 54 u64 block[4] = {}; // fake malloc block 55 m->AllocBlock(thr, 0, (uptr)&block[0], 4 * sizeof(u64)); 56 SyncVar *s1 = m->GetIfExistsAndLock((uptr)&block[0]); 57 EXPECT_EQ(s1, (SyncVar*)0); 58 s1 = m->GetOrCreateAndLock(thr, 0, (uptr)&block[0], true); 59 EXPECT_NE(s1, (SyncVar*)0); 60 EXPECT_EQ(s1->addr, (uptr)&block[0]); 61 s1->mtx.Unlock(); 62 SyncVar *s2 = m->GetOrCreateAndLock(thr, 0, (uptr)&block[1], false); 63 EXPECT_NE(s2, (SyncVar*)0); 64 EXPECT_EQ(s2->addr, (uptr)&block[1]); 65 s2->mtx.ReadUnlock(); 66 m->FreeBlock(thr, 0, (uptr)&block[0]); 67 s1 = m->GetIfExistsAndLock((uptr)&block[0]); 68 EXPECT_EQ(s1, (SyncVar*)0); 69 s2 = m->GetIfExistsAndLock((uptr)&block[1]); 70 EXPECT_EQ(s2, (SyncVar*)0); 71 m->OnThreadIdle(thr); 72 } 73 74 TEST(MetaMap, MoveMemory) { 75 ThreadState *thr = cur_thread(); 76 MetaMap *m = &ctx->metamap; 77 u64 block1[4] = {}; // fake malloc block 78 u64 block2[4] = {}; // fake malloc block 79 m->AllocBlock(thr, 0, (uptr)&block1[0], 3 * sizeof(u64)); 80 m->AllocBlock(thr, 0, (uptr)&block1[3], 1 * sizeof(u64)); 81 SyncVar *s1 = m->GetOrCreateAndLock(thr, 0, (uptr)&block1[0], true); 82 s1->mtx.Unlock(); 83 SyncVar *s2 = m->GetOrCreateAndLock(thr, 0, (uptr)&block1[1], true); 84 s2->mtx.Unlock(); 85 m->MoveMemory((uptr)&block1[0], (uptr)&block2[0], 4 * sizeof(u64)); 86 MBlock *mb1 = m->GetBlock((uptr)&block1[0]); 87 EXPECT_EQ(mb1, (MBlock*)0); 88 MBlock *mb2 = m->GetBlock((uptr)&block1[3]); 89 EXPECT_EQ(mb2, (MBlock*)0); 90 mb1 = m->GetBlock((uptr)&block2[0]); 91 EXPECT_NE(mb1, (MBlock*)0); 92 EXPECT_EQ(mb1->siz, 3 * sizeof(u64)); 93 mb2 = m->GetBlock((uptr)&block2[3]); 94 EXPECT_NE(mb2, (MBlock*)0); 95 EXPECT_EQ(mb2->siz, 1 * sizeof(u64)); 96 s1 = m->GetIfExistsAndLock((uptr)&block1[0]); 97 EXPECT_EQ(s1, (SyncVar*)0); 98 s2 = m->GetIfExistsAndLock((uptr)&block1[1]); 99 EXPECT_EQ(s2, (SyncVar*)0); 100 s1 = m->GetIfExistsAndLock((uptr)&block2[0]); 101 EXPECT_NE(s1, (SyncVar*)0); 102 EXPECT_EQ(s1->addr, (uptr)&block2[0]); 103 s1->mtx.Unlock(); 104 s2 = m->GetIfExistsAndLock((uptr)&block2[1]); 105 EXPECT_NE(s2, (SyncVar*)0); 106 EXPECT_EQ(s2->addr, (uptr)&block2[1]); 107 s2->mtx.Unlock(); 108 m->FreeRange(thr, 0, (uptr)&block2[0], 4 * sizeof(u64)); 109 } 110 111 TEST(MetaMap, ResetSync) { 112 ThreadState *thr = cur_thread(); 113 MetaMap *m = &ctx->metamap; 114 u64 block[1] = {}; // fake malloc block 115 m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64)); 116 SyncVar *s = m->GetOrCreateAndLock(thr, 0, (uptr)&block[0], true); 117 s->Reset(thr); 118 s->mtx.Unlock(); 119 uptr sz = m->FreeBlock(thr, 0, (uptr)&block[0]); 120 EXPECT_EQ(sz, 1 * sizeof(u64)); 121 } 122 123 } // namespace __tsan 124