13cab2bb3Spatrick //===-- tsan_mop.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_interface.h"
133cab2bb3Spatrick #include "tsan_test_util.h"
143cab2bb3Spatrick #include "gtest/gtest.h"
153cab2bb3Spatrick #include <stddef.h>
163cab2bb3Spatrick #include <stdint.h>
173cab2bb3Spatrick
TEST_F(ThreadSanitizer,SimpleWrite)18*810390e3Srobert TEST_F(ThreadSanitizer, SimpleWrite) {
193cab2bb3Spatrick ScopedThread t;
203cab2bb3Spatrick MemLoc l;
213cab2bb3Spatrick t.Write1(l);
223cab2bb3Spatrick }
233cab2bb3Spatrick
TEST_F(ThreadSanitizer,SimpleWriteWrite)24*810390e3Srobert TEST_F(ThreadSanitizer, SimpleWriteWrite) {
253cab2bb3Spatrick ScopedThread t1, t2;
263cab2bb3Spatrick MemLoc l1, l2;
273cab2bb3Spatrick t1.Write1(l1);
283cab2bb3Spatrick t2.Write1(l2);
293cab2bb3Spatrick }
303cab2bb3Spatrick
TEST_F(ThreadSanitizer,WriteWriteRace)31*810390e3Srobert TEST_F(ThreadSanitizer, WriteWriteRace) {
323cab2bb3Spatrick ScopedThread t1, t2;
333cab2bb3Spatrick MemLoc l;
343cab2bb3Spatrick t1.Write1(l);
353cab2bb3Spatrick t2.Write1(l, true);
363cab2bb3Spatrick }
373cab2bb3Spatrick
TEST_F(ThreadSanitizer,ReadWriteRace)38*810390e3Srobert TEST_F(ThreadSanitizer, ReadWriteRace) {
393cab2bb3Spatrick ScopedThread t1, t2;
403cab2bb3Spatrick MemLoc l;
413cab2bb3Spatrick t1.Read1(l);
423cab2bb3Spatrick t2.Write1(l, true);
433cab2bb3Spatrick }
443cab2bb3Spatrick
TEST_F(ThreadSanitizer,WriteReadRace)45*810390e3Srobert TEST_F(ThreadSanitizer, WriteReadRace) {
463cab2bb3Spatrick ScopedThread t1, t2;
473cab2bb3Spatrick MemLoc l;
483cab2bb3Spatrick t1.Write1(l);
493cab2bb3Spatrick t2.Read1(l, true);
503cab2bb3Spatrick }
513cab2bb3Spatrick
TEST_F(ThreadSanitizer,ReadReadNoRace)52*810390e3Srobert TEST_F(ThreadSanitizer, ReadReadNoRace) {
533cab2bb3Spatrick ScopedThread t1, t2;
543cab2bb3Spatrick MemLoc l;
553cab2bb3Spatrick t1.Read1(l);
563cab2bb3Spatrick t2.Read1(l);
573cab2bb3Spatrick }
583cab2bb3Spatrick
TEST_F(ThreadSanitizer,WriteThenRead)59*810390e3Srobert TEST_F(ThreadSanitizer, WriteThenRead) {
603cab2bb3Spatrick MemLoc l;
613cab2bb3Spatrick ScopedThread t1, t2;
623cab2bb3Spatrick t1.Write1(l);
633cab2bb3Spatrick t1.Read1(l);
643cab2bb3Spatrick t2.Read1(l, true);
653cab2bb3Spatrick }
663cab2bb3Spatrick
TEST_F(ThreadSanitizer,WriteThenLockedRead)67*810390e3Srobert TEST_F(ThreadSanitizer, WriteThenLockedRead) {
68d89ec533Spatrick UserMutex m(UserMutex::RW);
693cab2bb3Spatrick MainThread t0;
703cab2bb3Spatrick t0.Create(m);
713cab2bb3Spatrick MemLoc l;
723cab2bb3Spatrick {
733cab2bb3Spatrick ScopedThread t1, t2;
743cab2bb3Spatrick
753cab2bb3Spatrick t1.Write8(l);
763cab2bb3Spatrick
773cab2bb3Spatrick t1.Lock(m);
783cab2bb3Spatrick t1.Read8(l);
793cab2bb3Spatrick t1.Unlock(m);
803cab2bb3Spatrick
813cab2bb3Spatrick t2.Read8(l, true);
823cab2bb3Spatrick }
833cab2bb3Spatrick t0.Destroy(m);
843cab2bb3Spatrick }
853cab2bb3Spatrick
TEST_F(ThreadSanitizer,LockedWriteThenRead)86*810390e3Srobert TEST_F(ThreadSanitizer, LockedWriteThenRead) {
87d89ec533Spatrick UserMutex m(UserMutex::RW);
883cab2bb3Spatrick MainThread t0;
893cab2bb3Spatrick t0.Create(m);
903cab2bb3Spatrick MemLoc l;
913cab2bb3Spatrick {
923cab2bb3Spatrick ScopedThread t1, t2;
933cab2bb3Spatrick
943cab2bb3Spatrick t1.Lock(m);
953cab2bb3Spatrick t1.Write8(l);
963cab2bb3Spatrick t1.Unlock(m);
973cab2bb3Spatrick
983cab2bb3Spatrick t1.Read8(l);
993cab2bb3Spatrick
1003cab2bb3Spatrick t2.Read8(l, true);
1013cab2bb3Spatrick }
1023cab2bb3Spatrick t0.Destroy(m);
1033cab2bb3Spatrick }
1043cab2bb3Spatrick
1053cab2bb3Spatrick
TEST_F(ThreadSanitizer,RaceWithOffset)106*810390e3Srobert TEST_F(ThreadSanitizer, RaceWithOffset) {
1073cab2bb3Spatrick ScopedThread t1, t2;
1083cab2bb3Spatrick {
1093cab2bb3Spatrick MemLoc l;
1103cab2bb3Spatrick t1.Access(l.loc(), true, 8, false);
1113cab2bb3Spatrick t2.Access((char*)l.loc() + 4, true, 4, true);
1123cab2bb3Spatrick }
1133cab2bb3Spatrick {
1143cab2bb3Spatrick MemLoc l;
1153cab2bb3Spatrick t1.Access(l.loc(), true, 8, false);
1163cab2bb3Spatrick t2.Access((char*)l.loc() + 7, true, 1, true);
1173cab2bb3Spatrick }
1183cab2bb3Spatrick {
1193cab2bb3Spatrick MemLoc l;
1203cab2bb3Spatrick t1.Access((char*)l.loc() + 4, true, 4, false);
1213cab2bb3Spatrick t2.Access((char*)l.loc() + 4, true, 2, true);
1223cab2bb3Spatrick }
1233cab2bb3Spatrick {
1243cab2bb3Spatrick MemLoc l;
1253cab2bb3Spatrick t1.Access((char*)l.loc() + 4, true, 4, false);
1263cab2bb3Spatrick t2.Access((char*)l.loc() + 6, true, 2, true);
1273cab2bb3Spatrick }
1283cab2bb3Spatrick {
1293cab2bb3Spatrick MemLoc l;
1303cab2bb3Spatrick t1.Access((char*)l.loc() + 3, true, 2, false);
1313cab2bb3Spatrick t2.Access((char*)l.loc() + 4, true, 1, true);
1323cab2bb3Spatrick }
1333cab2bb3Spatrick {
1343cab2bb3Spatrick MemLoc l;
1353cab2bb3Spatrick t1.Access((char*)l.loc() + 1, true, 8, false);
1363cab2bb3Spatrick t2.Access((char*)l.loc() + 3, true, 1, true);
1373cab2bb3Spatrick }
1383cab2bb3Spatrick }
1393cab2bb3Spatrick
TEST_F(ThreadSanitizer,RaceWithOffset2)140*810390e3Srobert TEST_F(ThreadSanitizer, RaceWithOffset2) {
1413cab2bb3Spatrick ScopedThread t1, t2;
1423cab2bb3Spatrick {
1433cab2bb3Spatrick MemLoc l;
1443cab2bb3Spatrick t1.Access((char*)l.loc(), true, 4, false);
1453cab2bb3Spatrick t2.Access((char*)l.loc() + 2, true, 1, true);
1463cab2bb3Spatrick }
1473cab2bb3Spatrick {
1483cab2bb3Spatrick MemLoc l;
1493cab2bb3Spatrick t1.Access((char*)l.loc() + 2, true, 1, false);
1503cab2bb3Spatrick t2.Access((char*)l.loc(), true, 4, true);
1513cab2bb3Spatrick }
1523cab2bb3Spatrick }
1533cab2bb3Spatrick
TEST_F(ThreadSanitizer,NoRaceWithOffset)154*810390e3Srobert TEST_F(ThreadSanitizer, NoRaceWithOffset) {
1553cab2bb3Spatrick ScopedThread t1, t2;
1563cab2bb3Spatrick {
1573cab2bb3Spatrick MemLoc l;
1583cab2bb3Spatrick t1.Access(l.loc(), true, 4, false);
1593cab2bb3Spatrick t2.Access((char*)l.loc() + 4, true, 4, false);
1603cab2bb3Spatrick }
1613cab2bb3Spatrick {
1623cab2bb3Spatrick MemLoc l;
1633cab2bb3Spatrick t1.Access((char*)l.loc() + 3, true, 2, false);
1643cab2bb3Spatrick t2.Access((char*)l.loc() + 1, true, 2, false);
1653cab2bb3Spatrick t2.Access((char*)l.loc() + 5, true, 2, false);
1663cab2bb3Spatrick }
1673cab2bb3Spatrick }
1683cab2bb3Spatrick
TEST_F(ThreadSanitizer,RaceWithDeadThread)169*810390e3Srobert TEST_F(ThreadSanitizer, RaceWithDeadThread) {
1703cab2bb3Spatrick MemLoc l;
1713cab2bb3Spatrick ScopedThread t;
1723cab2bb3Spatrick ScopedThread().Write1(l);
1733cab2bb3Spatrick t.Write1(l, true);
1743cab2bb3Spatrick }
1753cab2bb3Spatrick
TEST_F(ThreadSanitizer,BenignRaceOnVptr)176*810390e3Srobert TEST_F(ThreadSanitizer, BenignRaceOnVptr) {
1773cab2bb3Spatrick void *vptr_storage;
1783cab2bb3Spatrick MemLoc vptr(&vptr_storage), val;
1793cab2bb3Spatrick vptr_storage = val.loc();
1803cab2bb3Spatrick ScopedThread t1, t2;
1813cab2bb3Spatrick t1.VptrUpdate(vptr, val);
1823cab2bb3Spatrick t2.Read8(vptr);
1833cab2bb3Spatrick }
1843cab2bb3Spatrick
TEST_F(ThreadSanitizer,HarmfulRaceOnVptr)185*810390e3Srobert TEST_F(ThreadSanitizer, HarmfulRaceOnVptr) {
1863cab2bb3Spatrick void *vptr_storage;
1873cab2bb3Spatrick MemLoc vptr(&vptr_storage), val1, val2;
1883cab2bb3Spatrick vptr_storage = val1.loc();
1893cab2bb3Spatrick ScopedThread t1, t2;
1903cab2bb3Spatrick t1.VptrUpdate(vptr, val2);
1913cab2bb3Spatrick t2.Read8(vptr, true);
1923cab2bb3Spatrick }
1933cab2bb3Spatrick
foo()1943cab2bb3Spatrick static void foo() {
1953cab2bb3Spatrick volatile int x = 42;
1963cab2bb3Spatrick int x2 = x;
1973cab2bb3Spatrick (void)x2;
1983cab2bb3Spatrick }
1993cab2bb3Spatrick
bar()2003cab2bb3Spatrick static void bar() {
2013cab2bb3Spatrick volatile int x = 43;
2023cab2bb3Spatrick int x2 = x;
2033cab2bb3Spatrick (void)x2;
2043cab2bb3Spatrick }
2053cab2bb3Spatrick
TEST_F(ThreadSanitizer,ReportDeadThread)206*810390e3Srobert TEST_F(ThreadSanitizer, ReportDeadThread) {
2073cab2bb3Spatrick MemLoc l;
2083cab2bb3Spatrick ScopedThread t1;
2093cab2bb3Spatrick {
2103cab2bb3Spatrick ScopedThread t2;
2113cab2bb3Spatrick t2.Call(&foo);
2123cab2bb3Spatrick t2.Call(&bar);
2133cab2bb3Spatrick t2.Write1(l);
2143cab2bb3Spatrick }
2153cab2bb3Spatrick t1.Write1(l, true);
2163cab2bb3Spatrick }
2173cab2bb3Spatrick
2183cab2bb3Spatrick struct ClassWithStatic {
2193cab2bb3Spatrick static int Data[4];
2203cab2bb3Spatrick };
2213cab2bb3Spatrick
2223cab2bb3Spatrick int ClassWithStatic::Data[4];
2233cab2bb3Spatrick
foobarbaz()2243cab2bb3Spatrick static void foobarbaz() {}
2253cab2bb3Spatrick
TEST_F(ThreadSanitizer,ReportRace)226*810390e3Srobert TEST_F(ThreadSanitizer, ReportRace) {
2273cab2bb3Spatrick ScopedThread t1;
2283cab2bb3Spatrick MainThread().Access(&ClassWithStatic::Data, true, 4, false);
2293cab2bb3Spatrick t1.Call(&foobarbaz);
2303cab2bb3Spatrick t1.Access(&ClassWithStatic::Data, true, 2, true);
2313cab2bb3Spatrick t1.Return();
2323cab2bb3Spatrick }
233