1fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov
2603c4be006d8c53905d736bf1f19a49f5ce98276Alexey Samsonov//===-- tsan_test_util_linux.cc -------------------------------------------===//
3da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany//
4da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany//                     The LLVM Compiler Infrastructure
5da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany//
6da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany// This file is distributed under the University of Illinois Open Source
7da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany// License. See LICENSE.TXT for details.
8da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany//
9da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany//===----------------------------------------------------------------------===//
10da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany//
11da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany// This file is a part of ThreadSanitizer (TSan), a race detector.
12da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany//
13da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany// Test utils, linux implementation.
14da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany//===----------------------------------------------------------------------===//
15da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
16fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov#include "sanitizer_common/sanitizer_atomic.h"
17da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#include "tsan_interface.h"
18da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#include "tsan_test_util.h"
19da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#include "tsan_report.h"
20da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
21da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#include "gtest/gtest.h"
22da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
23da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#include <assert.h>
24da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#include <pthread.h>
25da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#include <stdio.h>
26da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#include <stdint.h>
27da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#include <string.h>
28da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#include <unistd.h>
29da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany#include <errno.h>
30da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
31da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyusing namespace __tsan;  // NOLINT
32da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
33da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanystatic __thread bool expect_report;
34da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanystatic __thread bool expect_report_reported;
35da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanystatic __thread ReportType expect_report_type;
36da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
37d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukovextern "C" void *__interceptor_memcpy(void*, const void*, uptr);
38d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukovextern "C" void *__interceptor_memset(void*, int, uptr);
39d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov
40da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanystatic void *BeforeInitThread(void *param) {
41da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  (void)param;
42da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  return 0;
43da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
44da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
45da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanystatic void AtExit() {
46da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
47da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
48da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid TestMutexBeforeInit() {
49da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  // Mutexes must be usable before __tsan_init();
50da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
51da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  pthread_mutex_lock(&mtx);
52da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  pthread_mutex_unlock(&mtx);
53da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  pthread_mutex_destroy(&mtx);
54da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  pthread_t thr;
55da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  pthread_create(&thr, 0, BeforeInitThread, 0);
56da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  pthread_join(thr, 0);
57da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  atexit(AtExit);
58da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
59da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
60da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanynamespace __tsan {
61da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanybool OnReport(const ReportDesc *rep, bool suppressed) {
62da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (expect_report) {
63da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    if (rep->typ != expect_report_type) {
64da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany      printf("Expected report of type %d, got type %d\n",
65da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany             (int)expect_report_type, (int)rep->typ);
66da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany      EXPECT_FALSE("Wrong report type");
67da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany      return false;
68da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    }
69da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  } else {
70da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    EXPECT_FALSE("Unexpected report");
71da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    return false;
72da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  }
73da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  expect_report_reported = true;
74da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  return true;
75da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
76da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
77da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
78da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanystatic void* allocate_addr(int size, int offset_from_aligned = 0) {
79da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  static uintptr_t foo;
80da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  static atomic_uintptr_t uniq = {(uintptr_t)&foo};  // Some real address.
81da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  const int kAlign = 16;
82da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(offset_from_aligned < kAlign);
83da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  size = (size + 2 * kAlign) & ~(kAlign - 1);
84da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  uintptr_t addr = atomic_fetch_add(&uniq, size, memory_order_relaxed);
85da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  return (void*)(addr + offset_from_aligned);
86da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
87da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
88da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya SerebryanyMemLoc::MemLoc(int offset_from_aligned)
89da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  : loc_(allocate_addr(16, offset_from_aligned)) {
90da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
91da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
92da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya SerebryanyMemLoc::~MemLoc() {
93da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
94da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
95da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya SerebryanyMutex::Mutex(Type type)
96da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  : alive_()
97da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  , type_(type) {
98da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
99da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
100da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya SerebryanyMutex::~Mutex() {
101da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(!alive_);
102da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
103da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
104da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid Mutex::Init() {
105da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(!alive_);
106da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  alive_ = true;
107da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (type_ == Normal)
108da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(pthread_mutex_init((pthread_mutex_t*)mtx_, 0), 0);
109da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  else if (type_ == Spin)
110da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(pthread_spin_init((pthread_spinlock_t*)mtx_, 0), 0);
111da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  else if (type_ == RW)
112da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(pthread_rwlock_init((pthread_rwlock_t*)mtx_, 0), 0);
113da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  else
114da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK(0);
115da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
116da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
117da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid Mutex::StaticInit() {
118da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(!alive_);
119da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(type_ == Normal);
120da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  alive_ = true;
121da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  pthread_mutex_t tmp = PTHREAD_MUTEX_INITIALIZER;
122da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  memcpy(mtx_, &tmp, sizeof(tmp));
123da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
124da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
125da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid Mutex::Destroy() {
126da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(alive_);
127da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  alive_ = false;
128da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (type_ == Normal)
129da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(pthread_mutex_destroy((pthread_mutex_t*)mtx_), 0);
130da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  else if (type_ == Spin)
131da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(pthread_spin_destroy((pthread_spinlock_t*)mtx_), 0);
132da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  else if (type_ == RW)
133da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(pthread_rwlock_destroy((pthread_rwlock_t*)mtx_), 0);
134da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
135da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
136da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid Mutex::Lock() {
137da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(alive_);
138da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (type_ == Normal)
139da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(pthread_mutex_lock((pthread_mutex_t*)mtx_), 0);
140da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  else if (type_ == Spin)
141da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(pthread_spin_lock((pthread_spinlock_t*)mtx_), 0);
142da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  else if (type_ == RW)
143da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(pthread_rwlock_wrlock((pthread_rwlock_t*)mtx_), 0);
144da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
145da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
146da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanybool Mutex::TryLock() {
147da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(alive_);
148da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (type_ == Normal)
149da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    return pthread_mutex_trylock((pthread_mutex_t*)mtx_) == 0;
150da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  else if (type_ == Spin)
151da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    return pthread_spin_trylock((pthread_spinlock_t*)mtx_) == 0;
152da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  else if (type_ == RW)
153da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    return pthread_rwlock_trywrlock((pthread_rwlock_t*)mtx_) == 0;
154da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  return false;
155da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
156da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
157da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid Mutex::Unlock() {
158da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(alive_);
159da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (type_ == Normal)
160da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(pthread_mutex_unlock((pthread_mutex_t*)mtx_), 0);
161da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  else if (type_ == Spin)
162da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(pthread_spin_unlock((pthread_spinlock_t*)mtx_), 0);
163da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  else if (type_ == RW)
164da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(pthread_rwlock_unlock((pthread_rwlock_t*)mtx_), 0);
165da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
166da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
167da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid Mutex::ReadLock() {
168da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(alive_);
169da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(type_ == RW);
170da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK_EQ(pthread_rwlock_rdlock((pthread_rwlock_t*)mtx_), 0);
171da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
172da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
173da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanybool Mutex::TryReadLock() {
174da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(alive_);
175da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(type_ == RW);
176da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  return pthread_rwlock_tryrdlock((pthread_rwlock_t*)mtx_) ==  0;
177da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
178da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
179da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid Mutex::ReadUnlock() {
180da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(alive_);
181da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(type_ == RW);
182da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK_EQ(pthread_rwlock_unlock((pthread_rwlock_t*)mtx_), 0);
183da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
184da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
185da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanystruct Event {
186da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  enum Type {
187da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    SHUTDOWN,
188da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    READ,
189da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    WRITE,
190da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    VPTR_UPDATE,
191da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CALL,
192da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    RETURN,
193da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    MUTEX_CREATE,
194da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    MUTEX_DESTROY,
195da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    MUTEX_LOCK,
196da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    MUTEX_TRYLOCK,
197da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    MUTEX_UNLOCK,
198da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    MUTEX_READLOCK,
199da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    MUTEX_TRYREADLOCK,
200da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    MUTEX_READUNLOCK,
201da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    MEMCPY,
202da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    MEMSET
203da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  };
204da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Type type;
205da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  void *ptr;
206da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  uptr arg;
207da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  uptr arg2;
208da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  bool res;
209da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  bool expect_report;
210da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  ReportType report_type;
211da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
212da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event(Type type, const void *ptr = 0, uptr arg = 0, uptr arg2 = 0)
213da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    : type(type)
214da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    , ptr(const_cast<void*>(ptr))
215da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    , arg(arg)
216da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    , arg2(arg2)
217da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    , res()
218da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    , expect_report()
219da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    , report_type() {
220da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  }
221da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
222da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  void ExpectReport(ReportType type) {
223da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    expect_report = true;
224da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    report_type = type;
225da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  }
226da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany};
227da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
228da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanystruct ScopedThread::Impl {
229da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  pthread_t thread;
230da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  bool main;
231da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  bool detached;
232da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  atomic_uintptr_t event;  // Event*
233da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
234da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  static void *ScopedThreadCallback(void *arg);
235da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  void send(Event *ev);
236da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  void HandleEvent(Event *ev);
237da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany};
238da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
239da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::Impl::HandleEvent(Event *ev) {
240da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK_EQ(expect_report, false);
241da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  expect_report = ev->expect_report;
242da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  expect_report_reported = false;
243da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  expect_report_type = ev->report_type;
244da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  switch (ev->type) {
245da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::READ:
246da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::WRITE: {
247da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    void (*tsan_mop)(void *addr) = 0;
248da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    if (ev->type == Event::READ) {
249da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany      switch (ev->arg /*size*/) {
250da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany        case 1: tsan_mop = __tsan_read1; break;
251da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany        case 2: tsan_mop = __tsan_read2; break;
252da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany        case 4: tsan_mop = __tsan_read4; break;
253da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany        case 8: tsan_mop = __tsan_read8; break;
254da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany        case 16: tsan_mop = __tsan_read16; break;
255da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany      }
256da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    } else {
257da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany      switch (ev->arg /*size*/) {
258da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany        case 1: tsan_mop = __tsan_write1; break;
259da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany        case 2: tsan_mop = __tsan_write2; break;
260da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany        case 4: tsan_mop = __tsan_write4; break;
261da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany        case 8: tsan_mop = __tsan_write8; break;
262da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany        case 16: tsan_mop = __tsan_write16; break;
263da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany      }
264da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    }
265da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_NE(tsan_mop, 0);
266da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    errno = ECHRNG;
267da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    tsan_mop(ev->ptr);
268da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(errno, ECHRNG);  // In no case must errno be changed.
269da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
270da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  }
271da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::VPTR_UPDATE:
272da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    __tsan_vptr_update((void**)ev->ptr, (void*)ev->arg);
273da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
274da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::CALL:
275da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    __tsan_func_entry((void*)((uptr)ev->ptr));
276da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
277da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::RETURN:
278da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    __tsan_func_exit();
279da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
280da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::MUTEX_CREATE:
281da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    static_cast<Mutex*>(ev->ptr)->Init();
282da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
283da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::MUTEX_DESTROY:
284da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    static_cast<Mutex*>(ev->ptr)->Destroy();
285da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
286da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::MUTEX_LOCK:
287da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    static_cast<Mutex*>(ev->ptr)->Lock();
288da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
289da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::MUTEX_TRYLOCK:
290da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    ev->res = static_cast<Mutex*>(ev->ptr)->TryLock();
291da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
292da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::MUTEX_UNLOCK:
293da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    static_cast<Mutex*>(ev->ptr)->Unlock();
294da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
295da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::MUTEX_READLOCK:
296da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    static_cast<Mutex*>(ev->ptr)->ReadLock();
297da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
298da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::MUTEX_TRYREADLOCK:
299da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    ev->res = static_cast<Mutex*>(ev->ptr)->TryReadLock();
300da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
301da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::MUTEX_READUNLOCK:
302da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    static_cast<Mutex*>(ev->ptr)->ReadUnlock();
303da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
304da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::MEMCPY:
305d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov    __interceptor_memcpy(ev->ptr, (void*)ev->arg, ev->arg2);
306da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
307da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  case Event::MEMSET:
308d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov    __interceptor_memset(ev->ptr, ev->arg, ev->arg2);
309da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    break;
310da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  default: CHECK(0);
311da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  }
312da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (expect_report && !expect_report_reported) {
313da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    printf("Missed expected report of type %d\n", (int)ev->report_type);
314da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    EXPECT_FALSE("Missed expected race");
315da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  }
316da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  expect_report = false;
317da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
318da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
319da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid *ScopedThread::Impl::ScopedThreadCallback(void *arg) {
320da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  __tsan_func_entry(__builtin_return_address(0));
321da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Impl *impl = (Impl*)arg;
322da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  for (;;) {
323da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    Event* ev = (Event*)atomic_load(&impl->event, memory_order_acquire);
324da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    if (ev == 0) {
325da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany      pthread_yield();
326da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany      continue;
327da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    }
328da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    if (ev->type == Event::SHUTDOWN) {
329da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany      atomic_store(&impl->event, 0, memory_order_release);
330da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany      break;
331da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    }
332da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    impl->HandleEvent(ev);
333da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    atomic_store(&impl->event, 0, memory_order_release);
334da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  }
335da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  __tsan_func_exit();
336da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  return 0;
337da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
338da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
339da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::Impl::send(Event *e) {
340da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (main) {
341da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    HandleEvent(e);
342da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  } else {
343da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    CHECK_EQ(atomic_load(&event, memory_order_relaxed), 0);
344da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    atomic_store(&event, (uintptr_t)e, memory_order_release);
345da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    while (atomic_load(&event, memory_order_acquire) != 0)
346da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany      pthread_yield();
347da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  }
348da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
349da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
350da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya SerebryanyScopedThread::ScopedThread(bool detached, bool main) {
351da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_ = new Impl;
352da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->main = main;
353da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->detached = detached;
354da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  atomic_store(&impl_->event, 0, memory_order_relaxed);
355da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (!main) {
356da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    pthread_attr_t attr;
357da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    pthread_attr_init(&attr);
358da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    pthread_attr_setdetachstate(&attr, detached);
3599d2ffc2ee08216f8fad9b1bd267d1f112e0d2f01Dmitry Vyukov    pthread_attr_setstacksize(&attr, 64*1024);
360da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    pthread_create(&impl_->thread, &attr,
361da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany        ScopedThread::Impl::ScopedThreadCallback, impl_);
362da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  }
363da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
364da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
365da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya SerebryanyScopedThread::~ScopedThread() {
366da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (!impl_->main) {
367da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    Event event(Event::SHUTDOWN);
368da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    impl_->send(&event);
369da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    if (!impl_->detached)
370da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany      pthread_join(impl_->thread, 0);
371da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  }
372da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  delete impl_;
373da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
374da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
375da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::Detach() {
376da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(!impl_->main);
377da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  CHECK(!impl_->detached);
378da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->detached = true;
379da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  pthread_detach(impl_->thread);
380da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
381da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
382da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::Access(void *addr, bool is_write,
383da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany                          int size, bool expect_race) {
384da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(is_write ? Event::WRITE : Event::READ, addr, size);
385da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (expect_race)
386da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    event.ExpectReport(ReportTypeRace);
387da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
388da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
389da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
390da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::VptrUpdate(const MemLoc &vptr,
391da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany                              const MemLoc &new_val,
392da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany                              bool expect_race) {
393da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(Event::VPTR_UPDATE, vptr.loc(), (uptr)new_val.loc());
394da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (expect_race)
395da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    event.ExpectReport(ReportTypeRace);
396da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
397da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
398da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
399da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::Call(void(*pc)()) {
400da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(Event::CALL, (void*)pc);
401da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
402da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
403da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
404da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::Return() {
405da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(Event::RETURN);
406da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
407da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
408da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
409da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::Create(const Mutex &m) {
410da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(Event::MUTEX_CREATE, &m);
411da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
412da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
413da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
414da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::Destroy(const Mutex &m) {
415da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(Event::MUTEX_DESTROY, &m);
416da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
417da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
418da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
419da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::Lock(const Mutex &m) {
420da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(Event::MUTEX_LOCK, &m);
421da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
422da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
423da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
424da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanybool ScopedThread::TryLock(const Mutex &m) {
425da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(Event::MUTEX_TRYLOCK, &m);
426da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
427da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  return event.res;
428da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
429da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
430da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::Unlock(const Mutex &m) {
431da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(Event::MUTEX_UNLOCK, &m);
432da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
433da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
434da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
435da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::ReadLock(const Mutex &m) {
436da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(Event::MUTEX_READLOCK, &m);
437da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
438da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
439da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
440da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanybool ScopedThread::TryReadLock(const Mutex &m) {
441da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(Event::MUTEX_TRYREADLOCK, &m);
442da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
443da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  return event.res;
444da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
445da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
446da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::ReadUnlock(const Mutex &m) {
447da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(Event::MUTEX_READUNLOCK, &m);
448da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
449da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
450da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
451da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::Memcpy(void *dst, const void *src, int size,
452da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany                          bool expect_race) {
453da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(Event::MEMCPY, dst, (uptr)src, size);
454da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (expect_race)
455da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    event.ExpectReport(ReportTypeRace);
456da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
457da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
458da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany
459da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryanyvoid ScopedThread::Memset(void *dst, int val, int size,
460da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany                          bool expect_race) {
461da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  Event event(Event::MEMSET, dst, val, size);
462da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  if (expect_race)
463da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany    event.ExpectReport(ReportTypeRace);
464da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany  impl_->send(&event);
465da4edd850db1a333c15fc3b0abc01a2e8d2f08feKostya Serebryany}
466