• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2   This file is part of Valgrind, a dynamic binary instrumentation
3   framework.
4 
5   Copyright (C) 2008-2008 Google Inc
6      opensource@google.com
7 
8   This program is free software; you can redistribute it and/or
9   modify it under the terms of the GNU General Public License as
10   published by the Free Software Foundation; either version 2 of the
11   License, or (at your option) any later version.
12 
13   This program is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   General Public License for more details.
17 
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21   02111-1307, USA.
22 
23   The GNU General Public License is contained in the file COPYING.
24 */
25 
26 /* Author: Konstantin Serebryany <opensource@google.com>
27 
28  This file contains a set of unit tests for a data race detection tool.
29 
30  These tests can be compiled with pthreads (default) or
31  with any other library that supports threads, locks, cond vars, etc.
32 
33 */
34 #ifdef WIN32
35 #error "Don't build this file on Windows!"
36 #endif
37 
38 #include <fcntl.h>
39 #include <fenv.h>
40 #include <queue>
41 #include <signal.h>
42 #include <stdlib.h>
43 #include <string>
44 #include <vector>
45 #include <unistd.h>
46 
47 #ifdef OS_linux
48 # include <sys/epoll.h>
49 #endif  // OS_linux
50 
51 #include "test_utils.h"
52 #include <gtest/gtest.h>
53 #include "gtest_fixture_injection.h"
54 
55 static CondVar CV;
56 static int     COND = 0;
57 
58 // test11: FP. Synchronization via CondVar, 2 workers. {{{1
59 // This test is properly synchronized, but currently (Dec 2007)
60 // helgrind reports a false positive.
61 //
62 // Parent:                              Worker1, Worker2:
63 // 1. Start(workers)                    a. read(GLOB)
64 // 2. MU.Lock()                         b. MU.Lock()
65 // 3. while(COND != 2)        /-------- c. CV.Signal()
66 //      CV.Wait(&MU) <-------/          d. MU.Unlock()
67 // 4. MU.Unlock()
68 // 5. write(GLOB)
69 //
70 namespace test11 {
71 int     GLOB = 0;
72 Mutex   MU;
Worker()73 void Worker() {
74   usleep(200000);
75   CHECK(GLOB != 777);
76 
77   MU.Lock();
78   COND++;
79   CV.Signal();
80   MU.Unlock();
81 }
82 
Parent()83 void Parent() {
84   COND = 0;
85 
86   MyThreadArray t(Worker, Worker);
87   t.Start();
88 
89   MU.Lock();
90   while(COND != 2) {
91     CV.Wait(&MU);
92   }
93   MU.Unlock();
94 
95   GLOB = 2;
96 
97   t.Join();
98 }
99 
TEST(NegativeTests,test11)100 TEST(NegativeTests, test11) {
101 //  ANNOTATE_EXPECT_RACE(&GLOB, "test11. FP. Fixed by MSMProp1.");
102   printf("test11: negative\n");
103   Parent();
104   printf("\tGLOB=%d\n", GLOB);
105 }
106 }  // namespace test11
107 
108 
109 // test75: TN. Test for sem_post, sem_wait, sem_trywait. {{{1
110 namespace test75 {
111 int     GLOB = 0;
112 sem_t   sem[2];
113 
Poster()114 void Poster() {
115   GLOB = 1;
116   sem_post(&sem[0]);
117   sem_post(&sem[1]);
118 }
119 
Waiter()120 void Waiter() {
121   sem_wait(&sem[0]);
122   CHECK(GLOB==1);
123 }
TryWaiter()124 void TryWaiter() {
125   usleep(500000);
126   sem_trywait(&sem[1]);
127   CHECK(GLOB==1);
128 }
129 
TEST(NegativeTests,test75)130 TEST(NegativeTests, test75) {
131 #ifndef NO_UNNAMED_SEM
132   sem_init(&sem[0], 0, 0);
133   sem_init(&sem[1], 0, 0);
134 
135   printf("test75: negative\n");
136   {
137     MyThreadArray t(Poster, Waiter);
138     t.Start();
139     t.Join();
140   }
141   GLOB = 2;
142   {
143     MyThreadArray t(Poster, TryWaiter);
144     t.Start();
145     t.Join();
146   }
147   printf("\tGLOB=%d\n", GLOB);
148 
149   sem_destroy(&sem[0]);
150   sem_destroy(&sem[1]);
151 #endif // NO_UNNAMED_SEM
152 }
153 }  // namespace test75
154 
155 
156 // test98: Synchronization via read/write (or send/recv). {{{1
157 namespace test98 {
158 // The synchronization here is done by a pair of read/write calls
159 // that create a happens-before arc. Same may be done with send/recv.
160 // Such synchronization is quite unusual in real programs
161 // (why would one synchronizae via a file or socket?), but
162 // quite possible in unittests where one threads runs for producer
163 // and one for consumer.
164 //
165 // A race detector has to create a happens-before arcs for
166 // {read,send}->{write,recv} even if the file descriptors are different.
167 //
168 int     GLOB = 0;
169 int fd_out = -1;
170 int fd_in  = -1;
171 
Writer()172 void Writer() {
173   usleep(1000);
174   GLOB = 1;
175   const char *str = "Hey there!\n";
176   const int size = strlen(str) + 1;
177   CHECK(size == write(fd_out, str, size));
178 }
179 
Reader()180 void Reader() {
181   char buff[100];
182   while (read(fd_in, buff, 100) == 0)
183     sleep(1);
184   printf("read: %s\n", buff);
185   GLOB = 2;
186 }
187 
188 #ifndef __APPLE__
189 // Tsan for Mac OS is missing the unlink() syscall handler.
190 // TODO(glider): add the syscall handler to Valgrind.
TEST(NegativeTests,test98)191 TEST(NegativeTests, test98) {
192   printf("test98: negative, synchronization via I/O\n");
193   char in_name[100];
194   char out_name[100];
195   // we open two files, on for reading and one for writing,
196   // but the files are actually the same (symlinked).
197   sprintf(in_name,  "/tmp/racecheck_unittest_in.%d", getpid());
198   sprintf(out_name, "/tmp/racecheck_unittest_out.%d", getpid());
199   fd_out = creat(out_name, O_WRONLY | S_IRWXU);
200   CHECK(0 == symlink(out_name, in_name));
201   fd_in  = open(in_name, 0, O_RDONLY);
202   CHECK(fd_out >= 0);
203   CHECK(fd_in  >= 0);
204   MyThreadArray t(Writer, Reader);
205   t.Start();
206   t.Join();
207   printf("\tGLOB=%d\n", GLOB);
208   // cleanup
209   close(fd_in);
210   close(fd_out);
211   unlink(in_name);
212   unlink(out_name);
213 }
214 #endif  // __APPLE__
215 }  // namespace test98
216 
217 
218 namespace NegativeTests_PthreadOnce {  // {{{1
219 int     *GLOB = NULL;
220 static pthread_once_t once = PTHREAD_ONCE_INIT;
Init()221 void Init() {
222   GLOB = new int;
223   ANNOTATE_TRACE_MEMORY(GLOB);
224   *GLOB = 777;
225 }
226 
Worker0()227 void Worker0() {
228   pthread_once(&once, Init);
229 }
Worker1()230 void Worker1() {
231   usleep(100000);
232   pthread_once(&once, Init);
233   CHECK(*GLOB == 777);
234 }
235 
236 
TEST(NegativeTests,PthreadOnceTest)237 TEST(NegativeTests, PthreadOnceTest) {
238   MyThreadArray t(Worker0, Worker1, Worker1, Worker1);
239   t.Start();
240   t.Join();
241   printf("\tGLOB=%d\n", *GLOB);
242 }
243 }  // namespace
244 
245 
246 // test110: TP. Simple races with stack, global and heap objects. {{{1
247 namespace test110 {
248 int        GLOB = 0;
249 static int STATIC;
250 
251 char       *STACK = 0;
252 
253 int       *MALLOC;
254 int       *CALLOC;
255 int       *REALLOC;
256 int       *VALLOC;
257 int       *PVALLOC;
258 int       *MEMALIGN;
259 int       *POSIX_MEMALIGN;
260 int       *MMAP;
261 
262 int       *NEW;
263 int       *NEW_ARR;
264 
Worker()265 void Worker() {
266   GLOB++;
267   STATIC++;
268 
269   (*STACK)++;
270 
271   (*MALLOC)++;
272   (*CALLOC)++;
273   (*REALLOC)++;
274   (*VALLOC)++;
275   (*PVALLOC)++;
276   (*MEMALIGN)++;
277   (*POSIX_MEMALIGN)++;
278   (*MMAP)++;
279 
280   (*NEW)++;
281   (*NEW_ARR)++;
282 }
TEST(PositiveTests,test110)283 TEST(PositiveTests, test110) {
284   printf("test110: positive (race on a stack object)\n");
285 
286   char x = 0;
287   STACK = &x;
288 
289   MALLOC = (int*)malloc(sizeof(int));
290   CALLOC = (int*)calloc(1, sizeof(int));
291   REALLOC = (int*)realloc(NULL, sizeof(int));
292   VALLOC = (int*)valloc(sizeof(int));
293   PVALLOC = (int*)valloc(sizeof(int));  // TODO: pvalloc breaks helgrind.
294   MEMALIGN = (int*)memalign(64, sizeof(int));
295   CHECK(0 == posix_memalign((void**)&POSIX_MEMALIGN, 64, sizeof(int)));
296   MMAP = (int*)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
297                     MAP_PRIVATE | MAP_ANON, -1, 0);
298 
299   NEW     = new int;
300   NEW_ARR = new int[10];
301 
302 
303   ANNOTATE_EXPECT_RACE(STACK, "real race on stack object");
304   ANNOTATE_EXPECT_RACE(&GLOB, "real race on global object");
305   ANNOTATE_EXPECT_RACE(&STATIC, "real race on a static global object");
306   ANNOTATE_EXPECT_RACE(MALLOC, "real race on a malloc-ed object");
307   ANNOTATE_EXPECT_RACE(CALLOC, "real race on a calloc-ed object");
308   ANNOTATE_EXPECT_RACE(REALLOC, "real race on a realloc-ed object");
309   ANNOTATE_EXPECT_RACE(VALLOC, "real race on a valloc-ed object");
310   ANNOTATE_EXPECT_RACE(PVALLOC, "real race on a pvalloc-ed object");
311   ANNOTATE_EXPECT_RACE(MEMALIGN, "real race on a memalign-ed object");
312   ANNOTATE_EXPECT_RACE(POSIX_MEMALIGN, "real race on a posix_memalign-ed object");
313   ANNOTATE_EXPECT_RACE(MMAP, "real race on a mmap-ed object");
314 
315   ANNOTATE_EXPECT_RACE(NEW, "real race on a new-ed object");
316   ANNOTATE_EXPECT_RACE(NEW_ARR, "real race on a new[]-ed object");
317 
318   MyThreadArray t(Worker, Worker, Worker);
319   t.Start();
320   t.Join();
321   printf("\tSTACK=%d\n", *STACK);
322   CHECK(GLOB <= 3);
323   CHECK(STATIC <= 3);
324 
325   free(MALLOC);
326   free(CALLOC);
327   free(REALLOC);
328   free(VALLOC);
329   free(PVALLOC);
330   free(MEMALIGN);
331   free(POSIX_MEMALIGN);
332   munmap(MMAP, sizeof(int));
333   delete NEW;
334   delete [] NEW_ARR;
335 }
336 }  // namespace test110
337 
338 
339 // test115: TN. sem_open. {{{1
340 namespace    test115 {
341 int tid = 0;
342 Mutex mu;
343 const char *kSemName = "drt-test-sem";
344 
345 int GLOB = 0;
346 
DoSemOpen()347 sem_t *DoSemOpen() {
348   // TODO: there is some race report inside sem_open
349   // for which suppressions do not work... (???)
350   ANNOTATE_IGNORE_WRITES_BEGIN();
351   sem_t *sem = sem_open(kSemName, O_CREAT, 0600, 3);
352   ANNOTATE_IGNORE_WRITES_END();
353   return sem;
354 }
355 
Worker()356 void Worker() {
357   mu.Lock();
358   int my_tid = tid++;
359   mu.Unlock();
360 
361   if (my_tid == 0) {
362     GLOB = 1;
363   }
364 
365   // if the detector observes a happens-before arc between
366   // sem_open and sem_wait, it will be silent.
367   sem_t *sem = DoSemOpen();
368   usleep(100000);
369   CHECK(sem != SEM_FAILED);
370   CHECK(sem_wait(sem) == 0);
371 
372   if (my_tid > 0) {
373     CHECK(GLOB == 1);
374   }
375 }
376 
377 #ifndef __APPLE__
378 /* This test is disabled for Darwin because of the tricky implementation of
379  * sem_open on that platform: subsequent attempts to open an existing semafore
380  * create new ones. */
TEST(NegativeTests,test115)381 TEST(NegativeTests, test115) {
382   printf("test115: stab (sem_open())\n");
383 
384   // just check that sem_open is not completely broken
385   sem_unlink(kSemName);
386   sem_t* sem = DoSemOpen();
387   CHECK(sem != SEM_FAILED);
388   CHECK(sem_wait(sem) == 0);
389   sem_unlink(kSemName);
390 
391   // check that sem_open and sem_wait create a happens-before arc.
392   MyThreadArray t(Worker, Worker, Worker);
393   t.Start();
394   t.Join();
395   // clean up
396   sem_unlink(kSemName);
397 }
398 #endif  // __APPLE__
399 }  // namespace test115
400 
401 
402 // test122 TP: Simple test with RWLock {{{1
403 namespace  test122 {
404 int     VAR1 = 0;
405 int     VAR2 = 0;
406 RWLock mu;
407 
WriteWhileHoldingReaderLock(int * p)408 void WriteWhileHoldingReaderLock(int *p) {
409   usleep(100000);
410   ReaderLockScoped lock(&mu);  // Reader lock for writing. -- bug.
411   (*p)++;
412 }
413 
CorrectWrite(int * p)414 void CorrectWrite(int *p) {
415   WriterLockScoped lock(&mu);
416   (*p)++;
417 }
418 
Thread1()419 void Thread1() { WriteWhileHoldingReaderLock(&VAR1); }
Thread2()420 void Thread2() { CorrectWrite(&VAR1); }
Thread3()421 void Thread3() { CorrectWrite(&VAR2); }
Thread4()422 void Thread4() { WriteWhileHoldingReaderLock(&VAR2); }
423 
424 
TEST(PositiveTests,test122)425 TEST(PositiveTests, test122) {
426   printf("test122: positive (rw-lock)\n");
427   VAR1 = 0;
428   VAR2 = 0;
429   ANNOTATE_TRACE_MEMORY(&VAR1);
430   ANNOTATE_TRACE_MEMORY(&VAR2);
431   if (!Tsan_PureHappensBefore()) {
432     ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR1, "test122. TP. ReaderLock-ed while writing");
433     ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR2, "test122. TP. ReaderLock-ed while writing");
434   }
435   MyThreadArray t(Thread1, Thread2, Thread3, Thread4);
436   t.Start();
437   t.Join();
438 }
439 }  // namespace test122
440 
441 
442 // test125 TN: Backwards lock (annotated). {{{1
443 namespace test125 {
444 // This test uses "Backwards mutex" locking protocol.
445 // We take a *reader* lock when writing to a per-thread data
446 // (GLOB[thread_num])  and we take a *writer* lock when we
447 // are reading from the entire array at once.
448 //
449 // Such locking protocol is not understood by ThreadSanitizer's
450 // hybrid state machine. So, you either have to use a pure-happens-before
451 // detector ("tsan --pure-happens-before") or apply pure happens-before mode
452 // to this particular lock by using ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu).
453 
454 const int n_threads = 3;
455 RWLock   mu;
456 int     GLOB[n_threads];
457 
458 int adder_num; // updated atomically.
459 
Adder()460 void Adder() {
461   int my_num = AtomicIncrement(&adder_num, 1) - 1;
462   CHECK(my_num >= 0);
463   CHECK(my_num < n_threads);
464 
465   ReaderLockScoped lock(&mu);
466   GLOB[my_num]++;
467 }
468 
Aggregator()469 void Aggregator() {
470   int sum = 0;
471   {
472     WriterLockScoped lock(&mu);
473     for (int i = 0; i < n_threads; i++) {
474       sum += GLOB[i];
475     }
476   }
477   printf("sum=%d\n", sum);
478 }
479 
TEST(NegativeTests,test125)480 TEST(NegativeTests, test125) {
481   printf("test125: negative\n");
482 
483   ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu);
484 
485   // run Adders, then Aggregator
486   adder_num = 0;
487   {
488     MyThreadArray t(Adder, Adder, Adder, Aggregator);
489     t.Start();
490     t.Join();
491   }
492 
493   // Run Aggregator first.
494   adder_num = 0;
495   {
496     MyThreadArray t(Aggregator, Adder, Adder, Adder);
497     t.Start();
498     t.Join();
499   }
500 
501 }
502 }  // namespace test125
503 
504 
505 namespace MmapTest {  // {{{1
506 
507 const int kMmapSize =  65536;
508 
SubWorker()509 void SubWorker() {
510   for (int i = 0; i < 500; i++) {
511     int *ptr = (int*)mmap(NULL, kMmapSize, PROT_READ | PROT_WRITE,
512                           MAP_PRIVATE | MAP_ANON, -1, 0);
513     *ptr = 42;
514     munmap(ptr, kMmapSize);
515   }
516 }
517 
Worker1()518 void Worker1() {
519   MyThreadArray t(SubWorker, SubWorker, SubWorker, SubWorker);
520   t.Start();
521   t.Join();
522 }
Worker()523 void Worker() {
524   MyThreadArray t(Worker1, Worker1, Worker1, Worker1);
525   t.Start();
526   t.Join();
527 }
528 
TEST(NegativeTests,MmapTest)529 TEST(NegativeTests, MmapTest) {
530   MyThreadArray t(Worker, Worker, Worker, Worker);
531   t.Start();
532   t.Join();
533 }
534 }  // namespace
535 
536 
537 // A regression test for mmap/munmap handling in Pin.
538 // If the tool misses munmap() calls it may report a false positive if two
539 // threads map the same memory region.
540 namespace MmapRegressionTest {  // {{{1
541 
542 const int kMmapSize =  65536;
543 const uintptr_t kStartAddress = 0x10000;
544 
545 StealthNotification n1;
546 
Worker()547 void Worker() {
548     int *ptr = (int*)mmap((void*)kStartAddress, kMmapSize,
549                           PROT_READ | PROT_WRITE,
550                           MAP_PRIVATE | MAP_ANON, -1, 0);
551     *ptr = 42;
552     munmap(ptr, kMmapSize);
553 }
554 
TEST(NegativeTests,MmapRegressionTest)555 TEST(NegativeTests, MmapRegressionTest) {
556   MyThreadArray t(Worker, Worker);
557   t.Start();
558   t.Join();
559 }
560 
561 }  // namespace
562 
563 // test136. Unlock twice. {{{1
564 namespace test136 {
TEST(LockTests,UnlockTwice)565 TEST(LockTests, UnlockTwice) {
566   pthread_mutexattr_t attr;
567   CHECK(0 == pthread_mutexattr_init(&attr));
568   CHECK(0 == pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK));
569 
570   pthread_mutex_t mu;
571   CHECK(0 == pthread_mutex_init(&mu, &attr));
572   CHECK(0 == pthread_mutex_lock(&mu));
573   CHECK(0 == pthread_mutex_unlock(&mu));
574   int ret_unlock = pthread_mutex_unlock(&mu);  // unlocking twice.
575   int ret_destroy = pthread_mutex_destroy(&mu);
576   printf("  pthread_mutex_unlock returned %d\n", ret_unlock);
577   printf("  pthread_mutex_destroy returned %d\n", ret_destroy);
578 }
579 }  // namespace test136
580 
581 
582 // test141 FP. unlink/fopen, rmdir/opendir. {{{1
583 namespace test141 {
584 int GLOB1 = 0,
585     GLOB2 = 0;
586 char *dir_name = NULL,
587      *filename = NULL;
588 
Waker1()589 void Waker1() {
590   usleep(100000);
591   GLOB1 = 1;  // Write
592   // unlink deletes a file 'filename'
593   // which exits spin-loop in Waiter1().
594   printf("  Deleting file...\n");
595   CHECK(unlink(filename) == 0);
596 }
597 
Waiter1()598 void Waiter1() {
599   FILE *tmp;
600   while ((tmp = fopen(filename, "r")) != NULL) {
601     fclose(tmp);
602     usleep(10000);
603   }
604   printf("  ...file has been deleted\n");
605   GLOB1 = 2;  // Write
606 }
607 
Waker2()608 void Waker2() {
609   usleep(100000);
610   GLOB2 = 1;  // Write
611   // rmdir deletes a directory 'dir_name'
612   // which exit spin-loop in Waker().
613   printf("  Deleting directory...\n");
614   CHECK(rmdir(dir_name) == 0);
615 }
616 
Waiter2()617 void Waiter2() {
618   DIR *tmp;
619   while ((tmp = opendir(dir_name)) != NULL) {
620     closedir(tmp);
621     usleep(10000);
622   }
623   printf("  ...directory has been deleted\n");
624   GLOB2 = 2;
625 }
626 
TEST(NegativeTests,test141)627 TEST(NegativeTests, test141) {
628   printf("test141: FP. unlink/fopen, rmdir/opendir.\n");
629 
630   dir_name = strdup("/tmp/tsan-XXXXXX");
631   CHECK(mkdtemp(dir_name) != 0);
632 
633   filename = strdup((std::string() + dir_name + "/XXXXXX").c_str());
634   const int fd = mkstemp(filename);
635   CHECK(fd >= 0);
636   close(fd);
637 
638   MyThreadArray mta1(Waker1, Waiter1);
639   mta1.Start();
640   mta1.Join();
641 
642   MyThreadArray mta2(Waker2, Waiter2);
643   mta2.Start();
644   mta2.Join();
645 
646   free(filename);
647   filename = 0;
648   free(dir_name);
649   dir_name = 0;
650 }
651 }  // namespace test141
652 
653 
654 // test146: TP. Unit test for RWLock::TryLock and RWLock::ReaderTryLock. {{{1
655 namespace test146 {
656 // Worker1 locks the globals for writing for a long time.
657 // Worker2 tries to write to globals twice: without a writer lock and with it.
658 // Worker3 tries to read from globals twice: without a reader lock and with it.
659 int     GLOB1 = 0;
660 char    padding1[64];
661 int     GLOB2 = 0;
662 char    padding2[64];
663 int     GLOB3 = 0;
664 char    padding3[64];
665 int     GLOB4 = 0;
666 RWLock  MU;
667 StealthNotification n1, n2, n3, n4, n5;
668 
Worker1()669 void Worker1() {
670   MU.Lock();
671   GLOB1 = 1;
672   GLOB2 = 1;
673   GLOB3 = 1;
674   GLOB4 = 1;
675   n1.signal();
676   n2.wait();
677   n3.wait();
678   MU.Unlock();
679   n4.signal();
680 }
681 
Worker2()682 void Worker2() {
683   n1.wait();
684   if (MU.TryLock()) CHECK(0);
685   else
686     GLOB1 = 2;
687   n2.signal();
688   n5.wait();
689   if (MU.TryLock()) {
690     GLOB2 = 2;
691     MU.Unlock();
692   } else {
693     CHECK(0);
694   }
695 }
696 
Worker3()697 void Worker3() {
698   n1.wait();
699   if (MU.ReaderTryLock()) CHECK(0);
700   else
701     printf("\treading GLOB3: %d\n", GLOB3);
702   n3.signal();
703   n4.wait();
704   if (MU.ReaderTryLock()) {
705     printf("\treading GLOB4: %d\n", GLOB4);
706     MU.ReaderUnlock();
707   } else {
708     CHECK(0);
709   }
710   n5.signal();
711 }
712 
TEST(PositiveTests,test146)713 TEST(PositiveTests, test146) {
714   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB1, "test146. TP: a data race on GLOB1.");
715   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB3, "test146. TP: a data race on GLOB3.");
716   ANNOTATE_TRACE_MEMORY(&GLOB1);
717   ANNOTATE_TRACE_MEMORY(&GLOB2);
718   ANNOTATE_TRACE_MEMORY(&GLOB3);
719   ANNOTATE_TRACE_MEMORY(&GLOB4);
720   printf("test146: positive\n");
721   MyThreadArray t(Worker1, Worker2, Worker3);
722   t.Start();
723   t.Join();
724   printf("\tGLOB1=%d\n", GLOB1);
725   printf("\tGLOB2=%d\n", GLOB2);
726   printf("\tGLOB3=%d\n", GLOB3);
727   printf("\tGLOB4=%d\n", GLOB4);
728 }
729 } // namespace test146
730 
731 namespace PositiveTests_CyclicBarrierTest {  // {{{1
732 #ifndef NO_BARRIER
733 // regression test for correct support of cyclic barrier.
734 // This test was suggested by Julian Seward.
735 // There is a race on L here between a1 and b1,
736 // but a naive support of barrier makes us miss this race.
737 pthread_barrier_t B;
738 int L;
739 
740 // A1/A2: write L, then wait for barrier, then sleep
a1()741 void a1() {
742   L = 1;
743   pthread_barrier_wait(&B);
744   sleep(1);
745 }
a2()746 void a2() {
747   pthread_barrier_wait(&B);
748   sleep(1);
749 }
750 
751 // B1/B2: sleep, wait for barrier, then write L
b1()752 void b1() {
753   sleep(1);
754   pthread_barrier_wait(&B);
755   L = 1;
756 }
b2()757 void b2() {
758   sleep(1);
759   pthread_barrier_wait(&B);
760 }
761 
TEST(PositiveTests,CyclicBarrierTest)762 TEST(PositiveTests, CyclicBarrierTest) {
763   ANNOTATE_EXPECT_RACE_FOR_TSAN(&L, "real race, may be hidden"
764                                 " by incorrect implementation of barrier");
765   pthread_barrier_init(&B, NULL, 3);
766   MyThreadArray t1(a1, a2, a2),
767                 t2(b1, b2, b2);
768   t1.Start();
769   t2.Start();
770   t1.Join();
771   t2.Join();
772 }
773 
774 
775 int *G = NULL;
776 
Worker()777 void Worker() {
778   pthread_barrier_wait(&B);
779   (*G) = 1;
780   pthread_barrier_wait(&B);
781 }
782 
TEST(PositiveTests,CyclicBarrierTwoCallsTest)783 TEST(PositiveTests, CyclicBarrierTwoCallsTest) {
784   pthread_barrier_init(&B, NULL, 2);
785   G = new int(0);
786   ANNOTATE_TRACE_MEMORY(G);
787   ANNOTATE_EXPECT_RACE_FOR_TSAN(G, "real race, may be hidden"
788                                 " by incorrect implementation of barrier");
789   MyThreadArray t1(Worker, Worker);
790   t1.Start();
791   t1.Join();
792   CHECK(*G == 1);
793   delete G;
794 }
795 
796 
797 
798 #endif  // NO_BARRIER
799 }  // namespace
800 
TEST(NegativeTests,Mmap84GTest)801 TEST(NegativeTests, Mmap84GTest) {  // {{{1
802 #ifdef ARCH_amd64
803 #ifdef OS_linux
804   // test that we can mmap 84G and can do it fast.
805   size_t size = (1ULL << 32) * 21;  // 21 * 4G
806   void *mem_ptr = mmap((void *) 0,
807                        size,
808                        PROT_EXEC | PROT_READ | PROT_WRITE,
809                        MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE,
810                        -1,
811                        (off_t) 0);
812   printf("res=%p\n", mem_ptr);
813 #endif
814 #endif
815 }
816 
817 namespace NegativeTests_PthreadCreateFailureTest {  // {{{1
818 #ifdef OS_linux
ThreadRoutine(void *)819 void* ThreadRoutine(void *) {
820   return NULL;
821 }
822 
TEST(NegativeTests,PthreadCreateFailureTest)823 TEST(NegativeTests, PthreadCreateFailureTest) {
824   pthread_attr_t attributes;
825   pthread_attr_init(&attributes);
826   pthread_attr_setstacksize(&attributes, -1);
827   pthread_t handle;
828   CHECK(pthread_create(&handle, &attributes, ThreadRoutine, NULL) != 0);
829   pthread_attr_destroy(&attributes);
830 }
831 #endif  // OS_linux
832 }  // namespace NegativeTests_PthreadCreateFailureTest
833 
834 namespace Signals {  // {{{1
835 
836 typedef void (*Sigaction)(int, siginfo_t *, void *);
837 
838 int     GLOB = 0;
839 
EnableSigprof(Sigaction SignalHandler)840 static void EnableSigprof(Sigaction SignalHandler) {
841   struct sigaction sa;
842   sa.sa_sigaction = SignalHandler;
843   sa.sa_flags = SA_RESTART | SA_SIGINFO;
844   sigemptyset(&sa.sa_mask);
845   if (sigaction(SIGPROF, &sa, NULL) != 0) {
846     perror("sigaction");
847     abort();
848   }
849   struct itimerval timer;
850   timer.it_interval.tv_sec = 0;
851   timer.it_interval.tv_usec = 1000000 / 10000;
852   timer.it_value = timer.it_interval;
853   if (setitimer(ITIMER_PROF, &timer, 0) != 0) {
854     perror("setitimer");
855     abort();
856   }
857 }
858 
DisableSigprof()859 static void DisableSigprof() {
860   // Disable the profiling timer.
861   struct itimerval timer;
862   timer.it_interval.tv_sec = 0;
863   timer.it_interval.tv_usec = 0;
864   timer.it_value = timer.it_interval;
865   if (setitimer(ITIMER_PROF, &timer, 0) != 0) {
866     perror("setitimer");
867     abort();
868   }
869   // Ignore SIGPROFs from now on.
870   struct sigaction sa;
871   sa.sa_handler = SIG_IGN;
872   sa.sa_flags = SA_RESTART | SA_SIGINFO;
873   sigemptyset(&sa.sa_mask);
874   if (sigaction(SIGPROF, &sa, NULL) != 0) {
875     perror("sigaction");
876     abort();
877   }
878 }
879 
MallocTestWorker()880 void MallocTestWorker() {
881   for (int i = 0; i < 100000; i++) {
882     void *x = malloc((i % 64) + 1);
883     free (x);
884   }
885 }
886 
887 // Regression test for
888 // http://code.google.com/p/data-race-test/issues/detail?id=13 .
889 // Make sure that locking events are handled in signal handlers.
890 //
891 // For some reason, invoking the signal handlers causes deadlocks on Mac OS.
892 #ifndef __APPLE__
893 Mutex mu;
894 
SignalHandlerWithMutex(int,siginfo_t *,void *)895 void SignalHandlerWithMutex(int, siginfo_t*, void*) {
896   mu.Lock();
897   GLOB++;
898   mu.Unlock();
899 }
900 
TEST(Signals,SignalsAndMallocTestWithMutex)901 TEST(Signals, SignalsAndMallocTestWithMutex) {
902   EnableSigprof(SignalHandlerWithMutex);
903   MyThreadArray t(MallocTestWorker, MallocTestWorker, MallocTestWorker);
904   t.Start();
905   t.Join();
906   printf("\tGLOB=%d\n", GLOB);
907   DisableSigprof();
908 }
909 #endif
910 
911 // Another regression test for
912 // http://code.google.com/p/data-race-test/issues/detail?id=13 .
913 // Make sure that locking events are handled in signal handlers.
914 SpinLock sl;
915 
SignalHandlerWithSpinlock(int,siginfo_t *,void *)916 void SignalHandlerWithSpinlock(int, siginfo_t*, void*) {
917   sl.Lock();
918   GLOB++;
919   sl.Unlock();
920 }
921 
TEST(Signals,DISABLED_SignalsAndMallocTestWithSpinlock)922 TEST(Signals, DISABLED_SignalsAndMallocTestWithSpinlock) {
923   EnableSigprof(SignalHandlerWithSpinlock);
924   MyThreadArray t(MallocTestWorker, MallocTestWorker, MallocTestWorker);
925   t.Start();
926   t.Join();
927   printf("\tGLOB=%d\n", GLOB);
928   DisableSigprof();
929 }
930 
931 // Regression test for
932 // http://code.google.com/p/data-race-test/issues/detail?id=14.
WaitTestSignalHandler(int,siginfo_t *,void *)933 static void WaitTestSignalHandler(int, siginfo_t*, void*) {
934   ANNOTATE_HAPPENS_AFTER((void*)0x1234);
935 }
936 
WaitTestWorker()937 void WaitTestWorker() {
938   for (int i = 0; i < 1000000; i++) {
939     ANNOTATE_HAPPENS_AFTER((void*)0x1234);
940   }
941 }
942 
TEST(Signals,SignalsAndWaitTest)943 TEST(Signals, SignalsAndWaitTest) {
944   EnableSigprof(WaitTestSignalHandler);
945   MyThreadArray t(WaitTestWorker, WaitTestWorker, WaitTestWorker);
946   t.Start();
947   t.Join();
948   DisableSigprof();
949 }
950 
951 #ifndef __APPLE__
952 // this test crashes on Mac in debug TSan build, see
953 // http://code.google.com/p/data-race-test/issues/detail?id=47
954 pid_t child_pid = 0;
955 
child_handler(int signum)956 void child_handler(int signum) {
957   if (signum == SIGCHLD && child_pid == 0) {
958     printf("Whoops, PID shouldn't be 0!\n");
959   }
960 }
961 
TEST(Signals,PositiveTests_RaceInSignal)962 TEST(Signals, PositiveTests_RaceInSignal) {
963   // Currently the data race on child_pid can't be found,
964   // see http://code.google.com/p/data-race-test/issues/detail?id=46
965   //ANNOTATE_EXPECT_RACE(&child_pid, "Race on pid: fork vs signal handler");
966   signal(SIGCHLD, child_handler);
967   child_pid = fork();
968   if (child_pid == 0) {
969     // in child
970     exit(0);
971   }
972   wait(NULL);
973 }
974 #endif  // __APPLE__
975 
976 }  // namespace;
977 
TEST(WeirdSizesTests,FegetenvTest)978 TEST(WeirdSizesTests, FegetenvTest) {
979   // http://code.google.com/p/data-race-test/issues/detail?id=36
980   fenv_t tmp;
981   if (fegetenv(&tmp) != 0)
982     FAIL() << "fegetenv failed";
983 }
984 
985 namespace NegativeTests_epoll {  // {{{1
986 #ifdef OS_linux
987 int GLOB;
988 
989 // Currently, ThreadSanitizer should create hb arcs between
990 // epoll_ctl and epoll_wait regardless of the parameters. Check that.
991 
Worker1()992 void Worker1() {
993   GLOB++;
994   struct epoll_event event;
995   epoll_ctl(0, 0, 0, &event);
996 }
Worker2()997 void Worker2() {
998   struct epoll_event event;
999   epoll_wait(0, &event, 0, 0);
1000   GLOB++;
1001 }
1002 
TEST(NegativeTests,epollTest)1003 TEST(NegativeTests,epollTest) {
1004   MyThreadArray mta(Worker1, Worker2);
1005   mta.Start();
1006   mta.Join();
1007 }
1008 #endif  // OS_linux
1009 }
1010 namespace NegativeTests_LockfTest {  // {{{1
1011 
1012 class ShmMutex {
1013  public:
ShmMutex()1014   ShmMutex() : fd_(-1) { }
set_fd(int fd)1015   void set_fd(int fd) {
1016     CHECK(fd_ == -1);
1017     fd_ = fd;
1018   }
Lock()1019   void Lock() {
1020     LockOrUnlockInternal(true);
1021   }
Unlock()1022   void Unlock() {
1023     LockOrUnlockInternal(false);
1024   }
1025  private:
LockOrUnlockInternal(bool lock)1026   void LockOrUnlockInternal(bool lock) {
1027     CHECK(fd_ >= 0);
1028     while (lockf(fd_, lock ? F_LOCK : F_ULOCK, 0) < 0) {
1029       if (errno == EINTR) {
1030         continue;
1031       } else if (errno == ENOLCK) {
1032         usleep(5000);
1033         continue;
1034       }
1035       CHECK(0);
1036     }
1037 
1038   }
1039 
1040   int fd_;
1041 } mu;
1042 
1043 int GLOB;
1044 
Worker()1045 void Worker() {
1046   mu.Lock();
1047   GLOB++;
1048   mu.Unlock();
1049 }
1050 
TEST(NegativeTests,DISABLED_LockfTest)1051 TEST(NegativeTests,DISABLED_LockfTest) {
1052   mu.set_fd(1 /* stdout */);
1053   MyThreadArray mta(Worker, Worker);
1054   mta.Start();
1055   mta.Join();
1056 }
1057 
1058 }
1059 namespace PositiveTests_LockThenNoLock {  // {{{1
1060 // Regression test for a bug fixed by r2312
1061 int GLOB;
1062 pthread_mutex_t mu;
1063 StealthNotification n1, n2;
1064 
Worker1()1065 void Worker1() {
1066   pthread_mutex_lock(&mu);
1067   GLOB = 1;
1068   pthread_mutex_unlock(&mu);
1069   n1.signal();
1070   n2.wait();
1071   GLOB = 2;
1072 }
1073 
Worker2()1074 void Worker2() {
1075   pthread_mutex_lock(&mu);
1076   GLOB = 3;
1077   pthread_mutex_unlock(&mu);
1078   n2.signal();
1079   n1.wait();
1080   GLOB = 4;
1081 }
1082 
TEST(PositiveTests,LockThenNoLock)1083 TEST(PositiveTests, LockThenNoLock) {
1084   pthread_mutex_init(&mu, NULL);
1085   ANNOTATE_TRACE_MEMORY(&GLOB);
1086   ANNOTATE_EXPECT_RACE(&GLOB, "race");
1087   ANNOTATE_NOT_HAPPENS_BEFORE_MUTEX(&mu);
1088   MyThreadArray t(Worker1, Worker2);
1089   t.Start();
1090   t.Join();
1091   pthread_mutex_destroy(&mu);
1092 }
1093 }  // namespace
1094 
1095 #ifdef __APPLE__
1096 namespace NegativeTests_PthreadCondWaitRelativeNp {  // {{{1
1097 int GLOB = 0;
1098 pthread_mutex_t mu;
1099 pthread_cond_t cv;
1100 
Waiter()1101 void Waiter() {
1102   struct timespec tv = {1000, 1000};
1103   pthread_mutex_lock(&mu);
1104   pthread_cond_timedwait_relative_np(&cv, &mu, &tv);
1105   GLOB = 2;
1106   pthread_mutex_unlock(&mu);
1107 }
1108 
Waker()1109 void Waker() {
1110   pthread_mutex_lock(&mu);
1111   GLOB = 1;
1112   pthread_cond_signal(&cv);
1113   pthread_mutex_unlock(&mu);
1114 }
1115 
TEST(NegativeTests,PthreadCondWaitRelativeNpTest)1116 TEST(NegativeTests, PthreadCondWaitRelativeNpTest) {
1117   pthread_mutex_init(&mu, NULL);
1118   pthread_cond_init(&cv, NULL);
1119   MyThreadArray t(Waiter, Waker);
1120   t.Start();
1121   t.Join();
1122   pthread_mutex_destroy(&mu);
1123   pthread_cond_destroy(&cv);
1124 }
1125 }  // namespace
1126 #endif  // __APPLE__
1127 
1128 namespace PositiveTests_RWLockVsRWLockTest {  // {{{1
1129 // Test that reader lock/unlock do not create a hb-arc.
1130 RWLock mu;
1131 int GLOB;
1132 StealthNotification n;
1133 
Thread1()1134 void Thread1() {
1135   GLOB = 1;
1136   mu.ReaderLock();
1137   mu.ReaderUnlock();
1138   n.signal();
1139 }
1140 
Thread2()1141 void Thread2() {
1142   n.wait();
1143   mu.ReaderLock();
1144   mu.ReaderUnlock();
1145   GLOB = 1;
1146 }
1147 
TEST(PositiveTests,RWLockVsRWLockTest)1148 TEST(PositiveTests, RWLockVsRWLockTest) {
1149   ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu);
1150   ANNOTATE_EXPECT_RACE(&GLOB, "rwunlock/rwlock is not a hb-arc");
1151   MyThreadArray t(Thread1, Thread2);
1152   t.Start();
1153   t.Join();
1154 }
1155 
1156 }  // namespace
1157 
1158 namespace TSDTests {
1159 // Test the support for libpthread TSD destructors.
1160 pthread_key_t key;
1161 const int kInitialValue = 0xfeedface;
1162 int tsd_array[2];
1163 
Destructor(void * ptr)1164 void Destructor(void *ptr) {
1165   int *write = (int*) ptr;
1166   *write = kInitialValue;
1167 }
1168 
DoWork(int index)1169 void DoWork(int index) {
1170   int *value = &(tsd_array[index]);
1171   *value = 42;
1172   pthread_setspecific(key, value);
1173   int *read = (int*) pthread_getspecific(key);
1174   CHECK(read == value);
1175 }
1176 
Worker0()1177 void Worker0() { DoWork(0); }
Worker1()1178 void Worker1() { DoWork(1); }
1179 
TEST(TSDTests,TSDDestructorTest)1180 TEST(TSDTests, TSDDestructorTest) {
1181   pthread_key_create(&key, Destructor);
1182   MyThreadArray t(Worker0, Worker1);
1183   t.Start();
1184   t.Join();
1185   for (int i = 0; i < 2; ++i) {
1186     CHECK(tsd_array[i] == kInitialValue);
1187   }
1188 }
1189 
1190 }
1191 
1192 // End {{{1
1193  // vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker
1194