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