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->proc(), (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->proc(), (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], true);
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->proc(), (uptr)&block[0]);
67   s1 = m->GetIfExistsAndLock((uptr)&block[0], true);
68   EXPECT_EQ(s1, (SyncVar*)0);
69   s2 = m->GetIfExistsAndLock((uptr)&block[1], true);
70   EXPECT_EQ(s2, (SyncVar*)0);
71   m->OnProcIdle(thr->proc());
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], true);
97   EXPECT_EQ(s1, (SyncVar*)0);
98   s2 = m->GetIfExistsAndLock((uptr)&block1[1], true);
99   EXPECT_EQ(s2, (SyncVar*)0);
100   s1 = m->GetIfExistsAndLock((uptr)&block2[0], true);
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], true);
105   EXPECT_NE(s2, (SyncVar*)0);
106   EXPECT_EQ(s2->addr, (uptr)&block2[1]);
107   s2->mtx.Unlock();
108   m->FreeRange(thr->proc(), (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(thr->proc());
118   s->mtx.Unlock();
119   uptr sz = m->FreeBlock(thr->proc(), (uptr)&block[0]);
120   EXPECT_EQ(sz, 1 * sizeof(u64));
121 }
122 
123 }  // namespace __tsan
124