1 //===-- tsan_sync_test.cpp ------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is a part of ThreadSanitizer (TSan), a race detector.
11 //===----------------------------------------------------------------------===//
12 #include "tsan_sync.h"
14 #include "gtest/gtest.h"
18 TEST(MetaMap
, Basic
) {
19 ThreadState
*thr
= cur_thread();
20 SlotLocker
locker(thr
);
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 CHECK_NE(mb
, (MBlock
*)0);
26 CHECK_EQ(mb
->siz
, 1 * sizeof(u64
));
27 CHECK_EQ(mb
->tid
, thr
->tid
);
28 uptr sz
= m
->FreeBlock(thr
->proc(), (uptr
)&block
[0], true);
29 CHECK_EQ(sz
, 1 * sizeof(u64
));
30 mb
= m
->GetBlock((uptr
)&block
[0]);
31 CHECK_EQ(mb
, (MBlock
*)0);
34 TEST(MetaMap
, FreeRange
) {
35 ThreadState
*thr
= cur_thread();
36 SlotLocker
locker(thr
);
37 MetaMap
*m
= &ctx
->metamap
;
38 u64 block
[4] = {}; // fake malloc block
39 m
->AllocBlock(thr
, 0, (uptr
)&block
[0], 1 * sizeof(u64
));
40 m
->AllocBlock(thr
, 0, (uptr
)&block
[1], 3 * sizeof(u64
));
41 MBlock
*mb1
= m
->GetBlock((uptr
)&block
[0]);
42 CHECK_EQ(mb1
->siz
, 1 * sizeof(u64
));
43 MBlock
*mb2
= m
->GetBlock((uptr
)&block
[1]);
44 CHECK_EQ(mb2
->siz
, 3 * sizeof(u64
));
45 m
->FreeRange(thr
->proc(), (uptr
)&block
[0], 4 * sizeof(u64
), true);
46 mb1
= m
->GetBlock((uptr
)&block
[0]);
47 CHECK_EQ(mb1
, (MBlock
*)0);
48 mb2
= m
->GetBlock((uptr
)&block
[1]);
49 CHECK_EQ(mb2
, (MBlock
*)0);
53 // CHECK can call memset/etc. Disable interceptors to prevent
54 // them from detecting that we exit runtime with mutexes held.
55 ScopedIgnoreInterceptors ignore
;
56 ThreadState
*thr
= cur_thread();
57 SlotLocker
locker(thr
);
58 MetaMap
*m
= &ctx
->metamap
;
59 u64 block
[4] = {}; // fake malloc block
60 m
->AllocBlock(thr
, 0, (uptr
)&block
[0], 4 * sizeof(u64
));
61 SyncVar
*s1
= m
->GetSyncIfExists((uptr
)&block
[0]);
62 CHECK_EQ(s1
, (SyncVar
*)0);
63 s1
= m
->GetSyncOrCreate(thr
, 0, (uptr
)&block
[0], false);
64 CHECK_NE(s1
, (SyncVar
*)0);
65 CHECK_EQ(s1
->addr
, (uptr
)&block
[0]);
66 SyncVar
*s2
= m
->GetSyncOrCreate(thr
, 0, (uptr
)&block
[1], false);
67 CHECK_NE(s2
, (SyncVar
*)0);
68 CHECK_EQ(s2
->addr
, (uptr
)&block
[1]);
69 m
->FreeBlock(thr
->proc(), (uptr
)&block
[0], true);
70 s1
= m
->GetSyncIfExists((uptr
)&block
[0]);
71 CHECK_EQ(s1
, (SyncVar
*)0);
72 s2
= m
->GetSyncIfExists((uptr
)&block
[1]);
73 CHECK_EQ(s2
, (SyncVar
*)0);
74 m
->OnProcIdle(thr
->proc());
77 TEST(MetaMap
, MoveMemory
) {
78 ScopedIgnoreInterceptors ignore
;
79 ThreadState
*thr
= cur_thread();
80 SlotLocker
locker(thr
);
81 MetaMap
*m
= &ctx
->metamap
;
82 u64 block1
[4] = {}; // fake malloc block
83 u64 block2
[4] = {}; // fake malloc block
84 m
->AllocBlock(thr
, 0, (uptr
)&block1
[0], 3 * sizeof(u64
));
85 m
->AllocBlock(thr
, 0, (uptr
)&block1
[3], 1 * sizeof(u64
));
86 SyncVar
*s1
= m
->GetSyncOrCreate(thr
, 0, (uptr
)&block1
[0], false);
87 SyncVar
*s2
= m
->GetSyncOrCreate(thr
, 0, (uptr
)&block1
[1], false);
88 m
->MoveMemory((uptr
)&block1
[0], (uptr
)&block2
[0], 4 * sizeof(u64
));
89 MBlock
*mb1
= m
->GetBlock((uptr
)&block1
[0]);
90 CHECK_EQ(mb1
, (MBlock
*)0);
91 MBlock
*mb2
= m
->GetBlock((uptr
)&block1
[3]);
92 CHECK_EQ(mb2
, (MBlock
*)0);
93 mb1
= m
->GetBlock((uptr
)&block2
[0]);
94 CHECK_NE(mb1
, (MBlock
*)0);
95 CHECK_EQ(mb1
->siz
, 3 * sizeof(u64
));
96 mb2
= m
->GetBlock((uptr
)&block2
[3]);
97 CHECK_NE(mb2
, (MBlock
*)0);
98 CHECK_EQ(mb2
->siz
, 1 * sizeof(u64
));
99 s1
= m
->GetSyncIfExists((uptr
)&block1
[0]);
100 CHECK_EQ(s1
, (SyncVar
*)0);
101 s2
= m
->GetSyncIfExists((uptr
)&block1
[1]);
102 CHECK_EQ(s2
, (SyncVar
*)0);
103 s1
= m
->GetSyncIfExists((uptr
)&block2
[0]);
104 CHECK_NE(s1
, (SyncVar
*)0);
105 CHECK_EQ(s1
->addr
, (uptr
)&block2
[0]);
106 s2
= m
->GetSyncIfExists((uptr
)&block2
[1]);
107 CHECK_NE(s2
, (SyncVar
*)0);
108 CHECK_EQ(s2
->addr
, (uptr
)&block2
[1]);
109 m
->FreeRange(thr
->proc(), (uptr
)&block2
[0], 4 * sizeof(u64
), true);
112 TEST(MetaMap
, ResetSync
) {
113 ScopedIgnoreInterceptors ignore
;
114 ThreadState
*thr
= cur_thread();
115 SlotLocker
locker(thr
);
116 MetaMap
*m
= &ctx
->metamap
;
117 u64 block
[1] = {}; // fake malloc block
118 m
->AllocBlock(thr
, 0, (uptr
)&block
[0], 1 * sizeof(u64
));
119 SyncVar
*s
= m
->GetSyncOrCreate(thr
, 0, (uptr
)&block
[0], false);
121 uptr sz
= m
->FreeBlock(thr
->proc(), (uptr
)&block
[0], true);
122 CHECK_EQ(sz
, 1 * sizeof(u64
));
125 } // namespace __tsan