xref: /openbsd-src/gnu/llvm/compiler-rt/lib/tsan/tests/unit/tsan_sync_test.cpp (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
1 //===-- tsan_sync_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_sync.h"
13 #include "tsan_rtl.h"
14 #include "gtest/gtest.h"
15 
16 namespace __tsan {
17 
18 TEST(MetaMap, Basic) {
19   ThreadState *thr = cur_thread();
20   MetaMap *m = &ctx->metamap;
21   u64 block[1] = {};  // fake malloc block
22   m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
23   MBlock *mb = m->GetBlock((uptr)&block[0]);
24   EXPECT_NE(mb, (MBlock*)0);
25   EXPECT_EQ(mb->siz, 1 * sizeof(u64));
26   EXPECT_EQ(mb->tid, thr->tid);
27   uptr sz = m->FreeBlock(thr->proc(), (uptr)&block[0]);
28   EXPECT_EQ(sz, 1 * sizeof(u64));
29   mb = m->GetBlock((uptr)&block[0]);
30   EXPECT_EQ(mb, (MBlock*)0);
31 }
32 
33 TEST(MetaMap, FreeRange) {
34   ThreadState *thr = cur_thread();
35   MetaMap *m = &ctx->metamap;
36   u64 block[4] = {};  // fake malloc block
37   m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
38   m->AllocBlock(thr, 0, (uptr)&block[1], 3 * sizeof(u64));
39   MBlock *mb1 = m->GetBlock((uptr)&block[0]);
40   EXPECT_EQ(mb1->siz, 1 * sizeof(u64));
41   MBlock *mb2 = m->GetBlock((uptr)&block[1]);
42   EXPECT_EQ(mb2->siz, 3 * sizeof(u64));
43   m->FreeRange(thr->proc(), (uptr)&block[0], 4 * sizeof(u64));
44   mb1 = m->GetBlock((uptr)&block[0]);
45   EXPECT_EQ(mb1, (MBlock*)0);
46   mb2 = m->GetBlock((uptr)&block[1]);
47   EXPECT_EQ(mb2, (MBlock*)0);
48 }
49 
50 TEST(MetaMap, Sync) {
51   ThreadState *thr = cur_thread();
52   MetaMap *m = &ctx->metamap;
53   u64 block[4] = {};  // fake malloc block
54   m->AllocBlock(thr, 0, (uptr)&block[0], 4 * sizeof(u64));
55   SyncVar *s1 = m->GetIfExistsAndLock((uptr)&block[0], true);
56   EXPECT_EQ(s1, (SyncVar*)0);
57   s1 = m->GetOrCreateAndLock(thr, 0, (uptr)&block[0], true);
58   EXPECT_NE(s1, (SyncVar*)0);
59   EXPECT_EQ(s1->addr, (uptr)&block[0]);
60   s1->mtx.Unlock();
61   SyncVar *s2 = m->GetOrCreateAndLock(thr, 0, (uptr)&block[1], false);
62   EXPECT_NE(s2, (SyncVar*)0);
63   EXPECT_EQ(s2->addr, (uptr)&block[1]);
64   s2->mtx.ReadUnlock();
65   m->FreeBlock(thr->proc(), (uptr)&block[0]);
66   s1 = m->GetIfExistsAndLock((uptr)&block[0], true);
67   EXPECT_EQ(s1, (SyncVar*)0);
68   s2 = m->GetIfExistsAndLock((uptr)&block[1], true);
69   EXPECT_EQ(s2, (SyncVar*)0);
70   m->OnProcIdle(thr->proc());
71 }
72 
73 TEST(MetaMap, MoveMemory) {
74   ThreadState *thr = cur_thread();
75   MetaMap *m = &ctx->metamap;
76   u64 block1[4] = {};  // fake malloc block
77   u64 block2[4] = {};  // fake malloc block
78   m->AllocBlock(thr, 0, (uptr)&block1[0], 3 * sizeof(u64));
79   m->AllocBlock(thr, 0, (uptr)&block1[3], 1 * sizeof(u64));
80   SyncVar *s1 = m->GetOrCreateAndLock(thr, 0, (uptr)&block1[0], true);
81   s1->mtx.Unlock();
82   SyncVar *s2 = m->GetOrCreateAndLock(thr, 0, (uptr)&block1[1], true);
83   s2->mtx.Unlock();
84   m->MoveMemory((uptr)&block1[0], (uptr)&block2[0], 4 * sizeof(u64));
85   MBlock *mb1 = m->GetBlock((uptr)&block1[0]);
86   EXPECT_EQ(mb1, (MBlock*)0);
87   MBlock *mb2 = m->GetBlock((uptr)&block1[3]);
88   EXPECT_EQ(mb2, (MBlock*)0);
89   mb1 = m->GetBlock((uptr)&block2[0]);
90   EXPECT_NE(mb1, (MBlock*)0);
91   EXPECT_EQ(mb1->siz, 3 * sizeof(u64));
92   mb2 = m->GetBlock((uptr)&block2[3]);
93   EXPECT_NE(mb2, (MBlock*)0);
94   EXPECT_EQ(mb2->siz, 1 * sizeof(u64));
95   s1 = m->GetIfExistsAndLock((uptr)&block1[0], true);
96   EXPECT_EQ(s1, (SyncVar*)0);
97   s2 = m->GetIfExistsAndLock((uptr)&block1[1], true);
98   EXPECT_EQ(s2, (SyncVar*)0);
99   s1 = m->GetIfExistsAndLock((uptr)&block2[0], true);
100   EXPECT_NE(s1, (SyncVar*)0);
101   EXPECT_EQ(s1->addr, (uptr)&block2[0]);
102   s1->mtx.Unlock();
103   s2 = m->GetIfExistsAndLock((uptr)&block2[1], true);
104   EXPECT_NE(s2, (SyncVar*)0);
105   EXPECT_EQ(s2->addr, (uptr)&block2[1]);
106   s2->mtx.Unlock();
107   m->FreeRange(thr->proc(), (uptr)&block2[0], 4 * sizeof(u64));
108 }
109 
110 TEST(MetaMap, ResetSync) {
111   ThreadState *thr = cur_thread();
112   MetaMap *m = &ctx->metamap;
113   u64 block[1] = {};  // fake malloc block
114   m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
115   SyncVar *s = m->GetOrCreateAndLock(thr, 0, (uptr)&block[0], true);
116   s->Reset(thr->proc());
117   s->mtx.Unlock();
118   uptr sz = m->FreeBlock(thr->proc(), (uptr)&block[0]);
119   EXPECT_EQ(sz, 1 * sizeof(u64));
120 }
121 
122 }  // namespace __tsan
123