233 lines · cpp
1//===-- tsan_mop.cpp ------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of ThreadSanitizer (TSan), a race detector.10//11//===----------------------------------------------------------------------===//12#include "tsan_interface.h"13#include "tsan_test_util.h"14#include "gtest/gtest.h"15#include <stddef.h>16#include <stdint.h>17 18TEST_F(ThreadSanitizer, SimpleWrite) {19 ScopedThread t;20 MemLoc l;21 t.Write1(l);22}23 24TEST_F(ThreadSanitizer, SimpleWriteWrite) {25 ScopedThread t1, t2;26 MemLoc l1, l2;27 t1.Write1(l1);28 t2.Write1(l2);29}30 31TEST_F(ThreadSanitizer, WriteWriteRace) {32 ScopedThread t1, t2;33 MemLoc l;34 t1.Write1(l);35 t2.Write1(l, true);36}37 38TEST_F(ThreadSanitizer, ReadWriteRace) {39 ScopedThread t1, t2;40 MemLoc l;41 t1.Read1(l);42 t2.Write1(l, true);43}44 45TEST_F(ThreadSanitizer, WriteReadRace) {46 ScopedThread t1, t2;47 MemLoc l;48 t1.Write1(l);49 t2.Read1(l, true);50}51 52TEST_F(ThreadSanitizer, ReadReadNoRace) {53 ScopedThread t1, t2;54 MemLoc l;55 t1.Read1(l);56 t2.Read1(l);57}58 59TEST_F(ThreadSanitizer, WriteThenRead) {60 MemLoc l;61 ScopedThread t1, t2;62 t1.Write1(l);63 t1.Read1(l);64 t2.Read1(l, true);65}66 67TEST_F(ThreadSanitizer, WriteThenLockedRead) {68 UserMutex m(UserMutex::RW);69 MainThread t0;70 t0.Create(m);71 MemLoc l;72 {73 ScopedThread t1, t2;74 75 t1.Write8(l);76 77 t1.Lock(m);78 t1.Read8(l);79 t1.Unlock(m);80 81 t2.Read8(l, true);82 }83 t0.Destroy(m);84}85 86TEST_F(ThreadSanitizer, LockedWriteThenRead) {87 UserMutex m(UserMutex::RW);88 MainThread t0;89 t0.Create(m);90 MemLoc l;91 {92 ScopedThread t1, t2;93 94 t1.Lock(m);95 t1.Write8(l);96 t1.Unlock(m);97 98 t1.Read8(l);99 100 t2.Read8(l, true);101 }102 t0.Destroy(m);103}104 105 106TEST_F(ThreadSanitizer, RaceWithOffset) {107 ScopedThread t1, t2;108 {109 MemLoc l;110 t1.Access(l.loc(), true, 8, false);111 t2.Access((char*)l.loc() + 4, true, 4, true);112 }113 {114 MemLoc l;115 t1.Access(l.loc(), true, 8, false);116 t2.Access((char*)l.loc() + 7, true, 1, true);117 }118 {119 MemLoc l;120 t1.Access((char*)l.loc() + 4, true, 4, false);121 t2.Access((char*)l.loc() + 4, true, 2, true);122 }123 {124 MemLoc l;125 t1.Access((char*)l.loc() + 4, true, 4, false);126 t2.Access((char*)l.loc() + 6, true, 2, true);127 }128 {129 MemLoc l;130 t1.Access((char*)l.loc() + 3, true, 2, false);131 t2.Access((char*)l.loc() + 4, true, 1, true);132 }133 {134 MemLoc l;135 t1.Access((char*)l.loc() + 1, true, 8, false);136 t2.Access((char*)l.loc() + 3, true, 1, true);137 }138}139 140TEST_F(ThreadSanitizer, RaceWithOffset2) {141 ScopedThread t1, t2;142 {143 MemLoc l;144 t1.Access((char*)l.loc(), true, 4, false);145 t2.Access((char*)l.loc() + 2, true, 1, true);146 }147 {148 MemLoc l;149 t1.Access((char*)l.loc() + 2, true, 1, false);150 t2.Access((char*)l.loc(), true, 4, true);151 }152}153 154TEST_F(ThreadSanitizer, NoRaceWithOffset) {155 ScopedThread t1, t2;156 {157 MemLoc l;158 t1.Access(l.loc(), true, 4, false);159 t2.Access((char*)l.loc() + 4, true, 4, false);160 }161 {162 MemLoc l;163 t1.Access((char*)l.loc() + 3, true, 2, false);164 t2.Access((char*)l.loc() + 1, true, 2, false);165 t2.Access((char*)l.loc() + 5, true, 2, false);166 }167}168 169TEST_F(ThreadSanitizer, RaceWithDeadThread) {170 MemLoc l;171 ScopedThread t;172 ScopedThread().Write1(l);173 t.Write1(l, true);174}175 176TEST_F(ThreadSanitizer, BenignRaceOnVptr) {177 void *vptr_storage;178 MemLoc vptr(&vptr_storage), val;179 vptr_storage = val.loc();180 ScopedThread t1, t2;181 t1.VptrUpdate(vptr, val);182 t2.Read8(vptr);183}184 185TEST_F(ThreadSanitizer, HarmfulRaceOnVptr) {186 void *vptr_storage;187 MemLoc vptr(&vptr_storage), val1, val2;188 vptr_storage = val1.loc();189 ScopedThread t1, t2;190 t1.VptrUpdate(vptr, val2);191 t2.Read8(vptr, true);192}193 194static void foo() {195 volatile int x = 42;196 int x2 = x;197 (void)x2;198}199 200static void bar() {201 volatile int x = 43;202 int x2 = x;203 (void)x2;204}205 206TEST_F(ThreadSanitizer, ReportDeadThread) {207 MemLoc l;208 ScopedThread t1;209 {210 ScopedThread t2;211 t2.Call(&foo);212 t2.Call(&bar);213 t2.Write1(l);214 }215 t1.Write1(l, true);216}217 218struct ClassWithStatic {219 static int Data[4];220};221 222int ClassWithStatic::Data[4];223 224static void foobarbaz() {}225 226TEST_F(ThreadSanitizer, ReportRace) {227 ScopedThread t1;228 MainThread().Access(&ClassWithStatic::Data, true, 4, false);229 t1.Call(&foobarbaz);230 t1.Access(&ClassWithStatic::Data, true, 2, true);231 t1.Return();232}233