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
TEST(MetaMap,Basic)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
TEST(MetaMap,FreeRange)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
TEST(MetaMap,Sync)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
TEST(MetaMap,MoveMemory)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
TEST(MetaMap,ResetSync)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();
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