Home | History | Annotate | Download | only in unit
      1 //===-- tsan_sync_test.cc -------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is a part of ThreadSanitizer (TSan), a race detector.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 #include "tsan_sync.h"
     14 #include "tsan_rtl.h"
     15 #include "gtest/gtest.h"
     16 
     17 namespace __tsan {
     18 
     19 TEST(MetaMap, Basic) {
     20   ThreadState *thr = cur_thread();
     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   EXPECT_NE(mb, (MBlock*)0);
     26   EXPECT_EQ(mb->siz, 1 * sizeof(u64));
     27   EXPECT_EQ(mb->tid, thr->tid);
     28   uptr sz = m->FreeBlock(thr->proc(), (uptr)&block[0]);
     29   EXPECT_EQ(sz, 1 * sizeof(u64));
     30   mb = m->GetBlock((uptr)&block[0]);
     31   EXPECT_EQ(mb, (MBlock*)0);
     32 }
     33 
     34 TEST(MetaMap, FreeRange) {
     35   ThreadState *thr = cur_thread();
     36   MetaMap *m = &ctx->metamap;
     37   u64 block[4] = {};  // fake malloc block
     38   m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
     39   m->AllocBlock(thr, 0, (uptr)&block[1], 3 * sizeof(u64));
     40   MBlock *mb1 = m->GetBlock((uptr)&block[0]);
     41   EXPECT_EQ(mb1->siz, 1 * sizeof(u64));
     42   MBlock *mb2 = m->GetBlock((uptr)&block[1]);
     43   EXPECT_EQ(mb2->siz, 3 * sizeof(u64));
     44   m->FreeRange(thr->proc(), (uptr)&block[0], 4 * sizeof(u64));
     45   mb1 = m->GetBlock((uptr)&block[0]);
     46   EXPECT_EQ(mb1, (MBlock*)0);
     47   mb2 = m->GetBlock((uptr)&block[1]);
     48   EXPECT_EQ(mb2, (MBlock*)0);
     49 }
     50 
     51 TEST(MetaMap, Sync) {
     52   ThreadState *thr = cur_thread();
     53   MetaMap *m = &ctx->metamap;
     54   u64 block[4] = {};  // fake malloc block
     55   m->AllocBlock(thr, 0, (uptr)&block[0], 4 * sizeof(u64));
     56   SyncVar *s1 = m->GetIfExistsAndLock((uptr)&block[0], true);
     57   EXPECT_EQ(s1, (SyncVar*)0);
     58   s1 = m->GetOrCreateAndLock(thr, 0, (uptr)&block[0], true);
     59   EXPECT_NE(s1, (SyncVar*)0);
     60   EXPECT_EQ(s1->addr, (uptr)&block[0]);
     61   s1->mtx.Unlock();
     62   SyncVar *s2 = m->GetOrCreateAndLock(thr, 0, (uptr)&block[1], false);
     63   EXPECT_NE(s2, (SyncVar*)0);
     64   EXPECT_EQ(s2->addr, (uptr)&block[1]);
     65   s2->mtx.ReadUnlock();
     66   m->FreeBlock(thr->proc(), (uptr)&block[0]);
     67   s1 = m->GetIfExistsAndLock((uptr)&block[0], true);
     68   EXPECT_EQ(s1, (SyncVar*)0);
     69   s2 = m->GetIfExistsAndLock((uptr)&block[1], true);
     70   EXPECT_EQ(s2, (SyncVar*)0);
     71   m->OnProcIdle(thr->proc());
     72 }
     73 
     74 TEST(MetaMap, MoveMemory) {
     75   ThreadState *thr = cur_thread();
     76   MetaMap *m = &ctx->metamap;
     77   u64 block1[4] = {};  // fake malloc block
     78   u64 block2[4] = {};  // fake malloc block
     79   m->AllocBlock(thr, 0, (uptr)&block1[0], 3 * sizeof(u64));
     80   m->AllocBlock(thr, 0, (uptr)&block1[3], 1 * sizeof(u64));
     81   SyncVar *s1 = m->GetOrCreateAndLock(thr, 0, (uptr)&block1[0], true);
     82   s1->mtx.Unlock();
     83   SyncVar *s2 = m->GetOrCreateAndLock(thr, 0, (uptr)&block1[1], true);
     84   s2->mtx.Unlock();
     85   m->MoveMemory((uptr)&block1[0], (uptr)&block2[0], 4 * sizeof(u64));
     86   MBlock *mb1 = m->GetBlock((uptr)&block1[0]);
     87   EXPECT_EQ(mb1, (MBlock*)0);
     88   MBlock *mb2 = m->GetBlock((uptr)&block1[3]);
     89   EXPECT_EQ(mb2, (MBlock*)0);
     90   mb1 = m->GetBlock((uptr)&block2[0]);
     91   EXPECT_NE(mb1, (MBlock*)0);
     92   EXPECT_EQ(mb1->siz, 3 * sizeof(u64));
     93   mb2 = m->GetBlock((uptr)&block2[3]);
     94   EXPECT_NE(mb2, (MBlock*)0);
     95   EXPECT_EQ(mb2->siz, 1 * sizeof(u64));
     96   s1 = m->GetIfExistsAndLock((uptr)&block1[0], true);
     97   EXPECT_EQ(s1, (SyncVar*)0);
     98   s2 = m->GetIfExistsAndLock((uptr)&block1[1], true);
     99   EXPECT_EQ(s2, (SyncVar*)0);
    100   s1 = m->GetIfExistsAndLock((uptr)&block2[0], true);
    101   EXPECT_NE(s1, (SyncVar*)0);
    102   EXPECT_EQ(s1->addr, (uptr)&block2[0]);
    103   s1->mtx.Unlock();
    104   s2 = m->GetIfExistsAndLock((uptr)&block2[1], true);
    105   EXPECT_NE(s2, (SyncVar*)0);
    106   EXPECT_EQ(s2->addr, (uptr)&block2[1]);
    107   s2->mtx.Unlock();
    108   m->FreeRange(thr->proc(), (uptr)&block2[0], 4 * sizeof(u64));
    109 }
    110 
    111 TEST(MetaMap, ResetSync) {
    112   ThreadState *thr = cur_thread();
    113   MetaMap *m = &ctx->metamap;
    114   u64 block[1] = {};  // fake malloc block
    115   m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64));
    116   SyncVar *s = m->GetOrCreateAndLock(thr, 0, (uptr)&block[0], true);
    117   s->Reset(thr->proc());
    118   s->mtx.Unlock();
    119   uptr sz = m->FreeBlock(thr->proc(), (uptr)&block[0]);
    120   EXPECT_EQ(sz, 1 * sizeof(u64));
    121 }
    122 
    123 }  // namespace __tsan
    124