xref: /llvm-project/compiler-rt/lib/tsan/tests/unit/tsan_sync_test.cpp (revision b332134921b42796c6b46453eaf2affdc09e3154)
15de29a4bSNico Weber //===-- tsan_sync_test.cpp ------------------------------------------------===//
25de29a4bSNico Weber //
35de29a4bSNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45de29a4bSNico Weber // See https://llvm.org/LICENSE.txt for license information.
55de29a4bSNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65de29a4bSNico Weber //
75de29a4bSNico Weber //===----------------------------------------------------------------------===//
85de29a4bSNico Weber //
95de29a4bSNico Weber // This file is a part of ThreadSanitizer (TSan), a race detector.
105de29a4bSNico Weber //
115de29a4bSNico Weber //===----------------------------------------------------------------------===//
125de29a4bSNico Weber #include "tsan_sync.h"
135de29a4bSNico Weber #include "tsan_rtl.h"
145de29a4bSNico Weber #include "gtest/gtest.h"
155de29a4bSNico Weber 
165de29a4bSNico Weber namespace __tsan {
175de29a4bSNico Weber 
TEST(MetaMap,Basic)185de29a4bSNico Weber TEST(MetaMap, Basic) {
195de29a4bSNico Weber   ThreadState *thr = cur_thread();
20*b3321349SDmitry Vyukov   SlotLocker locker(thr);
215de29a4bSNico Weber   MetaMap *m = &ctx->metamap;
225de29a4bSNico Weber   u64 block[1] = {};  // fake malloc block
235de29a4bSNico Weber   m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
245de29a4bSNico Weber   MBlock *mb = m->GetBlock((uptr)&block[0]);
25f50cee2fSDmitry Vyukov   CHECK_NE(mb, (MBlock *)0);
26f50cee2fSDmitry Vyukov   CHECK_EQ(mb->siz, 1 * sizeof(u64));
27f50cee2fSDmitry Vyukov   CHECK_EQ(mb->tid, thr->tid);
28*b3321349SDmitry Vyukov   uptr sz = m->FreeBlock(thr->proc(), (uptr)&block[0], true);
29f50cee2fSDmitry Vyukov   CHECK_EQ(sz, 1 * sizeof(u64));
305de29a4bSNico Weber   mb = m->GetBlock((uptr)&block[0]);
31f50cee2fSDmitry Vyukov   CHECK_EQ(mb, (MBlock *)0);
325de29a4bSNico Weber }
335de29a4bSNico Weber 
TEST(MetaMap,FreeRange)345de29a4bSNico Weber TEST(MetaMap, FreeRange) {
355de29a4bSNico Weber   ThreadState *thr = cur_thread();
36*b3321349SDmitry Vyukov   SlotLocker locker(thr);
375de29a4bSNico Weber   MetaMap *m = &ctx->metamap;
385de29a4bSNico Weber   u64 block[4] = {};  // fake malloc block
395de29a4bSNico Weber   m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
405de29a4bSNico Weber   m->AllocBlock(thr, 0, (uptr)&block[1], 3 * sizeof(u64));
415de29a4bSNico Weber   MBlock *mb1 = m->GetBlock((uptr)&block[0]);
42f50cee2fSDmitry Vyukov   CHECK_EQ(mb1->siz, 1 * sizeof(u64));
435de29a4bSNico Weber   MBlock *mb2 = m->GetBlock((uptr)&block[1]);
44f50cee2fSDmitry Vyukov   CHECK_EQ(mb2->siz, 3 * sizeof(u64));
45*b3321349SDmitry Vyukov   m->FreeRange(thr->proc(), (uptr)&block[0], 4 * sizeof(u64), true);
465de29a4bSNico Weber   mb1 = m->GetBlock((uptr)&block[0]);
47f50cee2fSDmitry Vyukov   CHECK_EQ(mb1, (MBlock *)0);
485de29a4bSNico Weber   mb2 = m->GetBlock((uptr)&block[1]);
49f50cee2fSDmitry Vyukov   CHECK_EQ(mb2, (MBlock *)0);
505de29a4bSNico Weber }
515de29a4bSNico Weber 
TEST(MetaMap,Sync)529e3e97aaSDmitry Vyukov TEST(MetaMap, Sync) {
53f50cee2fSDmitry Vyukov   // CHECK can call memset/etc. Disable interceptors to prevent
543c92eb44SDmitry Vyukov   // them from detecting that we exit runtime with mutexes held.
553c92eb44SDmitry Vyukov   ScopedIgnoreInterceptors ignore;
565de29a4bSNico Weber   ThreadState *thr = cur_thread();
57*b3321349SDmitry Vyukov   SlotLocker locker(thr);
585de29a4bSNico Weber   MetaMap *m = &ctx->metamap;
595de29a4bSNico Weber   u64 block[4] = {};  // fake malloc block
605de29a4bSNico Weber   m->AllocBlock(thr, 0, (uptr)&block[0], 4 * sizeof(u64));
619e3e97aaSDmitry Vyukov   SyncVar *s1 = m->GetSyncIfExists((uptr)&block[0]);
62f50cee2fSDmitry Vyukov   CHECK_EQ(s1, (SyncVar *)0);
637bd81fe1SDmitry Vyukov   s1 = m->GetSyncOrCreate(thr, 0, (uptr)&block[0], false);
64f50cee2fSDmitry Vyukov   CHECK_NE(s1, (SyncVar *)0);
65f50cee2fSDmitry Vyukov   CHECK_EQ(s1->addr, (uptr)&block[0]);
667bd81fe1SDmitry Vyukov   SyncVar *s2 = m->GetSyncOrCreate(thr, 0, (uptr)&block[1], false);
67f50cee2fSDmitry Vyukov   CHECK_NE(s2, (SyncVar *)0);
68f50cee2fSDmitry Vyukov   CHECK_EQ(s2->addr, (uptr)&block[1]);
69*b3321349SDmitry Vyukov   m->FreeBlock(thr->proc(), (uptr)&block[0], true);
709e3e97aaSDmitry Vyukov   s1 = m->GetSyncIfExists((uptr)&block[0]);
71f50cee2fSDmitry Vyukov   CHECK_EQ(s1, (SyncVar *)0);
729e3e97aaSDmitry Vyukov   s2 = m->GetSyncIfExists((uptr)&block[1]);
73f50cee2fSDmitry Vyukov   CHECK_EQ(s2, (SyncVar *)0);
745de29a4bSNico Weber   m->OnProcIdle(thr->proc());
755de29a4bSNico Weber }
765de29a4bSNico Weber 
TEST(MetaMap,MoveMemory)779e3e97aaSDmitry Vyukov TEST(MetaMap, MoveMemory) {
783c92eb44SDmitry Vyukov   ScopedIgnoreInterceptors ignore;
795de29a4bSNico Weber   ThreadState *thr = cur_thread();
80*b3321349SDmitry Vyukov   SlotLocker locker(thr);
815de29a4bSNico Weber   MetaMap *m = &ctx->metamap;
825de29a4bSNico Weber   u64 block1[4] = {};  // fake malloc block
835de29a4bSNico Weber   u64 block2[4] = {};  // fake malloc block
845de29a4bSNico Weber   m->AllocBlock(thr, 0, (uptr)&block1[0], 3 * sizeof(u64));
855de29a4bSNico Weber   m->AllocBlock(thr, 0, (uptr)&block1[3], 1 * sizeof(u64));
867bd81fe1SDmitry Vyukov   SyncVar *s1 = m->GetSyncOrCreate(thr, 0, (uptr)&block1[0], false);
877bd81fe1SDmitry Vyukov   SyncVar *s2 = m->GetSyncOrCreate(thr, 0, (uptr)&block1[1], false);
885de29a4bSNico Weber   m->MoveMemory((uptr)&block1[0], (uptr)&block2[0], 4 * sizeof(u64));
895de29a4bSNico Weber   MBlock *mb1 = m->GetBlock((uptr)&block1[0]);
90f50cee2fSDmitry Vyukov   CHECK_EQ(mb1, (MBlock *)0);
915de29a4bSNico Weber   MBlock *mb2 = m->GetBlock((uptr)&block1[3]);
92f50cee2fSDmitry Vyukov   CHECK_EQ(mb2, (MBlock *)0);
935de29a4bSNico Weber   mb1 = m->GetBlock((uptr)&block2[0]);
94f50cee2fSDmitry Vyukov   CHECK_NE(mb1, (MBlock *)0);
95f50cee2fSDmitry Vyukov   CHECK_EQ(mb1->siz, 3 * sizeof(u64));
965de29a4bSNico Weber   mb2 = m->GetBlock((uptr)&block2[3]);
97f50cee2fSDmitry Vyukov   CHECK_NE(mb2, (MBlock *)0);
98f50cee2fSDmitry Vyukov   CHECK_EQ(mb2->siz, 1 * sizeof(u64));
999e3e97aaSDmitry Vyukov   s1 = m->GetSyncIfExists((uptr)&block1[0]);
100f50cee2fSDmitry Vyukov   CHECK_EQ(s1, (SyncVar *)0);
1019e3e97aaSDmitry Vyukov   s2 = m->GetSyncIfExists((uptr)&block1[1]);
102f50cee2fSDmitry Vyukov   CHECK_EQ(s2, (SyncVar *)0);
1039e3e97aaSDmitry Vyukov   s1 = m->GetSyncIfExists((uptr)&block2[0]);
104f50cee2fSDmitry Vyukov   CHECK_NE(s1, (SyncVar *)0);
105f50cee2fSDmitry Vyukov   CHECK_EQ(s1->addr, (uptr)&block2[0]);
1069e3e97aaSDmitry Vyukov   s2 = m->GetSyncIfExists((uptr)&block2[1]);
107f50cee2fSDmitry Vyukov   CHECK_NE(s2, (SyncVar *)0);
108f50cee2fSDmitry Vyukov   CHECK_EQ(s2->addr, (uptr)&block2[1]);
109*b3321349SDmitry Vyukov   m->FreeRange(thr->proc(), (uptr)&block2[0], 4 * sizeof(u64), true);
1105de29a4bSNico Weber }
1115de29a4bSNico Weber 
TEST(MetaMap,ResetSync)1129e3e97aaSDmitry Vyukov TEST(MetaMap, ResetSync) {
1133c92eb44SDmitry Vyukov   ScopedIgnoreInterceptors ignore;
1145de29a4bSNico Weber   ThreadState *thr = cur_thread();
115*b3321349SDmitry Vyukov   SlotLocker locker(thr);
1165de29a4bSNico Weber   MetaMap *m = &ctx->metamap;
1175de29a4bSNico Weber   u64 block[1] = {};  // fake malloc block
1185de29a4bSNico Weber   m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
1197bd81fe1SDmitry Vyukov   SyncVar *s = m->GetSyncOrCreate(thr, 0, (uptr)&block[0], false);
120*b3321349SDmitry Vyukov   s->Reset();
121*b3321349SDmitry Vyukov   uptr sz = m->FreeBlock(thr->proc(), (uptr)&block[0], true);
122f50cee2fSDmitry Vyukov   CHECK_EQ(sz, 1 * sizeof(u64));
1235de29a4bSNico Weber }
1245de29a4bSNico Weber 
1255de29a4bSNico Weber }  // namespace __tsan
126