1610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/*
2610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  This file is part of Valgrind, a dynamic binary instrumentation
3610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  framework.
4610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Copyright (C) 2008-2008 Google Inc
6610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov     opensource@google.com
7610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
8610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  This program is free software; you can redistribute it and/or
9610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  modify it under the terms of the GNU General Public License as
10610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  published by the Free Software Foundation; either version 2 of the
11610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  License, or (at your option) any later version.
12610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
13610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  This program is distributed in the hope that it will be useful, but
14610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  WITHOUT ANY WARRANTY; without even the implied warranty of
15610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  General Public License for more details.
17610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
18610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  You should have received a copy of the GNU General Public License
19610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  along with this program; if not, write to the Free Software
20610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  02111-1307, USA.
22610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
23610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  The GNU General Public License is contained in the file COPYING.
24610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov*/
25610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
26610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/* Author: Konstantin Serebryany <opensource@google.com>
27610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
28610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov This file contains a set of unit tests for a data race detection tool.
29610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
30610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov These tests can be compiled with pthreads (default) or
31610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov with any other library that supports threads, locks, cond vars, etc.
32610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
33610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov*/
34610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef WIN32
35610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#error "Don't build this file on Windows!"
36610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
37610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
38610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <fcntl.h>
39610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <fenv.h>
40610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <queue>
41610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <signal.h>
42610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <stdlib.h>
43610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <string>
44610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <vector>
45610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <unistd.h>
46610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
47610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef OS_linux
48610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov# include <sys/epoll.h>
49610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif  // OS_linux
50610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
51610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include "test_utils.h"
52610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <gtest/gtest.h>
53610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include "gtest_fixture_injection.h"
54610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
55610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic CondVar CV;
56610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int     COND = 0;
57610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
58610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test11: FP. Synchronization via CondVar, 2 workers. {{{1
59610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test is properly synchronized, but currently (Dec 2007)
60610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// helgrind reports a false positive.
61610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
62610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Parent:                              Worker1, Worker2:
63610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. Start(workers)                    a. read(GLOB)
64610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. MU.Lock()                         b. MU.Lock()
65610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. while(COND != 2)        /-------- c. CV.Signal()
66610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//      CV.Wait(&MU) <-------/          d. MU.Unlock()
67610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. MU.Unlock()
68610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 5. write(GLOB)
69610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
70610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test11 {
71610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
72610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
73610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
74610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(200000);
75610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != 777);
76610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
77610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
78610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND++;
79610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
80610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
81610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
82610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
83610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Parent() {
84610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
85610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
86610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker);
87610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
88610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
89610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
90610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND != 2) {
91610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
92610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
93610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
94610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
95610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
96610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
97610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
98610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
99610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
100610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, test11) {
101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  ANNOTATE_EXPECT_RACE(&GLOB, "test11. FP. Fixed by MSMProp1.");
102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test11: negative\n");
103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Parent();
104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test11
107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test75: TN. Test for sem_post, sem_wait, sem_trywait. {{{1
110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test75 {
111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovsem_t   sem[2];
113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Poster() {
115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
116610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_post(&sem[0]);
117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_post(&sem[1]);
118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_wait(&sem[0]);
122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB==1);
123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid TryWaiter() {
125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(500000);
126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_trywait(&sem[1]);
127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB==1);
128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
130610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, test75) {
131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_UNNAMED_SEM
132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_init(&sem[0], 0, 0);
133610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_init(&sem[1], 0, 0);
134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test75: negative\n");
136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThreadArray t(Poster, Waiter);
138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Start();
139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Join();
140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThreadArray t(Poster, TryWaiter);
144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Start();
145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Join();
146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_destroy(&sem[0]);
150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_destroy(&sem[1]);
151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // NO_UNNAMED_SEM
152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test75
154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test98: Synchronization via read/write (or send/recv). {{{1
157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test98 {
158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The synchronization here is done by a pair of read/write calls
159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// that create a happens-before arc. Same may be done with send/recv.
160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Such synchronization is quite unusual in real programs
161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// (why would one synchronizae via a file or socket?), but
162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// quite possible in unittests where one threads runs for producer
163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// and one for consumer.
164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A race detector has to create a happens-before arcs for
166610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// {read,send}->{write,recv} even if the file descriptors are different.
167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint fd_out = -1;
170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint fd_in  = -1;
171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
172610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
173610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(1000);
174610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
175610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  const char *str = "Hey there!\n";
176610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  const int size = strlen(str) + 1;
177610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(size == write(fd_out, str, size));
178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
180610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
181610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  char buff[100];
182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (read(fd_in, buff, 100) == 0)
183610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    sleep(1);
184610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("read: %s\n", buff);
185610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
188610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef __APPLE__
189610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Tsan for Mac OS is missing the unlink() syscall handler.
190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// TODO(glider): add the syscall handler to Valgrind.
191610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, test98) {
192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test98: negative, synchronization via I/O\n");
193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  char in_name[100];
194610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  char out_name[100];
195610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // we open two files, on for reading and one for writing,
196610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // but the files are actually the same (symlinked).
197610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sprintf(in_name,  "/tmp/racecheck_unittest_in.%d", getpid());
198610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sprintf(out_name, "/tmp/racecheck_unittest_out.%d", getpid());
199610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fd_out = creat(out_name, O_WRONLY | S_IRWXU);
200610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(0 == symlink(out_name, in_name));
201610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fd_in  = open(in_name, 0, O_RDONLY);
202610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(fd_out >= 0);
203610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(fd_in  >= 0);
204610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Writer, Reader);
205610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
206610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
207610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
208610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // cleanup
209610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  close(fd_in);
210610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  close(fd_out);
211610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  unlink(in_name);
212610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  unlink(out_name);
213610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
214610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif  // __APPLE__
215610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test98
216610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
217610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
218610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace NegativeTests_PthreadOnce {  // {{{1
219610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     *GLOB = NULL;
220610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic pthread_once_t once = PTHREAD_ONCE_INIT;
221610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Init() {
222610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = new int;
223610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(GLOB);
224610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *GLOB = 777;
225610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
226610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
227610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker0() {
228610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_once(&once, Init);
229610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
230610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
231610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
232610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_once(&once, Init);
233610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(*GLOB == 777);
234610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
235610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
236610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
237610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, PthreadOnceTest) {
238610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker0, Worker1, Worker1, Worker1);
239610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
240610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
241610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", *GLOB);
242610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
243610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
244610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
245610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
246610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test110: TP. Simple races with stack, global and heap objects. {{{1
247610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test110 {
248610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint        GLOB = 0;
249610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int STATIC;
250610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
251610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar       *STACK = 0;
252610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
253610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint       *MALLOC;
254610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint       *CALLOC;
255610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint       *REALLOC;
256610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint       *VALLOC;
257610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint       *PVALLOC;
258610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint       *MEMALIGN;
259610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint       *POSIX_MEMALIGN;
260610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint       *MMAP;
261610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
262610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint       *NEW;
263610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint       *NEW_ARR;
264610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
265610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
266610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
267610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  STATIC++;
268610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
269610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*STACK)++;
270610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
271610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*MALLOC)++;
272610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*CALLOC)++;
273610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*REALLOC)++;
274610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*VALLOC)++;
275610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*PVALLOC)++;
276610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*MEMALIGN)++;
277610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*POSIX_MEMALIGN)++;
278610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*MMAP)++;
279610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
280610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*NEW)++;
281610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*NEW_ARR)++;
282610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
283610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, test110) {
284610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test110: positive (race on a stack object)\n");
285610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
286610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  char x = 0;
287610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  STACK = &x;
288610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
289610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MALLOC = (int*)malloc(sizeof(int));
290610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CALLOC = (int*)calloc(1, sizeof(int));
291610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  REALLOC = (int*)realloc(NULL, sizeof(int));
292610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  VALLOC = (int*)valloc(sizeof(int));
293610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  PVALLOC = (int*)valloc(sizeof(int));  // TODO: pvalloc breaks helgrind.
294610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MEMALIGN = (int*)memalign(64, sizeof(int));
295610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(0 == posix_memalign((void**)&POSIX_MEMALIGN, 64, sizeof(int)));
296610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MMAP = (int*)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
297610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                    MAP_PRIVATE | MAP_ANON, -1, 0);
298610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
299610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  NEW     = new int;
300610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  NEW_ARR = new int[10];
301610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
302610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
303610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(STACK, "real race on stack object");
304610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB, "real race on global object");
305610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&STATIC, "real race on a static global object");
306610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(MALLOC, "real race on a malloc-ed object");
307610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(CALLOC, "real race on a calloc-ed object");
308610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(REALLOC, "real race on a realloc-ed object");
309610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(VALLOC, "real race on a valloc-ed object");
310610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(PVALLOC, "real race on a pvalloc-ed object");
311610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(MEMALIGN, "real race on a memalign-ed object");
312610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(POSIX_MEMALIGN, "real race on a posix_memalign-ed object");
313610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(MMAP, "real race on a mmap-ed object");
314610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
315610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(NEW, "real race on a new-ed object");
316610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(NEW_ARR, "real race on a new[]-ed object");
317610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
318610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker);
319610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
320610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
321610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tSTACK=%d\n", *STACK);
322610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB <= 3);
323610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(STATIC <= 3);
324610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
325610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(MALLOC);
326610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(CALLOC);
327610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(REALLOC);
328610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(VALLOC);
329610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(PVALLOC);
330610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(MEMALIGN);
331610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(POSIX_MEMALIGN);
332610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  munmap(MMAP, sizeof(int));
333610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete NEW;
334610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete [] NEW_ARR;
335610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
336610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test110
337610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
338610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
339610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test115: TN. sem_open. {{{1
340610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace    test115 {
341610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint tid = 0;
342610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu;
343610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst char *kSemName = "drt-test-sem";
344610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
345610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0;
346610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
347610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovsem_t *DoSemOpen() {
348610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // TODO: there is some race report inside sem_open
349610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // for which suppressions do not work... (???)
350610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_IGNORE_WRITES_BEGIN();
351610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_t *sem = sem_open(kSemName, O_CREAT, 0600, 3);
352610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_IGNORE_WRITES_END();
353610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return sem;
354610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
355610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
356610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
357610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Lock();
358610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int my_tid = tid++;
359610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
360610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
361610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (my_tid == 0) {
362610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB = 1;
363610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
364610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
365610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // if the detector observes a happens-before arc between
366610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // sem_open and sem_wait, it will be silent.
367610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_t *sem = DoSemOpen();
368610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
369610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(sem != SEM_FAILED);
370610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(sem_wait(sem) == 0);
371610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
372610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (my_tid > 0) {
373610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(GLOB == 1);
374610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
375610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
376610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
377610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef __APPLE__
378610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/* This test is disabled for Darwin because of the tricky implementation of
379610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * sem_open on that platform: subsequent attempts to open an existing semafore
380610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * create new ones. */
381610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, test115) {
382610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test115: stab (sem_open())\n");
383610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
384610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // just check that sem_open is not completely broken
385610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_unlink(kSemName);
386610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_t* sem = DoSemOpen();
387610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(sem != SEM_FAILED);
388610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(sem_wait(sem) == 0);
389610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_unlink(kSemName);
390610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
391610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // check that sem_open and sem_wait create a happens-before arc.
392610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker);
393610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
394610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
395610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // clean up
396610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sem_unlink(kSemName);
397610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
398610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif  // __APPLE__
399610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test115
400610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
401610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
402610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test122 TP: Simple test with RWLock {{{1
403610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace  test122 {
404610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     VAR1 = 0;
405610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     VAR2 = 0;
406610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovRWLock mu;
407610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
408610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid WriteWhileHoldingReaderLock(int *p) {
409610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
410610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ReaderLockScoped lock(&mu);  // Reader lock for writing. -- bug.
411610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*p)++;
412610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
413610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
414610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid CorrectWrite(int *p) {
415610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  WriterLockScoped lock(&mu);
416610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*p)++;
417610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
418610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
419610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() { WriteWhileHoldingReaderLock(&VAR1); }
420610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() { CorrectWrite(&VAR1); }
421610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread3() { CorrectWrite(&VAR2); }
422610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread4() { WriteWhileHoldingReaderLock(&VAR2); }
423610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
424610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
425610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, test122) {
426610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test122: positive (rw-lock)\n");
427610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  VAR1 = 0;
428610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  VAR2 = 0;
429610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&VAR1);
430610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&VAR2);
431610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (!Tsan_PureHappensBefore()) {
432610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR1, "test122. TP. ReaderLock-ed while writing");
433610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR2, "test122. TP. ReaderLock-ed while writing");
434610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
435610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Thread1, Thread2, Thread3, Thread4);
436610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
437610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
438610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
439610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test122
440610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
441610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
442610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test125 TN: Backwards lock (annotated). {{{1
443610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test125 {
444610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test uses "Backwards mutex" locking protocol.
445610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// We take a *reader* lock when writing to a per-thread data
446610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// (GLOB[thread_num])  and we take a *writer* lock when we
447610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// are reading from the entire array at once.
448610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
449610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Such locking protocol is not understood by ThreadSanitizer's
450610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// hybrid state machine. So, you either have to use a pure-happens-before
451610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// detector ("tsan --pure-happens-before") or apply pure happens-before mode
452610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// to this particular lock by using ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu).
453610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
454610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int n_threads = 3;
455610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovRWLock   mu;
456610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB[n_threads];
457610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
458610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint adder_num; // updated atomically.
459610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
460610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Adder() {
461610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int my_num = AtomicIncrement(&adder_num, 1) - 1;
462610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(my_num >= 0);
463610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(my_num < n_threads);
464610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
465610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ReaderLockScoped lock(&mu);
466610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB[my_num]++;
467610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
468610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
469610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Aggregator() {
470610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int sum = 0;
471610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
472610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    WriterLockScoped lock(&mu);
473610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < n_threads; i++) {
474610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      sum += GLOB[i];
475610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
476610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
477610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("sum=%d\n", sum);
478610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
479610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
480610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, test125) {
481610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test125: negative\n");
482610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
483610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu);
484610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
485610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // run Adders, then Aggregator
486610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  adder_num = 0;
487610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
488610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThreadArray t(Adder, Adder, Adder, Aggregator);
489610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Start();
490610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Join();
491610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
492610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
493610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Run Aggregator first.
494610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  adder_num = 0;
495610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
496610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThreadArray t(Aggregator, Adder, Adder, Adder);
497610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Start();
498610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Join();
499610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
500610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
501610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
502610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test125
503610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
504610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
505610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace MmapTest {  // {{{1
506610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
507610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kMmapSize =  65536;
508610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
509610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid SubWorker() {
510610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 500; i++) {
511610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int *ptr = (int*)mmap(NULL, kMmapSize, PROT_READ | PROT_WRITE,
512610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                          MAP_PRIVATE | MAP_ANON, -1, 0);
513610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    *ptr = 42;
514610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    munmap(ptr, kMmapSize);
515610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
516610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
517610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
518610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
519610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(SubWorker, SubWorker, SubWorker, SubWorker);
520610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
521610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
522610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
523610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
524610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker1, Worker1, Worker1);
525610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
526610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
527610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
528610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
529610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, MmapTest) {
530610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker, Worker);
531610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
532610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
533610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
534610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
535610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
536610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
537610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A regression test for mmap/munmap handling in Pin.
538610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// If the tool misses munmap() calls it may report a false positive if two
539610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// threads map the same memory region.
540610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace MmapRegressionTest {  // {{{1
541610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
542610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kMmapSize =  65536;
543610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst uintptr_t kStartAddress = 0x10000;
544610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
545610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n1;
546610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
547610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
548610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int *ptr = (int*)mmap((void*)kStartAddress, kMmapSize,
549610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                          PROT_READ | PROT_WRITE,
550610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                          MAP_PRIVATE | MAP_ANON, -1, 0);
551610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    *ptr = 42;
552610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    munmap(ptr, kMmapSize);
553610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
554610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
555610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, MmapRegressionTest) {
556610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker);
557610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
558610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
559610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
560610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
561610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
562610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
563610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test136. Unlock twice. {{{1
564610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test136 {
565610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(LockTests, UnlockTwice) {
566610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutexattr_t attr;
567610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(0 == pthread_mutexattr_init(&attr));
568610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(0 == pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK));
569610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
570610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutex_t mu;
571610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(0 == pthread_mutex_init(&mu, &attr));
572610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(0 == pthread_mutex_lock(&mu));
573610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(0 == pthread_mutex_unlock(&mu));
574610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int ret_unlock = pthread_mutex_unlock(&mu);  // unlocking twice.
575610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int ret_destroy = pthread_mutex_destroy(&mu);
576610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("  pthread_mutex_unlock returned %d\n", ret_unlock);
577610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("  pthread_mutex_destroy returned %d\n", ret_destroy);
578610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
579610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test136
580610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
581610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
582610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test141 FP. unlink/fopen, rmdir/opendir. {{{1
583610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test141 {
584610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB1 = 0,
585610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB2 = 0;
586610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar *dir_name = NULL,
587610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov     *filename = NULL;
588610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
589610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker1() {
590610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
591610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB1 = 1;  // Write
592610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // unlink deletes a file 'filename'
593610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // which exits spin-loop in Waiter1().
594610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("  Deleting file...\n");
595610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(unlink(filename) == 0);
596610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
597610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
598610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter1() {
599610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  FILE *tmp;
600610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while ((tmp = fopen(filename, "r")) != NULL) {
601610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    fclose(tmp);
602610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(10000);
603610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
604610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("  ...file has been deleted\n");
605610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB1 = 2;  // Write
606610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
607610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
608610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker2() {
609610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
610610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB2 = 1;  // Write
611610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // rmdir deletes a directory 'dir_name'
612610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // which exit spin-loop in Waker().
613610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("  Deleting directory...\n");
614610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(rmdir(dir_name) == 0);
615610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
616610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
617610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter2() {
618610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  DIR *tmp;
619610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while ((tmp = opendir(dir_name)) != NULL) {
620610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    closedir(tmp);
621610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(10000);
622610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
623610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("  ...directory has been deleted\n");
624610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB2 = 2;
625610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
626610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
627610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, test141) {
628610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test141: FP. unlink/fopen, rmdir/opendir.\n");
629610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
630610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  dir_name = strdup("/tmp/tsan-XXXXXX");
631610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(mkdtemp(dir_name) != 0);
632610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
633610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  filename = strdup((std::string() + dir_name + "/XXXXXX").c_str());
634610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  const int fd = mkstemp(filename);
635610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(fd >= 0);
636610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  close(fd);
637610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
638610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta1(Waker1, Waiter1);
639610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta1.Start();
640610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta1.Join();
641610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
642610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta2(Waker2, Waiter2);
643610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta2.Start();
644610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta2.Join();
645610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
646610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(filename);
647610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  filename = 0;
648610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(dir_name);
649610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  dir_name = 0;
650610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
651610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test141
652610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
653610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
654610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test146: TP. Unit test for RWLock::TryLock and RWLock::ReaderTryLock. {{{1
655610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test146 {
656610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Worker1 locks the globals for writing for a long time.
657610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Worker2 tries to write to globals twice: without a writer lock and with it.
658610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Worker3 tries to read from globals twice: without a reader lock and with it.
659610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB1 = 0;
660610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar    padding1[64];
661610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB2 = 0;
662610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar    padding2[64];
663610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB3 = 0;
664610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar    padding3[64];
665610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB4 = 0;
666610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovRWLock  MU;
667610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n1, n2, n3, n4, n5;
668610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
669610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
670610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
671610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB1 = 1;
672610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB2 = 1;
673610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB3 = 1;
674610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB4 = 1;
675610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.signal();
676610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.wait();
677610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n3.wait();
678610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
679610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n4.signal();
680610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
681610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
682610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
683610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.wait();
684610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (MU.TryLock()) CHECK(0);
685610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  else
686610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB1 = 2;
687610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.signal();
688610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n5.wait();
689610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (MU.TryLock()) {
690610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB2 = 2;
691610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Unlock();
692610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } else {
693610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(0);
694610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
695610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
696610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
697610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker3() {
698610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.wait();
699610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (MU.ReaderTryLock()) CHECK(0);
700610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  else
701610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("\treading GLOB3: %d\n", GLOB3);
702610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n3.signal();
703610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n4.wait();
704610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (MU.ReaderTryLock()) {
705610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("\treading GLOB4: %d\n", GLOB4);
706610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.ReaderUnlock();
707610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } else {
708610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(0);
709610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
710610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n5.signal();
711610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
712610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
713610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, test146) {
714610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB1, "test146. TP: a data race on GLOB1.");
715610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB3, "test146. TP: a data race on GLOB3.");
716610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB1);
717610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB2);
718610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB3);
719610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB4);
720610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test146: positive\n");
721610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2, Worker3);
722610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
723610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
724610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB1=%d\n", GLOB1);
725610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB2=%d\n", GLOB2);
726610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB3=%d\n", GLOB3);
727610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB4=%d\n", GLOB4);
728610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
729610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test146
730610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
731610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PositiveTests_CyclicBarrierTest {  // {{{1
732610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_BARRIER
733610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// regression test for correct support of cyclic barrier.
734610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test was suggested by Julian Seward.
735610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// There is a race on L here between a1 and b1,
736610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// but a naive support of barrier makes us miss this race.
737610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovpthread_barrier_t B;
738610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint L;
739610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
740610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A1/A2: write L, then wait for barrier, then sleep
741610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid a1() {
742610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  L = 1;
743610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_barrier_wait(&B);
744610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sleep(1);
745610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
746610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid a2() {
747610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_barrier_wait(&B);
748610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sleep(1);
749610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
750610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
751610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// B1/B2: sleep, wait for barrier, then write L
752610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid b1() {
753610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sleep(1);
754610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_barrier_wait(&B);
755610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  L = 1;
756610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
757610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid b2() {
758610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sleep(1);
759610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_barrier_wait(&B);
760610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
761610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
762610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, CyclicBarrierTest) {
763610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&L, "real race, may be hidden"
764610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                                " by incorrect implementation of barrier");
765610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_barrier_init(&B, NULL, 3);
766610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t1(a1, a2, a2),
767610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                t2(b1, b2, b2);
768610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Start();
769610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t2.Start();
770610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Join();
771610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t2.Join();
772610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
773610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
774610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
775610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint *G = NULL;
776610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
777610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
778610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_barrier_wait(&B);
779610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*G) = 1;
780610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_barrier_wait(&B);
781610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
782610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
783610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, CyclicBarrierTwoCallsTest) {
784610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_barrier_init(&B, NULL, 2);
785610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  G = new int(0);
786610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(G);
787610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(G, "real race, may be hidden"
788610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                                " by incorrect implementation of barrier");
789610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t1(Worker, Worker);
790610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Start();
791610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Join();
792610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(*G == 1);
793610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete G;
794610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
795610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
796610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
797610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
798610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif  // NO_BARRIER
799610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
800610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
801610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, Mmap84GTest) {  // {{{1
802610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef ARCH_amd64
803610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef OS_linux
804610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // test that we can mmap 84G and can do it fast.
805610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  size_t size = (1ULL << 32) * 21;  // 21 * 4G
806610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void *mem_ptr = mmap((void *) 0,
807610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                       size,
808610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                       PROT_EXEC | PROT_READ | PROT_WRITE,
809610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                       MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE,
810610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                       -1,
811610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                       (off_t) 0);
812610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("res=%p\n", mem_ptr);
813610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
814610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
815610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
816610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
817610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace NegativeTests_PthreadCreateFailureTest {  // {{{1
818610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef OS_linux
819610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid* ThreadRoutine(void *) {
820610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return NULL;
821610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
822610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
823610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, PthreadCreateFailureTest) {
824610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_attr_t attributes;
825610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_attr_init(&attributes);
826610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_attr_setstacksize(&attributes, -1);
827610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_t handle;
828610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(pthread_create(&handle, &attributes, ThreadRoutine, NULL) != 0);
829610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_attr_destroy(&attributes);
830610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
831610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif  // OS_linux
832610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace NegativeTests_PthreadCreateFailureTest
833610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
834610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace Signals {  // {{{1
835610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
836610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovtypedef void (*Sigaction)(int, siginfo_t *, void *);
837610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
838610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
839610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
840610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic void EnableSigprof(Sigaction SignalHandler) {
841610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  struct sigaction sa;
842610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sa.sa_sigaction = SignalHandler;
843610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sa.sa_flags = SA_RESTART | SA_SIGINFO;
844610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sigemptyset(&sa.sa_mask);
845610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (sigaction(SIGPROF, &sa, NULL) != 0) {
846610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    perror("sigaction");
847610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    abort();
848610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
849610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  struct itimerval timer;
850610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  timer.it_interval.tv_sec = 0;
851610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  timer.it_interval.tv_usec = 1000000 / 10000;
852610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  timer.it_value = timer.it_interval;
853610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (setitimer(ITIMER_PROF, &timer, 0) != 0) {
854610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    perror("setitimer");
855610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    abort();
856610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
857610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
858610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
859610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic void DisableSigprof() {
860610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Disable the profiling timer.
861610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  struct itimerval timer;
862610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  timer.it_interval.tv_sec = 0;
863610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  timer.it_interval.tv_usec = 0;
864610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  timer.it_value = timer.it_interval;
865610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (setitimer(ITIMER_PROF, &timer, 0) != 0) {
866610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    perror("setitimer");
867610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    abort();
868610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
869610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Ignore SIGPROFs from now on.
870610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  struct sigaction sa;
871610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sa.sa_handler = SIG_IGN;
872610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sa.sa_flags = SA_RESTART | SA_SIGINFO;
873610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sigemptyset(&sa.sa_mask);
874610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (sigaction(SIGPROF, &sa, NULL) != 0) {
875610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    perror("sigaction");
876610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    abort();
877610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
878610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
879610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
880610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid MallocTestWorker() {
881610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 100000; i++) {
882610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    void *x = malloc((i % 64) + 1);
883610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    free (x);
884610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
885610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
886610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
887610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Regression test for
888610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// http://code.google.com/p/data-race-test/issues/detail?id=13 .
889610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Make sure that locking events are handled in signal handlers.
890610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
891610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// For some reason, invoking the signal handlers causes deadlocks on Mac OS.
892610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef __APPLE__
893610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu;
894610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
895610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid SignalHandlerWithMutex(int, siginfo_t*, void*) {
896610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Lock();
897610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
898610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
899610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
900610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
901610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(Signals, SignalsAndMallocTestWithMutex) {
902610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EnableSigprof(SignalHandlerWithMutex);
903610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(MallocTestWorker, MallocTestWorker, MallocTestWorker);
904610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
905610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
906610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
907610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  DisableSigprof();
908610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
909610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
910610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
911610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Another regression test for
912610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// http://code.google.com/p/data-race-test/issues/detail?id=13 .
913610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Make sure that locking events are handled in signal handlers.
914610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovSpinLock sl;
915610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
916610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid SignalHandlerWithSpinlock(int, siginfo_t*, void*) {
917610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sl.Lock();
918610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
919610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sl.Unlock();
920610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
921610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
922610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(Signals, DISABLED_SignalsAndMallocTestWithSpinlock) {
923610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EnableSigprof(SignalHandlerWithSpinlock);
924610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(MallocTestWorker, MallocTestWorker, MallocTestWorker);
925610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
926610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
927610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
928610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  DisableSigprof();
929610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
930610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
931610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Regression test for
932610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// http://code.google.com/p/data-race-test/issues/detail?id=14.
933610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic void WaitTestSignalHandler(int, siginfo_t*, void*) {
934610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_HAPPENS_AFTER((void*)0x1234);
935610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
936610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
937610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid WaitTestWorker() {
938610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 1000000; i++) {
939610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_HAPPENS_AFTER((void*)0x1234);
940610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
941610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
942610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
943610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(Signals, SignalsAndWaitTest) {
944610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EnableSigprof(WaitTestSignalHandler);
945610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(WaitTestWorker, WaitTestWorker, WaitTestWorker);
946610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
947610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
948610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  DisableSigprof();
949610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
950610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
951610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef __APPLE__
952610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// this test crashes on Mac in debug TSan build, see
953610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// http://code.google.com/p/data-race-test/issues/detail?id=47
954610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovpid_t child_pid = 0;
955610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
956610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid child_handler(int signum) {
957610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (signum == SIGCHLD && child_pid == 0) {
958610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("Whoops, PID shouldn't be 0!\n");
959610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
960610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
961610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
962610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(Signals, PositiveTests_RaceInSignal) {
963610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Currently the data race on child_pid can't be found,
964610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // see http://code.google.com/p/data-race-test/issues/detail?id=46
965610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //ANNOTATE_EXPECT_RACE(&child_pid, "Race on pid: fork vs signal handler");
966610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  signal(SIGCHLD, child_handler);
967610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  child_pid = fork();
968610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (child_pid == 0) {
969610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // in child
970610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    exit(0);
971610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
972610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  wait(NULL);
973610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
974610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif  // __APPLE__
975610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
976610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace;
977610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
978610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(WeirdSizesTests, FegetenvTest) {
979610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // http://code.google.com/p/data-race-test/issues/detail?id=36
980610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fenv_t tmp;
981610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (fegetenv(&tmp) != 0)
982610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    FAIL() << "fegetenv failed";
983610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
984610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
985610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace NegativeTests_epoll {  // {{{1
986610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef OS_linux
987610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB;
988610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
989610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Currently, ThreadSanitizer should create hb arcs between
990610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// epoll_ctl and epoll_wait regardless of the parameters. Check that.
991610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
992610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
993610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
994610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  struct epoll_event event;
995610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  epoll_ctl(0, 0, 0, &event);
996610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
997610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
998610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  struct epoll_event event;
999610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  epoll_wait(0, &event, 0, 0);
1000610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1001610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1002610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1003610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests,epollTest) {
1004610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta(Worker1, Worker2);
1005610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Start();
1006610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Join();
1007610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1008610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif  // OS_linux
1009610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1010610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace NegativeTests_LockfTest {  // {{{1
1011610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1012610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass ShmMutex {
1013610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public:
1014610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ShmMutex() : fd_(-1) { }
1015610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void set_fd(int fd) {
1016610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(fd_ == -1);
1017610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    fd_ = fd;
1018610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
1019610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void Lock() {
1020610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    LockOrUnlockInternal(true);
1021610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
1022610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void Unlock() {
1023610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    LockOrUnlockInternal(false);
1024610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
1025610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private:
1026610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void LockOrUnlockInternal(bool lock) {
1027610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(fd_ >= 0);
1028610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    while (lockf(fd_, lock ? F_LOCK : F_ULOCK, 0) < 0) {
1029610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (errno == EINTR) {
1030610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        continue;
1031610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      } else if (errno == ENOLCK) {
1032610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        usleep(5000);
1033610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        continue;
1034610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
1035610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      CHECK(0);
1036610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1037610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1038610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
1039610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1040610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int fd_;
1041610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} mu;
1042610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1043610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB;
1044610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1045610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
1046610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Lock();
1047610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1048610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
1049610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1050610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1051610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests,DISABLED_LockfTest) {
1052610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.set_fd(1 /* stdout */);
1053610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta(Worker, Worker);
1054610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Start();
1055610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Join();
1056610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1057610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1058610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1059610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PositiveTests_LockThenNoLock {  // {{{1
1060610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Regression test for a bug fixed by r2312
1061610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB;
1062610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovpthread_mutex_t mu;
1063610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n1, n2;
1064610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1065610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
1066610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutex_lock(&mu);
1067610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
1068610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutex_unlock(&mu);
1069610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.signal();
1070610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.wait();
1071610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
1072610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1073610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1074610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
1075610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutex_lock(&mu);
1076610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 3;
1077610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutex_unlock(&mu);
1078610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.signal();
1079610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.wait();
1080610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 4;
1081610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1082610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1083610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, LockThenNoLock) {
1084610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutex_init(&mu, NULL);
1085610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB);
1086610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB, "race");
1087610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NOT_HAPPENS_BEFORE_MUTEX(&mu);
1088610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
1089610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1090610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1091610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutex_destroy(&mu);
1092610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1093610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
1094610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1095610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef __APPLE__
1096610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace NegativeTests_PthreadCondWaitRelativeNp {  // {{{1
1097610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0;
1098610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovpthread_mutex_t mu;
1099610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovpthread_cond_t cv;
1100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
1102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  struct timespec tv = {1000, 1000};
1103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutex_lock(&mu);
1104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_cond_timedwait_relative_np(&cv, &mu, &tv);
1105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
1106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutex_unlock(&mu);
1107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
1110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutex_lock(&mu);
1111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
1112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_cond_signal(&cv);
1113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutex_unlock(&mu);
1114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1116610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, PthreadCondWaitRelativeNpTest) {
1117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutex_init(&mu, NULL);
1118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_cond_init(&cv, NULL);
1119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Waiter, Waker);
1120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_mutex_destroy(&mu);
1123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_cond_destroy(&cv);
1124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
1126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif  // __APPLE__
1127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PositiveTests_RWLockVsRWLockTest {  // {{{1
1129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Test that reader lock/unlock do not create a hb-arc.
1130610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovRWLock mu;
1131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB;
1132610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n;
1133610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() {
1135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
1136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.ReaderLock();
1137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.ReaderUnlock();
1138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.signal();
1139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() {
1142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.wait();
1143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.ReaderLock();
1144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.ReaderUnlock();
1145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
1146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1148610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RWLockVsRWLockTest) {
1149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu);
1150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB, "rwunlock/rwlock is not a hb-arc");
1151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Thread1, Thread2);
1152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
1157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace TSDTests {
1159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Test the support for libpthread TSD destructors.
1160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovpthread_key_t key;
1161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kInitialValue = 0xfeedface;
1162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint tsd_array[2];
1163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Destructor(void *ptr) {
1165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int *write = (int*) ptr;
1166610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *write = kInitialValue;
1167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoWork(int index) {
1170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int *value = &(tsd_array[index]);
1171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *value = 42;
1172610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_setspecific(key, value);
1173610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int *read = (int*) pthread_getspecific(key);
1174610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(read == value);
1175610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1176610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1177610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker0() { DoWork(0); }
1178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() { DoWork(1); }
1179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1180610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(TSDTests, TSDDestructorTest) {
1181610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_key_create(&key, Destructor);
1182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker0, Worker1);
1183610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1184610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1185610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 2; ++i) {
1186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(tsd_array[i] == kInitialValue);
1187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
1188610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1189610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1191610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// End {{{1
1193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker
1194