summaryrefslogtreecommitdiff
path: root/lib/tsan/tests/unit/tsan_sync_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tsan/tests/unit/tsan_sync_test.cc')
-rw-r--r--lib/tsan/tests/unit/tsan_sync_test.cc140
1 files changed, 99 insertions, 41 deletions
diff --git a/lib/tsan/tests/unit/tsan_sync_test.cc b/lib/tsan/tests/unit/tsan_sync_test.cc
index dddf0b2908836..d3616a1a4b811 100644
--- a/lib/tsan/tests/unit/tsan_sync_test.cc
+++ b/lib/tsan/tests/unit/tsan_sync_test.cc
@@ -12,54 +12,112 @@
//===----------------------------------------------------------------------===//
#include "tsan_sync.h"
#include "tsan_rtl.h"
-#include "tsan_mman.h"
#include "gtest/gtest.h"
-#include <stdlib.h>
-#include <stdint.h>
-#include <map>
-
namespace __tsan {
-TEST(Sync, Table) {
- const uintptr_t kIters = 512*1024;
- const uintptr_t kRange = 10000;
+TEST(MetaMap, Basic) {
+ ThreadState *thr = cur_thread();
+ MetaMap *m = &ctx->metamap;
+ u64 block[1] = {}; // fake malloc block
+ m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
+ MBlock *mb = m->GetBlock((uptr)&block[0]);
+ EXPECT_NE(mb, (MBlock*)0);
+ EXPECT_EQ(mb->siz, 1 * sizeof(u64));
+ EXPECT_EQ(mb->tid, thr->tid);
+ uptr sz = m->FreeBlock(thr, 0, (uptr)&block[0]);
+ EXPECT_EQ(sz, 1 * sizeof(u64));
+ mb = m->GetBlock((uptr)&block[0]);
+ EXPECT_EQ(mb, (MBlock*)0);
+}
- ScopedInRtl in_rtl;
+TEST(MetaMap, FreeRange) {
ThreadState *thr = cur_thread();
- uptr pc = 0;
+ MetaMap *m = &ctx->metamap;
+ u64 block[4] = {}; // fake malloc block
+ m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
+ m->AllocBlock(thr, 0, (uptr)&block[1], 3 * sizeof(u64));
+ MBlock *mb1 = m->GetBlock((uptr)&block[0]);
+ EXPECT_EQ(mb1->siz, 1 * sizeof(u64));
+ MBlock *mb2 = m->GetBlock((uptr)&block[1]);
+ EXPECT_EQ(mb2->siz, 3 * sizeof(u64));
+ m->FreeRange(thr, 0, (uptr)&block[0], 4 * sizeof(u64));
+ mb1 = m->GetBlock((uptr)&block[0]);
+ EXPECT_EQ(mb1, (MBlock*)0);
+ mb2 = m->GetBlock((uptr)&block[1]);
+ EXPECT_EQ(mb2, (MBlock*)0);
+}
- SyncTab tab;
- SyncVar *golden[kRange] = {};
- unsigned seed = 0;
- for (uintptr_t i = 0; i < kIters; i++) {
- uintptr_t addr = rand_r(&seed) % (kRange - 1) + 1;
- if (rand_r(&seed) % 2) {
- // Get or add.
- SyncVar *v = tab.GetOrCreateAndLock(thr, pc, addr, true);
- EXPECT_TRUE(golden[addr] == 0 || golden[addr] == v);
- EXPECT_EQ(v->addr, addr);
- golden[addr] = v;
- v->mtx.Unlock();
- } else {
- // Remove.
- SyncVar *v = tab.GetAndRemove(thr, pc, addr);
- EXPECT_EQ(golden[addr], v);
- if (v) {
- EXPECT_EQ(v->addr, addr);
- golden[addr] = 0;
- DestroyAndFree(v);
- }
- }
- }
- for (uintptr_t addr = 0; addr < kRange; addr++) {
- if (golden[addr] == 0)
- continue;
- SyncVar *v = tab.GetAndRemove(thr, pc, addr);
- EXPECT_EQ(v, golden[addr]);
- EXPECT_EQ(v->addr, addr);
- DestroyAndFree(v);
- }
+TEST(MetaMap, Sync) {
+ ThreadState *thr = cur_thread();
+ MetaMap *m = &ctx->metamap;
+ u64 block[4] = {}; // fake malloc block
+ m->AllocBlock(thr, 0, (uptr)&block[0], 4 * sizeof(u64));
+ SyncVar *s1 = m->GetIfExistsAndLock((uptr)&block[0]);
+ EXPECT_EQ(s1, (SyncVar*)0);
+ s1 = m->GetOrCreateAndLock(thr, 0, (uptr)&block[0], true);
+ EXPECT_NE(s1, (SyncVar*)0);
+ EXPECT_EQ(s1->addr, (uptr)&block[0]);
+ s1->mtx.Unlock();
+ SyncVar *s2 = m->GetOrCreateAndLock(thr, 0, (uptr)&block[1], false);
+ EXPECT_NE(s2, (SyncVar*)0);
+ EXPECT_EQ(s2->addr, (uptr)&block[1]);
+ s2->mtx.ReadUnlock();
+ m->FreeBlock(thr, 0, (uptr)&block[0]);
+ s1 = m->GetIfExistsAndLock((uptr)&block[0]);
+ EXPECT_EQ(s1, (SyncVar*)0);
+ s2 = m->GetIfExistsAndLock((uptr)&block[1]);
+ EXPECT_EQ(s2, (SyncVar*)0);
+ m->OnThreadIdle(thr);
+}
+
+TEST(MetaMap, MoveMemory) {
+ ThreadState *thr = cur_thread();
+ MetaMap *m = &ctx->metamap;
+ u64 block1[4] = {}; // fake malloc block
+ u64 block2[4] = {}; // fake malloc block
+ m->AllocBlock(thr, 0, (uptr)&block1[0], 3 * sizeof(u64));
+ m->AllocBlock(thr, 0, (uptr)&block1[3], 1 * sizeof(u64));
+ SyncVar *s1 = m->GetOrCreateAndLock(thr, 0, (uptr)&block1[0], true);
+ s1->mtx.Unlock();
+ SyncVar *s2 = m->GetOrCreateAndLock(thr, 0, (uptr)&block1[1], true);
+ s2->mtx.Unlock();
+ m->MoveMemory((uptr)&block1[0], (uptr)&block2[0], 4 * sizeof(u64));
+ MBlock *mb1 = m->GetBlock((uptr)&block1[0]);
+ EXPECT_EQ(mb1, (MBlock*)0);
+ MBlock *mb2 = m->GetBlock((uptr)&block1[3]);
+ EXPECT_EQ(mb2, (MBlock*)0);
+ mb1 = m->GetBlock((uptr)&block2[0]);
+ EXPECT_NE(mb1, (MBlock*)0);
+ EXPECT_EQ(mb1->siz, 3 * sizeof(u64));
+ mb2 = m->GetBlock((uptr)&block2[3]);
+ EXPECT_NE(mb2, (MBlock*)0);
+ EXPECT_EQ(mb2->siz, 1 * sizeof(u64));
+ s1 = m->GetIfExistsAndLock((uptr)&block1[0]);
+ EXPECT_EQ(s1, (SyncVar*)0);
+ s2 = m->GetIfExistsAndLock((uptr)&block1[1]);
+ EXPECT_EQ(s2, (SyncVar*)0);
+ s1 = m->GetIfExistsAndLock((uptr)&block2[0]);
+ EXPECT_NE(s1, (SyncVar*)0);
+ EXPECT_EQ(s1->addr, (uptr)&block2[0]);
+ s1->mtx.Unlock();
+ s2 = m->GetIfExistsAndLock((uptr)&block2[1]);
+ EXPECT_NE(s2, (SyncVar*)0);
+ EXPECT_EQ(s2->addr, (uptr)&block2[1]);
+ s2->mtx.Unlock();
+ m->FreeRange(thr, 0, (uptr)&block2[0], 4 * sizeof(u64));
+}
+
+TEST(MetaMap, ResetSync) {
+ ThreadState *thr = cur_thread();
+ MetaMap *m = &ctx->metamap;
+ u64 block[1] = {}; // fake malloc block
+ m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
+ SyncVar *s = m->GetOrCreateAndLock(thr, 0, (uptr)&block[0], true);
+ s->Reset(thr);
+ s->mtx.Unlock();
+ uptr sz = m->FreeBlock(thr, 0, (uptr)&block[0]);
+ EXPECT_EQ(sz, 1 * sizeof(u64));
}
} // namespace __tsan