xref: /openbsd-src/gnu/llvm/compiler-rt/lib/tsan/tests/unit/tsan_sync_test.cpp (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===-- tsan_sync_test.cpp ------------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of ThreadSanitizer (TSan), a race detector.
103cab2bb3Spatrick //
113cab2bb3Spatrick //===----------------------------------------------------------------------===//
123cab2bb3Spatrick #include "tsan_sync.h"
133cab2bb3Spatrick #include "tsan_rtl.h"
143cab2bb3Spatrick #include "gtest/gtest.h"
153cab2bb3Spatrick 
163cab2bb3Spatrick namespace __tsan {
173cab2bb3Spatrick 
TEST(MetaMap,Basic)183cab2bb3Spatrick TEST(MetaMap, Basic) {
193cab2bb3Spatrick   ThreadState *thr = cur_thread();
20*810390e3Srobert   SlotLocker locker(thr);
213cab2bb3Spatrick   MetaMap *m = &ctx->metamap;
223cab2bb3Spatrick   u64 block[1] = {};  // fake malloc block
233cab2bb3Spatrick   m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
243cab2bb3Spatrick   MBlock *mb = m->GetBlock((uptr)&block[0]);
25*810390e3Srobert   CHECK_NE(mb, (MBlock *)0);
26*810390e3Srobert   CHECK_EQ(mb->siz, 1 * sizeof(u64));
27*810390e3Srobert   CHECK_EQ(mb->tid, thr->tid);
28*810390e3Srobert   uptr sz = m->FreeBlock(thr->proc(), (uptr)&block[0], true);
29*810390e3Srobert   CHECK_EQ(sz, 1 * sizeof(u64));
303cab2bb3Spatrick   mb = m->GetBlock((uptr)&block[0]);
31*810390e3Srobert   CHECK_EQ(mb, (MBlock *)0);
323cab2bb3Spatrick }
333cab2bb3Spatrick 
TEST(MetaMap,FreeRange)343cab2bb3Spatrick TEST(MetaMap, FreeRange) {
353cab2bb3Spatrick   ThreadState *thr = cur_thread();
36*810390e3Srobert   SlotLocker locker(thr);
373cab2bb3Spatrick   MetaMap *m = &ctx->metamap;
383cab2bb3Spatrick   u64 block[4] = {};  // fake malloc block
393cab2bb3Spatrick   m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
403cab2bb3Spatrick   m->AllocBlock(thr, 0, (uptr)&block[1], 3 * sizeof(u64));
413cab2bb3Spatrick   MBlock *mb1 = m->GetBlock((uptr)&block[0]);
42*810390e3Srobert   CHECK_EQ(mb1->siz, 1 * sizeof(u64));
433cab2bb3Spatrick   MBlock *mb2 = m->GetBlock((uptr)&block[1]);
44*810390e3Srobert   CHECK_EQ(mb2->siz, 3 * sizeof(u64));
45*810390e3Srobert   m->FreeRange(thr->proc(), (uptr)&block[0], 4 * sizeof(u64), true);
463cab2bb3Spatrick   mb1 = m->GetBlock((uptr)&block[0]);
47*810390e3Srobert   CHECK_EQ(mb1, (MBlock *)0);
483cab2bb3Spatrick   mb2 = m->GetBlock((uptr)&block[1]);
49*810390e3Srobert   CHECK_EQ(mb2, (MBlock *)0);
503cab2bb3Spatrick }
513cab2bb3Spatrick 
TEST(MetaMap,Sync)52*810390e3Srobert TEST(MetaMap, Sync) {
53*810390e3Srobert   // CHECK can call memset/etc. Disable interceptors to prevent
54d89ec533Spatrick   // them from detecting that we exit runtime with mutexes held.
55d89ec533Spatrick   ScopedIgnoreInterceptors ignore;
563cab2bb3Spatrick   ThreadState *thr = cur_thread();
57*810390e3Srobert   SlotLocker locker(thr);
583cab2bb3Spatrick   MetaMap *m = &ctx->metamap;
593cab2bb3Spatrick   u64 block[4] = {};  // fake malloc block
603cab2bb3Spatrick   m->AllocBlock(thr, 0, (uptr)&block[0], 4 * sizeof(u64));
61*810390e3Srobert   SyncVar *s1 = m->GetSyncIfExists((uptr)&block[0]);
62*810390e3Srobert   CHECK_EQ(s1, (SyncVar *)0);
63*810390e3Srobert   s1 = m->GetSyncOrCreate(thr, 0, (uptr)&block[0], false);
64*810390e3Srobert   CHECK_NE(s1, (SyncVar *)0);
65*810390e3Srobert   CHECK_EQ(s1->addr, (uptr)&block[0]);
66*810390e3Srobert   SyncVar *s2 = m->GetSyncOrCreate(thr, 0, (uptr)&block[1], false);
67*810390e3Srobert   CHECK_NE(s2, (SyncVar *)0);
68*810390e3Srobert   CHECK_EQ(s2->addr, (uptr)&block[1]);
69*810390e3Srobert   m->FreeBlock(thr->proc(), (uptr)&block[0], true);
70*810390e3Srobert   s1 = m->GetSyncIfExists((uptr)&block[0]);
71*810390e3Srobert   CHECK_EQ(s1, (SyncVar *)0);
72*810390e3Srobert   s2 = m->GetSyncIfExists((uptr)&block[1]);
73*810390e3Srobert   CHECK_EQ(s2, (SyncVar *)0);
743cab2bb3Spatrick   m->OnProcIdle(thr->proc());
753cab2bb3Spatrick }
763cab2bb3Spatrick 
TEST(MetaMap,MoveMemory)77*810390e3Srobert TEST(MetaMap, MoveMemory) {
78d89ec533Spatrick   ScopedIgnoreInterceptors ignore;
793cab2bb3Spatrick   ThreadState *thr = cur_thread();
80*810390e3Srobert   SlotLocker locker(thr);
813cab2bb3Spatrick   MetaMap *m = &ctx->metamap;
823cab2bb3Spatrick   u64 block1[4] = {};  // fake malloc block
833cab2bb3Spatrick   u64 block2[4] = {};  // fake malloc block
843cab2bb3Spatrick   m->AllocBlock(thr, 0, (uptr)&block1[0], 3 * sizeof(u64));
853cab2bb3Spatrick   m->AllocBlock(thr, 0, (uptr)&block1[3], 1 * sizeof(u64));
86*810390e3Srobert   SyncVar *s1 = m->GetSyncOrCreate(thr, 0, (uptr)&block1[0], false);
87*810390e3Srobert   SyncVar *s2 = m->GetSyncOrCreate(thr, 0, (uptr)&block1[1], false);
883cab2bb3Spatrick   m->MoveMemory((uptr)&block1[0], (uptr)&block2[0], 4 * sizeof(u64));
893cab2bb3Spatrick   MBlock *mb1 = m->GetBlock((uptr)&block1[0]);
90*810390e3Srobert   CHECK_EQ(mb1, (MBlock *)0);
913cab2bb3Spatrick   MBlock *mb2 = m->GetBlock((uptr)&block1[3]);
92*810390e3Srobert   CHECK_EQ(mb2, (MBlock *)0);
933cab2bb3Spatrick   mb1 = m->GetBlock((uptr)&block2[0]);
94*810390e3Srobert   CHECK_NE(mb1, (MBlock *)0);
95*810390e3Srobert   CHECK_EQ(mb1->siz, 3 * sizeof(u64));
963cab2bb3Spatrick   mb2 = m->GetBlock((uptr)&block2[3]);
97*810390e3Srobert   CHECK_NE(mb2, (MBlock *)0);
98*810390e3Srobert   CHECK_EQ(mb2->siz, 1 * sizeof(u64));
99*810390e3Srobert   s1 = m->GetSyncIfExists((uptr)&block1[0]);
100*810390e3Srobert   CHECK_EQ(s1, (SyncVar *)0);
101*810390e3Srobert   s2 = m->GetSyncIfExists((uptr)&block1[1]);
102*810390e3Srobert   CHECK_EQ(s2, (SyncVar *)0);
103*810390e3Srobert   s1 = m->GetSyncIfExists((uptr)&block2[0]);
104*810390e3Srobert   CHECK_NE(s1, (SyncVar *)0);
105*810390e3Srobert   CHECK_EQ(s1->addr, (uptr)&block2[0]);
106*810390e3Srobert   s2 = m->GetSyncIfExists((uptr)&block2[1]);
107*810390e3Srobert   CHECK_NE(s2, (SyncVar *)0);
108*810390e3Srobert   CHECK_EQ(s2->addr, (uptr)&block2[1]);
109*810390e3Srobert   m->FreeRange(thr->proc(), (uptr)&block2[0], 4 * sizeof(u64), true);
1103cab2bb3Spatrick }
1113cab2bb3Spatrick 
TEST(MetaMap,ResetSync)112*810390e3Srobert TEST(MetaMap, ResetSync) {
113d89ec533Spatrick   ScopedIgnoreInterceptors ignore;
1143cab2bb3Spatrick   ThreadState *thr = cur_thread();
115*810390e3Srobert   SlotLocker locker(thr);
1163cab2bb3Spatrick   MetaMap *m = &ctx->metamap;
1173cab2bb3Spatrick   u64 block[1] = {};  // fake malloc block
1183cab2bb3Spatrick   m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
119*810390e3Srobert   SyncVar *s = m->GetSyncOrCreate(thr, 0, (uptr)&block[0], false);
120*810390e3Srobert   s->Reset();
121*810390e3Srobert   uptr sz = m->FreeBlock(thr->proc(), (uptr)&block[0], true);
122*810390e3Srobert   CHECK_EQ(sz, 1 * sizeof(u64));
1233cab2bb3Spatrick }
1243cab2bb3Spatrick 
1253cab2bb3Spatrick }  // namespace __tsan
126