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