tsan_sync_test.cc revision 5d71de26cedae3dafc17449fe0182045c0bd20e8
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
17namespace __tsan {
18
19TEST(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
34TEST(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
51TEST(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
74TEST(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
111TEST(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