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 //
31 //
32 // This test can be compiled with pthreads (default) or
33 // with any other library that supports threads, locks, cond vars, etc.
34 //
35 // To compile with pthreads:
36 //   g++  racecheck_unittest.cc dynamic_annotations.cc
37 //        -lpthread -g -DDYNAMIC_ANNOTATIONS=1
38 //
39 // To compile with different library:
40 //   1. cp thread_wrappers_pthread.h thread_wrappers_yourlib.h
41 //   2. edit thread_wrappers_yourlib.h
42 //   3. add '-DTHREAD_WRAPPERS="thread_wrappers_yourlib.h"' to your compilation.
43 //
44 //
45 
46 // This test must not include any other file specific to threading library,
47 // everything should be inside THREAD_WRAPPERS.
48 #ifndef THREAD_WRAPPERS
49 # define THREAD_WRAPPERS "thread_wrappers_pthread.h"
50 #endif
51 #include THREAD_WRAPPERS
52 
53 #ifndef NEEDS_SEPERATE_RW_LOCK
54 #define RWLock Mutex // Mutex does work as an rw-lock.
55 #define WriterLockScoped MutexLock
56 #define ReaderLockScoped ReaderMutexLock
57 #endif // !NEEDS_SEPERATE_RW_LOCK
58 
59 
60 // Helgrind memory usage testing stuff
61 // If not present in dynamic_annotations.h/.cc - ignore
62 #ifndef ANNOTATE_RESET_STATS
63 #define ANNOTATE_RESET_STATS() do { } while(0)
64 #endif
65 #ifndef ANNOTATE_PRINT_STATS
66 #define ANNOTATE_PRINT_STATS() do { } while(0)
67 #endif
68 #ifndef ANNOTATE_PRINT_MEMORY_USAGE
69 #define ANNOTATE_PRINT_MEMORY_USAGE(a) do { } while(0)
70 #endif
71 //
72 
73 // A function that allows to suppress gcc's warnings about
74 // unused return values in a portable way.
75 template <typename T>
IGNORE_RETURN_VALUE(T v)76 static inline void IGNORE_RETURN_VALUE(T v)
77 { }
78 
79 #include <vector>
80 #include <string>
81 #include <map>
82 #include <queue>
83 #include <algorithm>
84 #include <cstring>      // strlen(), index(), rindex()
85 #include <ctime>
86 #include <sys/time.h>
87 #include <sys/types.h>
88 #include <sys/stat.h>
89 #include <fcntl.h>
90 #include <sys/mman.h>  // mmap
91 #include <errno.h>
92 #include <stdint.h>    // uintptr_t
93 #include <stdlib.h>
94 #include <dirent.h>
95 
96 #ifndef VGO_darwin
97 #include <malloc.h>
98 #endif
99 
100 // The tests are
101 // - Stability tests (marked STAB)
102 // - Performance tests (marked PERF)
103 // - Feature tests
104 //   - TN (true negative) : no race exists and the tool is silent.
105 //   - TP (true positive) : a race exists and reported.
106 //   - FN (false negative): a race exists but not reported.
107 //   - FP (false positive): no race exists but the tool reports it.
108 //
109 // The feature tests are marked according to the behavior of helgrind 3.3.0.
110 //
111 // TP and FP tests are annotated with ANNOTATE_EXPECT_RACE,
112 // so, no error reports should be seen when running under helgrind.
113 //
114 // When some of the FP cases are fixed in helgrind we'll need
115 // to update this test.
116 //
117 // Each test resides in its own namespace.
118 // Namespaces are named test01, test02, ...
119 // Please, *DO NOT* change the logic of existing tests nor rename them.
120 // Create a new test instead.
121 //
122 // Some tests use sleep()/usleep().
123 // This is not a synchronization, but a simple way to trigger
124 // some specific behaviour of the race detector's scheduler.
125 
126 // Globals and utilities used by several tests. {{{1
127 CondVar CV;
128 int     COND = 0;
129 
130 
131 typedef void (*void_func_void_t)(void);
132 enum TEST_FLAG {
133   FEATURE           = 1 << 0,
134   STABILITY         = 1 << 1,
135   PERFORMANCE       = 1 << 2,
136   EXCLUDE_FROM_ALL  = 1 << 3,
137   NEEDS_ANNOTATIONS = 1 << 4,
138   RACE_DEMO         = 1 << 5,
139   MEMORY_USAGE      = 1 << 6,
140   PRINT_STATS       = 1 << 7
141 };
142 
143 // Put everything into stderr.
144 Mutex printf_mu;
145 #define printf(args...) \
146     do{ \
147       printf_mu.Lock();\
148       fprintf(stderr, args);\
149       printf_mu.Unlock(); \
150     }while(0)
151 
GetTimeInMs()152 long GetTimeInMs() {
153    struct timeval tv;
154    gettimeofday(&tv, NULL);
155    return (tv.tv_sec * 1000L) + (tv.tv_usec / 1000L);
156 }
157 
158 struct Test{
159   void_func_void_t f_;
160   int flags_;
TestTest161   Test(void_func_void_t f, int flags)
162     : f_(f)
163     , flags_(flags)
164   {}
TestTest165   Test() : f_(0), flags_(0) {}
RunTest166   void Run() {
167      ANNOTATE_RESET_STATS();
168      if (flags_ & PERFORMANCE) {
169         long start = GetTimeInMs();
170         f_();
171         long end = GetTimeInMs();
172         printf ("Time: %4ldms\n", end-start);
173      } else
174         f_();
175      if (flags_ & PRINT_STATS)
176         ANNOTATE_PRINT_STATS();
177      if (flags_ & MEMORY_USAGE)
178         ANNOTATE_PRINT_MEMORY_USAGE(0);
179   }
180 };
181 std::map<int, Test> TheMapOfTests;
182 
183 #define NOINLINE __attribute__ ((noinline))
AnnotateSetVerbosity(const char *,int,int)184 extern "C" void NOINLINE AnnotateSetVerbosity(const char *, int, int) {};
185 
186 
187 struct TestAdder {
TestAdderTestAdder188   TestAdder(void_func_void_t f, int id, int flags = FEATURE) {
189     // AnnotateSetVerbosity(__FILE__, __LINE__, 0);
190     CHECK(TheMapOfTests.count(id) == 0);
191     TheMapOfTests[id] = Test(f, flags);
192   }
193 };
194 
195 #define REGISTER_TEST(f, id)         TestAdder add_test_##id (f, id);
196 #define REGISTER_TEST2(f, id, flags) TestAdder add_test_##id (f, id, flags);
197 
ArgIsOne(int * arg)198 static bool ArgIsOne(int *arg) { return *arg == 1; };
ArgIsZero(int * arg)199 static bool ArgIsZero(int *arg) { return *arg == 0; };
ArgIsTrue(bool * arg)200 static bool ArgIsTrue(bool *arg) { return *arg == true; };
201 
202 // Call ANNOTATE_EXPECT_RACE only if 'machine' env variable is defined.
203 // Useful to test against several different machines.
204 // Supported machines so far:
205 //   MSM_HYBRID1             -- aka MSMProp1
206 //   MSM_HYBRID1_INIT_STATE  -- aka MSMProp1 with --initialization-state=yes
207 //   MSM_THREAD_SANITIZER    -- ThreadSanitizer's state machine
208 #define ANNOTATE_EXPECT_RACE_FOR_MACHINE(mem, descr, machine) \
209     while(getenv(machine)) {\
210       ANNOTATE_EXPECT_RACE(mem, descr); \
211       break;\
212     }\
213 
214 #define ANNOTATE_EXPECT_RACE_FOR_TSAN(mem, descr) \
215     ANNOTATE_EXPECT_RACE_FOR_MACHINE(mem, descr, "MSM_THREAD_SANITIZER")
216 
Tsan_PureHappensBefore()217 inline bool Tsan_PureHappensBefore() {
218   return true;
219 }
220 
Tsan_FastMode()221 inline bool Tsan_FastMode()           {
222   return getenv("TSAN_FAST_MODE") != NULL;
223 }
224 
225 // Initialize *(mem) to 0 if Tsan_FastMode.
226 #define FAST_MODE_INIT(mem) do { if (Tsan_FastMode()) { *(mem) = 0; } } while(0)
227 
228 #ifndef MAIN_INIT_ACTION
229 #define MAIN_INIT_ACTION
230 #endif
231 
232 
233 
main(int argc,char ** argv)234 int main(int argc, char** argv) { // {{{1
235   MAIN_INIT_ACTION;
236   printf("FLAGS [phb=%i, fm=%i]\n", Tsan_PureHappensBefore(), Tsan_FastMode());
237   if (argc == 2 && !strcmp(argv[1], "benchmark")) {
238      for (std::map<int,Test>::iterator it = TheMapOfTests.begin();
239          it != TheMapOfTests.end(); ++it) {
240        if(!(it->second.flags_ & PERFORMANCE)) continue;
241        it->second.Run();
242      }
243   } else if (argc == 2 && !strcmp(argv[1], "demo")) {
244      for (std::map<int,Test>::iterator it = TheMapOfTests.begin();
245          it != TheMapOfTests.end();  ++it) {
246        if(!(it->second.flags_ & RACE_DEMO)) continue;
247        it->second.Run();
248      }
249   } else if (argc > 1) {
250     // the tests are listed in command line flags
251     for (int i = 1; i < argc; i++) {
252       int f_num = atoi(argv[i]);
253       CHECK(TheMapOfTests.count(f_num));
254       TheMapOfTests[f_num].Run();
255     }
256   } else {
257     bool run_tests_with_annotations = false;
258     if (getenv("DRT_ALLOW_ANNOTATIONS")) {
259       run_tests_with_annotations = true;
260     }
261     for (std::map<int,Test>::iterator it = TheMapOfTests.begin();
262         it != TheMapOfTests.end();
263         ++it) {
264       if(it->second.flags_ & EXCLUDE_FROM_ALL) continue;
265       if(it->second.flags_ & RACE_DEMO) continue;
266       if((it->second.flags_ & NEEDS_ANNOTATIONS)
267          && run_tests_with_annotations == false) continue;
268       it->second.Run();
269     }
270   }
271 }
272 
273 #ifdef THREAD_WRAPPERS_PTHREAD_H
274 #endif
275 
276 
277 // An array of threads. Create/start/join all elements at once. {{{1
278 class MyThreadArray {
279  public:
280   static const int kSize = 5;
281   typedef void (*F) (void);
MyThreadArray(F f1,F f2=NULL,F f3=NULL,F f4=NULL,F f5=NULL)282   MyThreadArray(F f1, F f2 = NULL, F f3 = NULL, F f4 = NULL, F f5 = NULL) {
283     ar_[0] = new MyThread(f1);
284     ar_[1] = f2 ? new MyThread(f2) : NULL;
285     ar_[2] = f3 ? new MyThread(f3) : NULL;
286     ar_[3] = f4 ? new MyThread(f4) : NULL;
287     ar_[4] = f5 ? new MyThread(f5) : NULL;
288   }
Start()289   void Start() {
290     for(int i = 0; i < kSize; i++) {
291       if(ar_[i]) {
292         ar_[i]->Start();
293         usleep(10);
294       }
295     }
296   }
297 
Join()298   void Join() {
299     for(int i = 0; i < kSize; i++) {
300       if(ar_[i]) {
301         ar_[i]->Join();
302       }
303     }
304   }
305 
~MyThreadArray()306   ~MyThreadArray() {
307     for(int i = 0; i < kSize; i++) {
308       delete ar_[i];
309     }
310   }
311  private:
312   MyThread *ar_[kSize];
313 };
314 
315 
316 
317 // test00: {{{1
318 namespace test00 {
319 int     GLOB = 0;
Run()320 void Run() {
321   printf("test00: negative\n");
322   printf("\tGLOB=%d\n", GLOB);
323 }
324 REGISTER_TEST(Run, 00)
325 }  // namespace test00
326 
327 
328 // test01: TP. Simple race (write vs write). {{{1
329 namespace test01 {
330 int     GLOB = 0;
Worker()331 void Worker() {
332   GLOB = 1;
333 }
334 
Parent()335 void Parent() {
336   MyThread t(Worker);
337   t.Start();
338   const timespec delay = { 0, 100 * 1000 * 1000 };
339   nanosleep(&delay, 0);
340   GLOB = 2;
341   t.Join();
342 }
Run()343 void Run() {
344   FAST_MODE_INIT(&GLOB);
345   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test01. TP.");
346   ANNOTATE_TRACE_MEMORY(&GLOB);
347   printf("test01: positive\n");
348   Parent();
349   const int tmp = GLOB;
350   printf("\tGLOB=%d\n", tmp);
351 }
352 REGISTER_TEST(Run, 1);
353 }  // namespace test01
354 
355 
356 // test02: TN. Synchronization via CondVar. {{{1
357 namespace test02 {
358 int     GLOB = 0;
359 // Two write accesses to GLOB are synchronized because
360 // the pair of CV.Signal() and CV.Wait() establish happens-before relation.
361 //
362 // Waiter:                      Waker:
363 // 1. COND = 0
364 // 2. Start(Waker)
365 // 3. MU.Lock()                 a. write(GLOB)
366 //                              b. MU.Lock()
367 //                              c. COND = 1
368 //                         /--- d. CV.Signal()
369 //  4. while(COND)        /     e. MU.Unlock()
370 //       CV.Wait(MU) <---/
371 //  5. MU.Unlock()
372 //  6. write(GLOB)
373 Mutex   MU;
374 
Waker()375 void Waker() {
376   usleep(100000);  // Make sure the waiter blocks.
377   GLOB = 1;
378 
379   MU.Lock();
380   COND = 1;
381   CV.Signal();
382   MU.Unlock();
383 }
384 
Waiter()385 void Waiter() {
386   ThreadPool pool(1);
387   pool.StartWorkers();
388   COND = 0;
389   pool.Add(NewCallback(Waker));
390   MU.Lock();
391   while(COND != 1)
392     CV.Wait(&MU);
393   MU.Unlock();
394   GLOB = 2;
395 }
Run()396 void Run() {
397   printf("test02: negative\n");
398   Waiter();
399   printf("\tGLOB=%d\n", GLOB);
400 }
401 REGISTER_TEST(Run, 2);
402 }  // namespace test02
403 
404 
405 // test03: TN. Synchronization via LockWhen, signaller gets there first. {{{1
406 namespace test03 {
407 int     GLOB = 0;
408 // Two write accesses to GLOB are synchronized via conditional critical section.
409 // Note that LockWhen() happens first (we use sleep(1) to make sure)!
410 //
411 // Waiter:                           Waker:
412 // 1. COND = 0
413 // 2. Start(Waker)
414 //                                   a. write(GLOB)
415 //                                   b. MU.Lock()
416 //                                   c. COND = 1
417 //                              /--- d. MU.Unlock()
418 // 3. MU.LockWhen(COND==1) <---/
419 // 4. MU.Unlock()
420 // 5. write(GLOB)
421 Mutex   MU;
422 
Waker()423 void Waker() {
424   usleep(100000);  // Make sure the waiter blocks.
425   GLOB = 1;
426 
427   MU.Lock();
428   COND = 1; // We are done! Tell the Waiter.
429   MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
430 }
Waiter()431 void Waiter() {
432   ThreadPool pool(1);
433   pool.StartWorkers();
434   COND = 0;
435   pool.Add(NewCallback(Waker));
436   MU.LockWhen(Condition(&ArgIsOne, &COND));  // calls ANNOTATE_CONDVAR_WAIT
437   MU.Unlock();  // Waker is done!
438 
439   GLOB = 2;
440 }
Run()441 void Run() {
442   printf("test03: negative\n");
443   Waiter();
444   printf("\tGLOB=%d\n", GLOB);
445 }
446 REGISTER_TEST2(Run, 3, FEATURE|NEEDS_ANNOTATIONS);
447 }  // namespace test03
448 
449 // test04: TN. Synchronization via PCQ. {{{1
450 namespace test04 {
451 int     GLOB = 0;
452 ProducerConsumerQueue Q(INT_MAX);
453 // Two write accesses to GLOB are separated by PCQ Put/Get.
454 //
455 // Putter:                        Getter:
456 // 1. write(GLOB)
457 // 2. Q.Put() ---------\          .
458 //                      \-------> a. Q.Get()
459 //                                b. write(GLOB)
460 
461 
Putter()462 void Putter() {
463   GLOB = 1;
464   Q.Put(NULL);
465 }
466 
Getter()467 void Getter() {
468   Q.Get();
469   GLOB = 2;
470 }
471 
Run()472 void Run() {
473   printf("test04: negative\n");
474   MyThreadArray t(Putter, Getter);
475   t.Start();
476   t.Join();
477   printf("\tGLOB=%d\n", GLOB);
478 }
479 REGISTER_TEST(Run, 4);
480 }  // namespace test04
481 
482 
483 // test05: FP. Synchronization via CondVar, but waiter does not block. {{{1
484 // Since CondVar::Wait() is not called, we get a false positive.
485 namespace test05 {
486 int     GLOB = 0;
487 // Two write accesses to GLOB are synchronized via CondVar.
488 // But race detector can not see it.
489 // See this for details:
490 // http://www.valgrind.org/docs/manual/hg-manual.html#hg-manual.effective-use.
491 //
492 // Waiter:                                  Waker:
493 // 1. COND = 0
494 // 2. Start(Waker)
495 // 3. MU.Lock()                             a. write(GLOB)
496 //                                          b. MU.Lock()
497 //                                          c. COND = 1
498 //                                          d. CV.Signal()
499 //  4. while(COND)                          e. MU.Unlock()
500 //       CV.Wait(MU) <<< not called
501 //  5. MU.Unlock()
502 //  6. write(GLOB)
503 Mutex   MU;
504 
Waker()505 void Waker() {
506   GLOB = 1;
507   MU.Lock();
508   COND = 1;
509   CV.Signal();
510   MU.Unlock();
511 }
512 
Waiter()513 void Waiter() {
514   ThreadPool pool(1);
515   pool.StartWorkers();
516   COND = 0;
517   pool.Add(NewCallback(Waker));
518   usleep(100000);  // Make sure the signaller gets first.
519   MU.Lock();
520   while(COND != 1)
521     CV.Wait(&MU);
522   MU.Unlock();
523   GLOB = 2;
524 }
Run()525 void Run() {
526   FAST_MODE_INIT(&GLOB);
527   if (!Tsan_PureHappensBefore())
528     ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test05. FP. Unavoidable in hybrid scheme.");
529   printf("test05: unavoidable false positive\n");
530   Waiter();
531   printf("\tGLOB=%d\n", GLOB);
532 }
533 REGISTER_TEST(Run, 5);
534 }  // namespace test05
535 
536 
537 // test06: TN. Synchronization via CondVar, but Waker gets there first.  {{{1
538 namespace test06 {
539 int     GLOB = 0;
540 // Same as test05 but we annotated the Wait() loop.
541 //
542 // Waiter:                                            Waker:
543 // 1. COND = 0
544 // 2. Start(Waker)
545 // 3. MU.Lock()                                       a. write(GLOB)
546 //                                                    b. MU.Lock()
547 //                                                    c. COND = 1
548 //                                           /------- d. CV.Signal()
549 //  4. while(COND)                          /         e. MU.Unlock()
550 //       CV.Wait(MU) <<< not called        /
551 //  6. ANNOTATE_CONDVAR_WAIT(CV, MU) <----/
552 //  5. MU.Unlock()
553 //  6. write(GLOB)
554 
555 Mutex   MU;
556 
Waker()557 void Waker() {
558   GLOB = 1;
559   MU.Lock();
560   COND = 1;
561   CV.Signal();
562   MU.Unlock();
563 }
564 
Waiter()565 void Waiter() {
566   ThreadPool pool(1);
567   pool.StartWorkers();
568   COND = 0;
569   pool.Add(NewCallback(Waker));
570   usleep(100000);  // Make sure the signaller gets first.
571   MU.Lock();
572   while(COND != 1)
573     CV.Wait(&MU);
574   ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
575 
576   MU.Unlock();
577   GLOB = 2;
578 }
Run()579 void Run() {
580   printf("test06: negative\n");
581   Waiter();
582   printf("\tGLOB=%d\n", GLOB);
583 }
584 REGISTER_TEST2(Run, 6, FEATURE|NEEDS_ANNOTATIONS);
585 }  // namespace test06
586 
587 
588 // test07: TN. Synchronization via LockWhen(), Signaller is observed first. {{{1
589 namespace test07 {
590 int     GLOB = 0;
591 bool    COND = 0;
592 // Two write accesses to GLOB are synchronized via conditional critical section.
593 // LockWhen() is observed after COND has been set (due to sleep).
594 // Unlock() calls ANNOTATE_CONDVAR_SIGNAL().
595 //
596 // Waiter:                           Signaller:
597 // 1. COND = 0
598 // 2. Start(Signaller)
599 //                                   a. write(GLOB)
600 //                                   b. MU.Lock()
601 //                                   c. COND = 1
602 //                              /--- d. MU.Unlock calls ANNOTATE_CONDVAR_SIGNAL
603 // 3. MU.LockWhen(COND==1) <---/
604 // 4. MU.Unlock()
605 // 5. write(GLOB)
606 
607 Mutex   MU;
Signaller()608 void Signaller() {
609   GLOB = 1;
610   MU.Lock();
611   COND = true; // We are done! Tell the Waiter.
612   MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
613 }
Waiter()614 void Waiter() {
615   COND = false;
616   MyThread t(Signaller);
617   t.Start();
618   usleep(100000);  // Make sure the signaller gets there first.
619 
620   MU.LockWhen(Condition(&ArgIsTrue, &COND));  // calls ANNOTATE_CONDVAR_WAIT
621   MU.Unlock();  // Signaller is done!
622 
623   GLOB = 2; // If LockWhen didn't catch the signal, a race may be reported here.
624   t.Join();
625 }
Run()626 void Run() {
627   printf("test07: negative\n");
628   Waiter();
629   printf("\tGLOB=%d\n", GLOB);
630 }
631 REGISTER_TEST2(Run, 7, FEATURE|NEEDS_ANNOTATIONS);
632 }  // namespace test07
633 
634 // test08: TN. Synchronization via thread start/join. {{{1
635 namespace test08 {
636 int     GLOB = 0;
637 // Three accesses to GLOB are separated by thread start/join.
638 //
639 // Parent:                        Worker:
640 // 1. write(GLOB)
641 // 2. Start(Worker) ------------>
642 //                                a. write(GLOB)
643 // 3. Join(Worker) <------------
644 // 4. write(GLOB)
Worker()645 void Worker() {
646   GLOB = 2;
647 }
648 
Parent()649 void Parent() {
650   MyThread t(Worker);
651   GLOB = 1;
652   t.Start();
653   t.Join();
654   GLOB = 3;
655 }
Run()656 void Run() {
657   printf("test08: negative\n");
658   Parent();
659   printf("\tGLOB=%d\n", GLOB);
660 }
661 REGISTER_TEST(Run, 8);
662 }  // namespace test08
663 
664 
665 // test09: TP. Simple race (read vs write). {{{1
666 namespace test09 {
667 int     GLOB = 0;
668 // A simple data race between writer and reader.
669 // Write happens after read (enforced by sleep).
670 // Usually, easily detectable by a race detector.
Writer()671 void Writer() {
672   usleep(100000);
673   GLOB = 3;
674 }
Reader()675 void Reader() {
676   CHECK(GLOB != -777);
677 }
678 
Run()679 void Run() {
680   ANNOTATE_TRACE_MEMORY(&GLOB);
681   FAST_MODE_INIT(&GLOB);
682   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test09. TP.");
683   printf("test09: positive\n");
684   MyThreadArray t(Writer, Reader);
685   t.Start();
686   t.Join();
687   printf("\tGLOB=%d\n", GLOB);
688 }
689 REGISTER_TEST(Run, 9);
690 }  // namespace test09
691 
692 
693 // test10: FN. Simple race (write vs read). {{{1
694 namespace test10 {
695 int     GLOB = 0;
696 // A simple data race between writer and reader.
697 // Write happens before Read (enforced by sleep),
698 // otherwise this test is the same as test09.
699 //
700 // Writer:                    Reader:
701 // 1. write(GLOB)             a. sleep(long enough so that GLOB
702 //                                is most likely initialized by Writer)
703 //                            b. read(GLOB)
704 //
705 //
706 // Eraser algorithm does not detect the race here,
707 // see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html.
708 //
Writer()709 void Writer() {
710   GLOB = 3;
711 }
Reader()712 void Reader() {
713   usleep(100000);
714   CHECK(GLOB != -777);
715 }
716 
Run()717 void Run() {
718   FAST_MODE_INIT(&GLOB);
719   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test10. TP. FN in MSMHelgrind.");
720   printf("test10: positive\n");
721   MyThreadArray t(Writer, Reader);
722   t.Start();
723   t.Join();
724   printf("\tGLOB=%d\n", GLOB);
725 }
726 REGISTER_TEST(Run, 10);
727 }  // namespace test10
728 
729 
730 // test11: FP. Synchronization via CondVar, 2 workers. {{{1
731 // This test is properly synchronized, but currently (Dec 2007)
732 // helgrind reports a false positive.
733 //
734 // Parent:                              Worker1, Worker2:
735 // 1. Start(workers)                    a. read(GLOB)
736 // 2. MU.Lock()                         b. MU.Lock()
737 // 3. while(COND != 2)        /-------- c. CV.Signal()
738 //      CV.Wait(&MU) <-------/          d. MU.Unlock()
739 // 4. MU.Unlock()
740 // 5. write(GLOB)
741 //
742 namespace test11 {
743 int     GLOB = 0;
744 Mutex   MU;
Worker()745 void Worker() {
746   usleep(200000);
747   CHECK(GLOB != 777);
748 
749   MU.Lock();
750   COND++;
751   CV.Signal();
752   MU.Unlock();
753 }
754 
Parent()755 void Parent() {
756   COND = 0;
757 
758   MyThreadArray t(Worker, Worker);
759   t.Start();
760 
761   MU.Lock();
762   while(COND != 2) {
763     CV.Wait(&MU);
764   }
765   MU.Unlock();
766 
767   GLOB = 2;
768 
769   t.Join();
770 }
771 
Run()772 void Run() {
773 //  ANNOTATE_EXPECT_RACE(&GLOB, "test11. FP. Fixed by MSMProp1.");
774   printf("test11: negative\n");
775   Parent();
776   printf("\tGLOB=%d\n", GLOB);
777 }
778 REGISTER_TEST(Run, 11);
779 }  // namespace test11
780 
781 
782 // test12: FP. Synchronization via Mutex, then via PCQ. {{{1
783 namespace test12 {
784 int     GLOB = 0;
785 // This test is properly synchronized, but currently (Dec 2007)
786 // helgrind reports a false positive.
787 //
788 // First, we write to GLOB under MU, then we synchronize via PCQ,
789 // which is essentially a semaphore.
790 //
791 // Putter:                       Getter:
792 // 1. MU.Lock()                  a. MU.Lock()
793 // 2. write(GLOB) <---- MU ----> b. write(GLOB)
794 // 3. MU.Unlock()                c. MU.Unlock()
795 // 4. Q.Put()   ---------------> d. Q.Get()
796 //                               e. write(GLOB)
797 
798 ProducerConsumerQueue Q(INT_MAX);
799 Mutex   MU;
800 
Putter()801 void Putter() {
802   MU.Lock();
803   GLOB++;
804   MU.Unlock();
805 
806   Q.Put(NULL);
807 }
808 
Getter()809 void Getter() {
810   MU.Lock();
811   GLOB++;
812   MU.Unlock();
813 
814   Q.Get();
815   GLOB++;
816 }
817 
Run()818 void Run() {
819 //  ANNOTATE_EXPECT_RACE(&GLOB, "test12. FP. Fixed by MSMProp1.");
820   printf("test12: negative\n");
821   MyThreadArray t(Putter, Getter);
822   t.Start();
823   t.Join();
824   printf("\tGLOB=%d\n", GLOB);
825 }
826 REGISTER_TEST(Run, 12);
827 }  // namespace test12
828 
829 
830 // test13: FP. Synchronization via Mutex, then via LockWhen. {{{1
831 namespace test13 {
832 int     GLOB = 0;
833 // This test is essentially the same as test12, but uses LockWhen
834 // instead of PCQ.
835 //
836 // Waker:                                     Waiter:
837 // 1. MU.Lock()                               a. MU.Lock()
838 // 2. write(GLOB) <---------- MU ---------->  b. write(GLOB)
839 // 3. MU.Unlock()                             c. MU.Unlock()
840 // 4. MU.Lock()                               .
841 // 5. COND = 1                                .
842 // 6. ANNOTATE_CONDVAR_SIGNAL -------\        .
843 // 7. MU.Unlock()                     \       .
844 //                                     \----> d. MU.LockWhen(COND == 1)
845 //                                            e. MU.Unlock()
846 //                                            f. write(GLOB)
847 Mutex   MU;
848 
Waker()849 void Waker() {
850   MU.Lock();
851   GLOB++;
852   MU.Unlock();
853 
854   MU.Lock();
855   COND = 1;
856   ANNOTATE_CONDVAR_SIGNAL(&MU);
857   MU.Unlock();
858 }
859 
Waiter()860 void Waiter() {
861   MU.Lock();
862   GLOB++;
863   MU.Unlock();
864 
865   MU.LockWhen(Condition(&ArgIsOne, &COND));
866   MU.Unlock();
867   GLOB++;
868 }
869 
Run()870 void Run() {
871 //  ANNOTATE_EXPECT_RACE(&GLOB, "test13. FP. Fixed by MSMProp1.");
872   printf("test13: negative\n");
873   COND = 0;
874 
875   MyThreadArray t(Waker, Waiter);
876   t.Start();
877   t.Join();
878 
879   printf("\tGLOB=%d\n", GLOB);
880 }
881 REGISTER_TEST2(Run, 13, FEATURE|NEEDS_ANNOTATIONS);
882 }  // namespace test13
883 
884 
885 // test14: FP. Synchronization via PCQ, reads, 2 workers. {{{1
886 namespace test14 {
887 int     GLOB = 0;
888 // This test is properly synchronized, but currently (Dec 2007)
889 // helgrind reports a false positive.
890 //
891 // This test is similar to test11, but uses PCQ (semaphore).
892 //
893 // Putter2:                  Putter1:                     Getter:
894 // 1. read(GLOB)             a. read(GLOB)
895 // 2. Q2.Put() ----\         b. Q1.Put() -----\           .
896 //                  \                          \--------> A. Q1.Get()
897 //                   \----------------------------------> B. Q2.Get()
898 //                                                        C. write(GLOB)
899 ProducerConsumerQueue Q1(INT_MAX), Q2(INT_MAX);
900 
Putter1()901 void Putter1() {
902   CHECK(GLOB != 777);
903   Q1.Put(NULL);
904 }
Putter2()905 void Putter2() {
906   CHECK(GLOB != 777);
907   Q2.Put(NULL);
908 }
Getter()909 void Getter() {
910   Q1.Get();
911   Q2.Get();
912   GLOB++;
913 }
Run()914 void Run() {
915 //  ANNOTATE_EXPECT_RACE(&GLOB, "test14. FP. Fixed by MSMProp1.");
916   printf("test14: negative\n");
917   MyThreadArray t(Getter, Putter1, Putter2);
918   t.Start();
919   t.Join();
920   printf("\tGLOB=%d\n", GLOB);
921 }
922 REGISTER_TEST(Run, 14);
923 }  // namespace test14
924 
925 
926 // test15: TN. Synchronization via LockWhen. One waker and 2 waiters. {{{1
927 namespace test15 {
928 // Waker:                                   Waiter1, Waiter2:
929 // 1. write(GLOB)
930 // 2. MU.Lock()
931 // 3. COND = 1
932 // 4. ANNOTATE_CONDVAR_SIGNAL ------------> a. MU.LockWhen(COND == 1)
933 // 5. MU.Unlock()                           b. MU.Unlock()
934 //                                          c. read(GLOB)
935 
936 int     GLOB = 0;
937 Mutex   MU;
938 
Waker()939 void Waker() {
940   GLOB = 2;
941 
942   MU.Lock();
943   COND = 1;
944   ANNOTATE_CONDVAR_SIGNAL(&MU);
945   MU.Unlock();
946 };
947 
Waiter()948 void Waiter() {
949   MU.LockWhen(Condition(&ArgIsOne, &COND));
950   MU.Unlock();
951   CHECK(GLOB != 777);
952 }
953 
954 
Run()955 void Run() {
956   COND = 0;
957   printf("test15: negative\n");
958   MyThreadArray t(Waker, Waiter, Waiter);
959   t.Start();
960   t.Join();
961   printf("\tGLOB=%d\n", GLOB);
962 }
963 REGISTER_TEST(Run, 15);
964 }  // namespace test15
965 
966 
967 // test16: FP. Barrier (emulated by CV), 2 threads. {{{1
968 namespace test16 {
969 // Worker1:                                     Worker2:
970 // 1. MU.Lock()                                 a. MU.Lock()
971 // 2. write(GLOB) <------------ MU ---------->  b. write(GLOB)
972 // 3. MU.Unlock()                               c. MU.Unlock()
973 // 4. MU2.Lock()                                d. MU2.Lock()
974 // 5. COND--                                    e. COND--
975 // 6. ANNOTATE_CONDVAR_SIGNAL(MU2) ---->V       .
976 // 7. MU2.Await(COND == 0) <------------+------ f. ANNOTATE_CONDVAR_SIGNAL(MU2)
977 // 8. MU2.Unlock()                      V-----> g. MU2.Await(COND == 0)
978 // 9. read(GLOB)                                h. MU2.Unlock()
979 //                                              i. read(GLOB)
980 //
981 //
982 // TODO: This way we may create too many edges in happens-before graph.
983 // Arndt Mühlenfeld in his PhD (TODO: link) suggests creating special nodes in
984 // happens-before graph to reduce the total number of edges.
985 // See figure 3.14.
986 //
987 //
988 int     GLOB = 0;
989 Mutex   MU;
990 Mutex MU2;
991 
Worker()992 void Worker() {
993   MU.Lock();
994   GLOB++;
995   MU.Unlock();
996 
997   MU2.Lock();
998   COND--;
999   ANNOTATE_CONDVAR_SIGNAL(&MU2);
1000   MU2.Await(Condition(&ArgIsZero, &COND));
1001   MU2.Unlock();
1002 
1003   CHECK(GLOB == 2);
1004 }
1005 
Run()1006 void Run() {
1007 //  ANNOTATE_EXPECT_RACE(&GLOB, "test16. FP. Fixed by MSMProp1 + Barrier support.");
1008   COND = 2;
1009   printf("test16: negative\n");
1010   MyThreadArray t(Worker, Worker);
1011   t.Start();
1012   t.Join();
1013   printf("\tGLOB=%d\n", GLOB);
1014 }
1015 REGISTER_TEST2(Run, 16, FEATURE|NEEDS_ANNOTATIONS);
1016 }  // namespace test16
1017 
1018 
1019 // test17: FP. Barrier (emulated by CV), 3 threads. {{{1
1020 namespace test17 {
1021 // Same as test16, but with 3 threads.
1022 int     GLOB = 0;
1023 Mutex   MU;
1024 Mutex MU2;
1025 
Worker()1026 void Worker() {
1027   MU.Lock();
1028   GLOB++;
1029   MU.Unlock();
1030 
1031   MU2.Lock();
1032   COND--;
1033   ANNOTATE_CONDVAR_SIGNAL(&MU2);
1034   MU2.Await(Condition(&ArgIsZero, &COND));
1035   MU2.Unlock();
1036 
1037   CHECK(GLOB == 3);
1038 }
1039 
Run()1040 void Run() {
1041 //  ANNOTATE_EXPECT_RACE(&GLOB, "test17. FP. Fixed by MSMProp1 + Barrier support.");
1042   COND = 3;
1043   printf("test17: negative\n");
1044   MyThreadArray t(Worker, Worker, Worker);
1045   t.Start();
1046   t.Join();
1047   printf("\tGLOB=%d\n", GLOB);
1048 }
1049 REGISTER_TEST2(Run, 17, FEATURE|NEEDS_ANNOTATIONS);
1050 }  // namespace test17
1051 
1052 
1053 // test18: TN. Synchronization via Await(), signaller gets there first. {{{1
1054 namespace test18 {
1055 int     GLOB = 0;
1056 Mutex   MU;
1057 // Same as test03, but uses Mutex::Await() instead of Mutex::LockWhen().
1058 
Waker()1059 void Waker() {
1060   usleep(100000);  // Make sure the waiter blocks.
1061   GLOB = 1;
1062 
1063   MU.Lock();
1064   COND = 1; // We are done! Tell the Waiter.
1065   MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
1066 }
Waiter()1067 void Waiter() {
1068   ThreadPool pool(1);
1069   pool.StartWorkers();
1070   COND = 0;
1071   pool.Add(NewCallback(Waker));
1072 
1073   MU.Lock();
1074   MU.Await(Condition(&ArgIsOne, &COND));  // calls ANNOTATE_CONDVAR_WAIT
1075   MU.Unlock();  // Waker is done!
1076 
1077   GLOB = 2;
1078 }
Run()1079 void Run() {
1080   printf("test18: negative\n");
1081   Waiter();
1082   printf("\tGLOB=%d\n", GLOB);
1083 }
1084 REGISTER_TEST2(Run, 18, FEATURE|NEEDS_ANNOTATIONS);
1085 }  // namespace test18
1086 
1087 // test19: TN. Synchronization via AwaitWithTimeout(). {{{1
1088 namespace test19 {
1089 int     GLOB = 0;
1090 // Same as test18, but with AwaitWithTimeout. Do not timeout.
1091 Mutex   MU;
Waker()1092 void Waker() {
1093   usleep(100000);  // Make sure the waiter blocks.
1094   GLOB = 1;
1095 
1096   MU.Lock();
1097   COND = 1; // We are done! Tell the Waiter.
1098   MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
1099 }
Waiter()1100 void Waiter() {
1101   ThreadPool pool(1);
1102   pool.StartWorkers();
1103   COND = 0;
1104   pool.Add(NewCallback(Waker));
1105 
1106   MU.Lock();
1107   CHECK(MU.AwaitWithTimeout(Condition(&ArgIsOne, &COND), INT_MAX));
1108   MU.Unlock();
1109 
1110   GLOB = 2;
1111 }
Run()1112 void Run() {
1113   printf("test19: negative\n");
1114   Waiter();
1115   printf("\tGLOB=%d\n", GLOB);
1116 }
1117 REGISTER_TEST2(Run, 19, FEATURE|NEEDS_ANNOTATIONS);
1118 }  // namespace test19
1119 
1120 // test20: TP. Incorrect synchronization via AwaitWhen(), timeout. {{{1
1121 namespace test20 {
1122 int     GLOB = 0;
1123 Mutex   MU;
1124 // True race. We timeout in AwaitWhen.
Waker()1125 void Waker() {
1126   GLOB = 1;
1127   usleep(100 * 1000);
1128 }
Waiter()1129 void Waiter() {
1130   ThreadPool pool(1);
1131   pool.StartWorkers();
1132   COND = 0;
1133   pool.Add(NewCallback(Waker));
1134 
1135   MU.Lock();
1136   CHECK(!MU.AwaitWithTimeout(Condition(&ArgIsOne, &COND), 100));
1137   MU.Unlock();
1138 
1139   GLOB = 2;
1140 }
Run()1141 void Run() {
1142   FAST_MODE_INIT(&GLOB);
1143   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test20. TP.");
1144   printf("test20: positive\n");
1145   Waiter();
1146   printf("\tGLOB=%d\n", GLOB);
1147 }
1148 REGISTER_TEST2(Run, 20, FEATURE|NEEDS_ANNOTATIONS);
1149 }  // namespace test20
1150 
1151 // test21: TP. Incorrect synchronization via LockWhenWithTimeout(). {{{1
1152 namespace test21 {
1153 int     GLOB = 0;
1154 // True race. We timeout in LockWhenWithTimeout().
1155 Mutex   MU;
Waker()1156 void Waker() {
1157   GLOB = 1;
1158   usleep(100 * 1000);
1159 }
Waiter()1160 void Waiter() {
1161   ThreadPool pool(1);
1162   pool.StartWorkers();
1163   COND = 0;
1164   pool.Add(NewCallback(Waker));
1165 
1166   CHECK(!MU.LockWhenWithTimeout(Condition(&ArgIsOne, &COND), 100));
1167   MU.Unlock();
1168 
1169   GLOB = 2;
1170 }
Run()1171 void Run() {
1172   FAST_MODE_INIT(&GLOB);
1173   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test21. TP.");
1174   printf("test21: positive\n");
1175   Waiter();
1176   printf("\tGLOB=%d\n", GLOB);
1177 }
1178 REGISTER_TEST2(Run, 21, FEATURE|NEEDS_ANNOTATIONS);
1179 }  // namespace test21
1180 
1181 // test22: TP. Incorrect synchronization via CondVar::WaitWithTimeout(). {{{1
1182 namespace test22 {
1183 int     GLOB = 0;
1184 Mutex   MU;
1185 // True race. We timeout in CondVar::WaitWithTimeout().
Waker()1186 void Waker() {
1187   GLOB = 1;
1188   usleep(100 * 1000);
1189 }
Waiter()1190 void Waiter() {
1191   ThreadPool pool(1);
1192   pool.StartWorkers();
1193   COND = 0;
1194   pool.Add(NewCallback(Waker));
1195 
1196   int64_t ms_left_to_wait = 100;
1197   int64_t deadline_ms = GetCurrentTimeMillis() + ms_left_to_wait;
1198   MU.Lock();
1199   while(COND != 1 && ms_left_to_wait > 0) {
1200     CV.WaitWithTimeout(&MU, ms_left_to_wait);
1201     ms_left_to_wait = deadline_ms - GetCurrentTimeMillis();
1202   }
1203   MU.Unlock();
1204 
1205   GLOB = 2;
1206 }
Run()1207 void Run() {
1208   FAST_MODE_INIT(&GLOB);
1209   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test22. TP.");
1210   printf("test22: positive\n");
1211   Waiter();
1212   printf("\tGLOB=%d\n", GLOB);
1213 }
1214 REGISTER_TEST(Run, 22);
1215 }  // namespace test22
1216 
1217 // test23: TN. TryLock, ReaderLock, ReaderTryLock. {{{1
1218 namespace test23 {
1219 // Correct synchronization with TryLock, Lock, ReaderTryLock, ReaderLock.
1220 int     GLOB = 0;
1221 Mutex   MU;
Worker_TryLock()1222 void Worker_TryLock() {
1223   for (int i = 0; i < 20; i++) {
1224     while (true) {
1225       if (MU.TryLock()) {
1226         GLOB++;
1227         MU.Unlock();
1228         break;
1229       }
1230       usleep(1000);
1231     }
1232   }
1233 }
1234 
Worker_ReaderTryLock()1235 void Worker_ReaderTryLock() {
1236   for (int i = 0; i < 20; i++) {
1237     while (true) {
1238       if (MU.ReaderTryLock()) {
1239         CHECK(GLOB != 777);
1240         MU.ReaderUnlock();
1241         break;
1242       }
1243       usleep(1000);
1244     }
1245   }
1246 }
1247 
Worker_ReaderLock()1248 void Worker_ReaderLock() {
1249   for (int i = 0; i < 20; i++) {
1250     MU.ReaderLock();
1251     CHECK(GLOB != 777);
1252     MU.ReaderUnlock();
1253     usleep(1000);
1254   }
1255 }
1256 
Worker_Lock()1257 void Worker_Lock() {
1258   for (int i = 0; i < 20; i++) {
1259     MU.Lock();
1260     GLOB++;
1261     MU.Unlock();
1262     usleep(1000);
1263   }
1264 }
1265 
Run()1266 void Run() {
1267   printf("test23: negative\n");
1268   MyThreadArray t(Worker_TryLock,
1269                   Worker_ReaderTryLock,
1270                   Worker_ReaderLock,
1271                   Worker_Lock
1272                   );
1273   t.Start();
1274   t.Join();
1275   printf("\tGLOB=%d\n", GLOB);
1276 }
1277 REGISTER_TEST(Run, 23);
1278 }  // namespace test23
1279 
1280 // test24: TN. Synchronization via ReaderLockWhen(). {{{1
1281 namespace test24 {
1282 int     GLOB = 0;
1283 Mutex   MU;
1284 // Same as test03, but uses ReaderLockWhen().
1285 
Waker()1286 void Waker() {
1287   usleep(100000);  // Make sure the waiter blocks.
1288   GLOB = 1;
1289 
1290   MU.Lock();
1291   COND = 1; // We are done! Tell the Waiter.
1292   MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
1293 }
Waiter()1294 void Waiter() {
1295   ThreadPool pool(1);
1296   pool.StartWorkers();
1297   COND = 0;
1298   pool.Add(NewCallback(Waker));
1299   MU.ReaderLockWhen(Condition(&ArgIsOne, &COND));
1300   MU.ReaderUnlock();
1301 
1302   GLOB = 2;
1303 }
Run()1304 void Run() {
1305   printf("test24: negative\n");
1306   Waiter();
1307   printf("\tGLOB=%d\n", GLOB);
1308 }
1309 REGISTER_TEST2(Run, 24, FEATURE|NEEDS_ANNOTATIONS);
1310 }  // namespace test24
1311 
1312 // test25: TN. Synchronization via ReaderLockWhenWithTimeout(). {{{1
1313 namespace test25 {
1314 int     GLOB = 0;
1315 Mutex   MU;
1316 // Same as test24, but uses ReaderLockWhenWithTimeout().
1317 // We do not timeout.
1318 
Waker()1319 void Waker() {
1320   usleep(100000);  // Make sure the waiter blocks.
1321   GLOB = 1;
1322 
1323   MU.Lock();
1324   COND = 1; // We are done! Tell the Waiter.
1325   MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
1326 }
Waiter()1327 void Waiter() {
1328   ThreadPool pool(1);
1329   pool.StartWorkers();
1330   COND = 0;
1331   pool.Add(NewCallback(Waker));
1332   CHECK(MU.ReaderLockWhenWithTimeout(Condition(&ArgIsOne, &COND), INT_MAX));
1333   MU.ReaderUnlock();
1334 
1335   GLOB = 2;
1336 }
Run()1337 void Run() {
1338   printf("test25: negative\n");
1339   Waiter();
1340   printf("\tGLOB=%d\n", GLOB);
1341 }
1342 REGISTER_TEST2(Run, 25, FEATURE|NEEDS_ANNOTATIONS);
1343 }  // namespace test25
1344 
1345 // test26: TP. Incorrect synchronization via ReaderLockWhenWithTimeout(). {{{1
1346 namespace test26 {
1347 int     GLOB = 0;
1348 Mutex   MU;
1349 // Same as test25, but we timeout and incorrectly assume happens-before.
1350 
Waker()1351 void Waker() {
1352   GLOB = 1;
1353   usleep(10000);
1354 }
Waiter()1355 void Waiter() {
1356   ThreadPool pool(1);
1357   pool.StartWorkers();
1358   COND = 0;
1359   pool.Add(NewCallback(Waker));
1360   CHECK(!MU.ReaderLockWhenWithTimeout(Condition(&ArgIsOne, &COND), 100));
1361   MU.ReaderUnlock();
1362 
1363   GLOB = 2;
1364 }
Run()1365 void Run() {
1366   FAST_MODE_INIT(&GLOB);
1367   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test26. TP");
1368   printf("test26: positive\n");
1369   Waiter();
1370   printf("\tGLOB=%d\n", GLOB);
1371 }
1372 REGISTER_TEST2(Run, 26, FEATURE|NEEDS_ANNOTATIONS);
1373 }  // namespace test26
1374 
1375 
1376 // test27: TN. Simple synchronization via SpinLock. {{{1
1377 namespace test27 {
1378 #ifndef NO_SPINLOCK
1379 int     GLOB = 0;
1380 SpinLock MU;
Worker()1381 void Worker() {
1382   MU.Lock();
1383   GLOB++;
1384   MU.Unlock();
1385   usleep(10000);
1386 }
1387 
Run()1388 void Run() {
1389   printf("test27: negative\n");
1390   MyThreadArray t(Worker, Worker, Worker, Worker);
1391   t.Start();
1392   t.Join();
1393   printf("\tGLOB=%d\n", GLOB);
1394 }
1395 REGISTER_TEST2(Run, 27, FEATURE|NEEDS_ANNOTATIONS);
1396 #endif // NO_SPINLOCK
1397 }  // namespace test27
1398 
1399 
1400 // test28: TN. Synchronization via Mutex, then PCQ. 3 threads {{{1
1401 namespace test28 {
1402 // Putter1:                       Getter:                         Putter2:
1403 // 1. MU.Lock()                                                   A. MU.Lock()
1404 // 2. write(GLOB)                                                 B. write(GLOB)
1405 // 3. MU.Unlock()                                                 C. MU.Unlock()
1406 // 4. Q.Put() ---------\                                 /------- D. Q.Put()
1407 // 5. MU.Lock()         \-------> a. Q.Get()            /         E. MU.Lock()
1408 // 6. read(GLOB)                  b. Q.Get() <---------/          F. read(GLOB)
1409 // 7. MU.Unlock()                   (sleep)                       G. MU.Unlock()
1410 //                                c. read(GLOB)
1411 ProducerConsumerQueue Q(INT_MAX);
1412 int     GLOB = 0;
1413 Mutex   MU;
1414 
Putter()1415 void Putter() {
1416   MU.Lock();
1417   GLOB++;
1418   MU.Unlock();
1419 
1420   Q.Put(NULL);
1421 
1422   MU.Lock();
1423   CHECK(GLOB != 777);
1424   MU.Unlock();
1425 }
1426 
Getter()1427 void Getter() {
1428   Q.Get();
1429   Q.Get();
1430   usleep(100000);
1431   CHECK(GLOB == 2);
1432 }
1433 
Run()1434 void Run() {
1435   printf("test28: negative\n");
1436   MyThreadArray t(Getter, Putter, Putter);
1437   t.Start();
1438   t.Join();
1439   printf("\tGLOB=%d\n", GLOB);
1440 }
1441 REGISTER_TEST(Run, 28);
1442 }  // namespace test28
1443 
1444 
1445 // test29: TN. Synchronization via Mutex, then PCQ. 4 threads. {{{1
1446 namespace test29 {
1447 // Similar to test28, but has two Getters and two PCQs.
1448 ProducerConsumerQueue *Q1, *Q2;
1449 Mutex   MU;
1450 int     GLOB = 0;
1451 
Putter(ProducerConsumerQueue * q)1452 void Putter(ProducerConsumerQueue *q) {
1453   MU.Lock();
1454   GLOB++;
1455   MU.Unlock();
1456 
1457   q->Put(NULL);
1458   q->Put(NULL);
1459 
1460   MU.Lock();
1461   CHECK(GLOB != 777);
1462   MU.Unlock();
1463 
1464 }
1465 
Putter1()1466 void Putter1() { Putter(Q1); }
Putter2()1467 void Putter2() { Putter(Q2); }
1468 
Getter()1469 void Getter() {
1470   Q1->Get();
1471   Q2->Get();
1472   usleep(100000);
1473   CHECK(GLOB == 2);
1474   usleep(48000); //  TODO: remove this when FP in test32 is fixed.
1475 }
1476 
Run()1477 void Run() {
1478   printf("test29: negative\n");
1479   Q1 = new ProducerConsumerQueue(INT_MAX);
1480   Q2 = new ProducerConsumerQueue(INT_MAX);
1481   MyThreadArray t(Getter, Getter, Putter1, Putter2);
1482   t.Start();
1483   t.Join();
1484   printf("\tGLOB=%d\n", GLOB);
1485   delete Q1;
1486   delete Q2;
1487 }
1488 REGISTER_TEST(Run, 29);
1489 }  // namespace test29
1490 
1491 
1492 // test30: TN. Synchronization via 'safe' race. Writer vs multiple Readers. {{{1
1493 namespace test30 {
1494 // This test shows a very risky kind of synchronization which is very easy
1495 // to get wrong. Actually, I am not sure I've got it right.
1496 //
1497 // Writer:                                 Reader1, Reader2, ..., ReaderN:
1498 // 1. write(GLOB[i]: i >= BOUNDARY)        a. n = BOUNDARY
1499 // 2. HAPPENS_BEFORE(BOUNDARY+1)  -------> b. HAPPENS_AFTER(n)
1500 // 3. BOUNDARY++;                          c. read(GLOB[i]: i < n)
1501 //
1502 // Here we have a 'safe' race on accesses to BOUNDARY and
1503 // no actual races on accesses to GLOB[]:
1504 // Writer writes to GLOB[i] where i>=BOUNDARY and then increments BOUNDARY.
1505 // Readers read BOUNDARY and read GLOB[i] where i<BOUNDARY.
1506 //
1507 // I am not completely sure that this scheme guaranties no race between
1508 // accesses to GLOB since compilers and CPUs
1509 // are free to rearrange memory operations.
1510 // I am actually sure that this scheme is wrong unless we use
1511 // some smart memory fencing...
1512 
1513 
1514 const int N = 48;
1515 static int GLOB[N];
1516 volatile int BOUNDARY = 0;
1517 
Writer()1518 void Writer() {
1519   for (int i = 0; i < N; i++) {
1520     CHECK(BOUNDARY == i);
1521     for (int j = i; j < N; j++) {
1522       GLOB[j] = j;
1523     }
1524     ANNOTATE_HAPPENS_BEFORE(reinterpret_cast<void*>(BOUNDARY+1));
1525     BOUNDARY++;
1526     usleep(1000);
1527   }
1528 }
1529 
Reader()1530 void Reader() {
1531   int n;
1532   do {
1533     n = BOUNDARY;
1534     if (n == 0) continue;
1535     ANNOTATE_HAPPENS_AFTER(reinterpret_cast<void*>(n));
1536     for (int i = 0; i < n; i++) {
1537       CHECK(GLOB[i] == i);
1538     }
1539     usleep(100);
1540   } while(n < N);
1541 }
1542 
Run()1543 void Run() {
1544   FAST_MODE_INIT(&BOUNDARY);
1545   ANNOTATE_EXPECT_RACE((void*)(&BOUNDARY), "test30. Sync via 'safe' race.");
1546   printf("test30: negative\n");
1547   MyThreadArray t(Writer, Reader, Reader, Reader);
1548   t.Start();
1549   t.Join();
1550   printf("\tGLOB=%d\n", GLOB[N-1]);
1551 }
1552 REGISTER_TEST2(Run, 30, FEATURE|NEEDS_ANNOTATIONS);
1553 }  // namespace test30
1554 
1555 
1556 // test31: TN. Synchronization via 'safe' race. Writer vs Writer. {{{1
1557 namespace test31 {
1558 // This test is similar to test30, but
1559 // it has one Writer instead of mulitple Readers.
1560 //
1561 // Writer1:                                Writer2
1562 // 1. write(GLOB[i]: i >= BOUNDARY)        a. n = BOUNDARY
1563 // 2. HAPPENS_BEFORE(BOUNDARY+1)  -------> b. HAPPENS_AFTER(n)
1564 // 3. BOUNDARY++;                          c. write(GLOB[i]: i < n)
1565 //
1566 
1567 const int N = 48;
1568 static int GLOB[N];
1569 volatile int BOUNDARY = 0;
1570 
Writer1()1571 void Writer1() {
1572   for (int i = 0; i < N; i++) {
1573     CHECK(BOUNDARY == i);
1574     for (int j = i; j < N; j++) {
1575       GLOB[j] = j;
1576     }
1577     ANNOTATE_HAPPENS_BEFORE(reinterpret_cast<void*>(BOUNDARY+1));
1578     BOUNDARY++;
1579     usleep(1000);
1580   }
1581 }
1582 
Writer2()1583 void Writer2() {
1584   int n;
1585   do {
1586     n = BOUNDARY;
1587     if (n == 0) continue;
1588     ANNOTATE_HAPPENS_AFTER(reinterpret_cast<void*>(n));
1589     for (int i = 0; i < n; i++) {
1590       if(GLOB[i] == i) {
1591         GLOB[i]++;
1592       }
1593     }
1594     usleep(100);
1595   } while(n < N);
1596 }
1597 
Run()1598 void Run() {
1599   FAST_MODE_INIT(&BOUNDARY);
1600   ANNOTATE_EXPECT_RACE((void*)(&BOUNDARY), "test31. Sync via 'safe' race.");
1601   printf("test31: negative\n");
1602   MyThreadArray t(Writer1, Writer2);
1603   t.Start();
1604   t.Join();
1605   printf("\tGLOB=%d\n", GLOB[N-1]);
1606 }
1607 REGISTER_TEST2(Run, 31, FEATURE|NEEDS_ANNOTATIONS);
1608 }  // namespace test31
1609 
1610 
1611 // test32: FP. Synchronization via thread create/join. W/R. {{{1
1612 namespace test32 {
1613 // This test is well synchronized but helgrind 3.3.0 reports a race.
1614 //
1615 // Parent:                   Writer:               Reader:
1616 // 1. Start(Reader) -----------------------\       .
1617 //                                          \      .
1618 // 2. Start(Writer) ---\                     \     .
1619 //                      \---> a. MU.Lock()    \--> A. sleep(long enough)
1620 //                            b. write(GLOB)
1621 //                      /---- c. MU.Unlock()
1622 // 3. Join(Writer) <---/
1623 //                                                 B. MU.Lock()
1624 //                                                 C. read(GLOB)
1625 //                                   /------------ D. MU.Unlock()
1626 // 4. Join(Reader) <----------------/
1627 // 5. write(GLOB)
1628 //
1629 //
1630 // The call to sleep() in Reader is not part of synchronization,
1631 // it is required to trigger the false positive in helgrind 3.3.0.
1632 //
1633 int     GLOB = 0;
1634 Mutex   MU;
1635 
Writer()1636 void Writer() {
1637   MU.Lock();
1638   GLOB = 1;
1639   MU.Unlock();
1640 }
1641 
Reader()1642 void Reader() {
1643   usleep(480000);
1644   MU.Lock();
1645   CHECK(GLOB != 777);
1646   MU.Unlock();
1647 }
1648 
Parent()1649 void Parent() {
1650   MyThread r(Reader);
1651   MyThread w(Writer);
1652   r.Start();
1653   w.Start();
1654 
1655   w.Join();  // 'w' joins first.
1656   r.Join();
1657 
1658   GLOB = 2;
1659 }
1660 
Run()1661 void Run() {
1662 //  ANNOTATE_EXPECT_RACE(&GLOB, "test32. FP. Fixed by MSMProp1.");
1663   printf("test32: negative\n");
1664   Parent();
1665   printf("\tGLOB=%d\n", GLOB);
1666 }
1667 
1668 REGISTER_TEST(Run, 32);
1669 }  // namespace test32
1670 
1671 
1672 // test33: STAB. Stress test for the number of thread sets (TSETs). {{{1
1673 namespace test33 {
1674 int     GLOB = 0;
1675 // Here we access N memory locations from within log(N) threads.
1676 // We do it in such a way that helgrind creates nearly all possible TSETs.
1677 // Then we join all threads and start again (N_iter times).
1678 const int N_iter = 48;
1679 const int Nlog  = 15;
1680 const int N     = 1 << Nlog;
1681 static int ARR[N];
1682 Mutex   MU;
1683 
Worker()1684 void Worker() {
1685   MU.Lock();
1686   int n = ++GLOB;
1687   MU.Unlock();
1688 
1689   n %= Nlog;
1690   for (int i = 0; i < N; i++) {
1691     // ARR[i] is accessed by threads from i-th subset
1692     if (i & (1 << n)) {
1693         CHECK(ARR[i] == 0);
1694     }
1695   }
1696 }
1697 
Run()1698 void Run() {
1699   printf("test33:\n");
1700 
1701   std::vector<MyThread*> vec(Nlog);
1702 
1703   for (int j = 0; j < N_iter; j++) {
1704     // Create and start Nlog threads
1705     for (int i = 0; i < Nlog; i++) {
1706       vec[i] = new MyThread(Worker);
1707     }
1708     for (int i = 0; i < Nlog; i++) {
1709       vec[i]->Start();
1710     }
1711     // Join all threads.
1712     for (int i = 0; i < Nlog; i++) {
1713       vec[i]->Join();
1714       delete vec[i];
1715     }
1716     printf("------------------\n");
1717   }
1718 
1719   printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n",
1720          GLOB, ARR[1], ARR[7], ARR[N-1]);
1721 }
1722 REGISTER_TEST2(Run, 33, STABILITY|EXCLUDE_FROM_ALL);
1723 }  // namespace test33
1724 
1725 
1726 // test34: STAB. Stress test for the number of locks sets (LSETs). {{{1
1727 namespace test34 {
1728 // Similar to test33, but for lock sets.
1729 int     GLOB = 0;
1730 const int N_iter = 48;
1731 const int Nlog = 10;
1732 const int N    = 1 << Nlog;
1733 static int ARR[N];
1734 static Mutex *MUs[Nlog];
1735 
Worker()1736 void Worker() {
1737     for (int i = 0; i < N; i++) {
1738       // ARR[i] is protected by MUs from i-th subset of all MUs
1739       for (int j = 0; j < Nlog; j++)  if (i & (1 << j)) MUs[j]->Lock();
1740       CHECK(ARR[i] == 0);
1741       for (int j = 0; j < Nlog; j++)  if (i & (1 << j)) MUs[j]->Unlock();
1742     }
1743 }
1744 
Run()1745 void Run() {
1746   printf("test34:\n");
1747   for (int iter = 0; iter < N_iter; iter++) {
1748     for (int i = 0; i < Nlog; i++) {
1749       MUs[i] = new Mutex;
1750     }
1751     MyThreadArray t(Worker, Worker);
1752     t.Start();
1753     t.Join();
1754     for (int i = 0; i < Nlog; i++) {
1755       delete MUs[i];
1756     }
1757     printf("------------------\n");
1758   }
1759   printf("\tGLOB=%d\n", GLOB);
1760 }
1761 REGISTER_TEST2(Run, 34, STABILITY|EXCLUDE_FROM_ALL);
1762 }  // namespace test34
1763 
1764 
1765 // test35: PERF. Lots of mutexes and lots of call to free().  {{{1
1766 namespace test35 {
1767 // Helgrind 3.3.0 has very slow in shadow_mem_make_NoAccess(). Fixed locally.
1768 // With the fix helgrind runs this test about a minute.
1769 // Without the fix -- about 5 minutes. (on c2d 2.4GHz).
1770 //
1771 // TODO: need to figure out the best way for performance testing.
1772 int **ARR;
1773 const int N_mu   = 25000;
1774 const int N_free = 48000;
1775 
Worker()1776 void Worker() {
1777   for (int i = 0; i < N_free; i++)
1778     CHECK(777 == *ARR[i]);
1779 }
1780 
Run()1781 void Run() {
1782   printf("test35:\n");
1783   std::vector<Mutex*> mus;
1784 
1785   ARR = new int *[N_free];
1786   for (int i = 0; i < N_free; i++) {
1787     const int c = N_free / N_mu;
1788     if ((i % c) == 0) {
1789       mus.push_back(new Mutex);
1790       mus.back()->Lock();
1791       mus.back()->Unlock();
1792     }
1793     ARR[i] = new int(777);
1794   }
1795 
1796   // Need to put all ARR[i] into shared state in order
1797   // to trigger the performance bug.
1798   MyThreadArray t(Worker, Worker);
1799   t.Start();
1800   t.Join();
1801 
1802   for (int i = 0; i < N_free; i++) delete ARR[i];
1803   delete [] ARR;
1804 
1805   for (size_t i = 0; i < mus.size(); i++) {
1806     delete mus[i];
1807   }
1808 }
1809 REGISTER_TEST2(Run, 35, PERFORMANCE|EXCLUDE_FROM_ALL);
1810 }  // namespace test35
1811 
1812 
1813 // test36: TN. Synchronization via Mutex, then PCQ. 3 threads. W/W {{{1
1814 namespace test36 {
1815 // variation of test28 (W/W instead of W/R)
1816 
1817 // Putter1:                       Getter:                         Putter2:
1818 // 1. MU.Lock();                                                  A. MU.Lock()
1819 // 2. write(GLOB)                                                 B. write(GLOB)
1820 // 3. MU.Unlock()                                                 C. MU.Unlock()
1821 // 4. Q.Put() ---------\                                 /------- D. Q.Put()
1822 // 5. MU1.Lock()        \-------> a. Q.Get()            /         E. MU1.Lock()
1823 // 6. MU.Lock()                   b. Q.Get() <---------/          F. MU.Lock()
1824 // 7. write(GLOB)                                                 G. write(GLOB)
1825 // 8. MU.Unlock()                                                 H. MU.Unlock()
1826 // 9. MU1.Unlock()                  (sleep)                       I. MU1.Unlock()
1827 //                                c. MU1.Lock()
1828 //                                d. write(GLOB)
1829 //                                e. MU1.Unlock()
1830 ProducerConsumerQueue Q(INT_MAX);
1831 int     GLOB = 0;
1832 Mutex   MU, MU1;
1833 
Putter()1834 void Putter() {
1835   MU.Lock();
1836   GLOB++;
1837   MU.Unlock();
1838 
1839   Q.Put(NULL);
1840 
1841   MU1.Lock();
1842   MU.Lock();
1843   GLOB++;
1844   MU.Unlock();
1845   MU1.Unlock();
1846 }
1847 
Getter()1848 void Getter() {
1849   Q.Get();
1850   Q.Get();
1851   usleep(100000);
1852   MU1.Lock();
1853   GLOB++;
1854   MU1.Unlock();
1855 }
1856 
Run()1857 void Run() {
1858   printf("test36: negative \n");
1859   MyThreadArray t(Getter, Putter, Putter);
1860   t.Start();
1861   t.Join();
1862   printf("\tGLOB=%d\n", GLOB);
1863 }
1864 REGISTER_TEST(Run, 36);
1865 }  // namespace test36
1866 
1867 
1868 // test37: TN. Simple synchronization (write vs read). {{{1
1869 namespace test37 {
1870 int     GLOB = 0;
1871 Mutex   MU;
1872 // Similar to test10, but properly locked.
1873 // Writer:             Reader:
1874 // 1. MU.Lock()
1875 // 2. write
1876 // 3. MU.Unlock()
1877 //                    a. MU.Lock()
1878 //                    b. read
1879 //                    c. MU.Unlock();
1880 
Writer()1881 void Writer() {
1882   MU.Lock();
1883   GLOB = 3;
1884   MU.Unlock();
1885 }
Reader()1886 void Reader() {
1887   usleep(100000);
1888   MU.Lock();
1889   CHECK(GLOB != -777);
1890   MU.Unlock();
1891 }
1892 
Run()1893 void Run() {
1894   printf("test37: negative\n");
1895   MyThreadArray t(Writer, Reader);
1896   t.Start();
1897   t.Join();
1898   printf("\tGLOB=%d\n", GLOB);
1899 }
1900 REGISTER_TEST(Run, 37);
1901 }  // namespace test37
1902 
1903 
1904 // test38: TN. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1
1905 namespace test38 {
1906 // Fusion of test29 and test36.
1907 
1908 // Putter1:            Putter2:           Getter1:       Getter2:
1909 //    MU1.Lock()          MU1.Lock()
1910 //    write(GLOB)         write(GLOB)
1911 //    MU1.Unlock()        MU1.Unlock()
1912 //    Q1.Put()            Q2.Put()
1913 //    Q1.Put()            Q2.Put()
1914 //    MU1.Lock()          MU1.Lock()
1915 //    MU2.Lock()          MU2.Lock()
1916 //    write(GLOB)         write(GLOB)
1917 //    MU2.Unlock()        MU2.Unlock()
1918 //    MU1.Unlock()        MU1.Unlock()     sleep          sleep
1919 //                                         Q1.Get()       Q1.Get()
1920 //                                         Q2.Get()       Q2.Get()
1921 //                                         MU2.Lock()     MU2.Lock()
1922 //                                         write(GLOB)    write(GLOB)
1923 //                                         MU2.Unlock()   MU2.Unlock()
1924 //
1925 
1926 
1927 ProducerConsumerQueue *Q1, *Q2;
1928 int     GLOB = 0;
1929 Mutex   MU, MU1, MU2;
1930 
Putter(ProducerConsumerQueue * q)1931 void Putter(ProducerConsumerQueue *q) {
1932   MU1.Lock();
1933   GLOB++;
1934   MU1.Unlock();
1935 
1936   q->Put(NULL);
1937   q->Put(NULL);
1938 
1939   MU1.Lock();
1940   MU2.Lock();
1941   GLOB++;
1942   MU2.Unlock();
1943   MU1.Unlock();
1944 
1945 }
1946 
Putter1()1947 void Putter1() { Putter(Q1); }
Putter2()1948 void Putter2() { Putter(Q2); }
1949 
Getter()1950 void Getter() {
1951   usleep(100000);
1952   Q1->Get();
1953   Q2->Get();
1954 
1955   MU2.Lock();
1956   GLOB++;
1957   MU2.Unlock();
1958 
1959   usleep(48000); //  TODO: remove this when FP in test32 is fixed.
1960 }
1961 
Run()1962 void Run() {
1963   printf("test38: negative\n");
1964   Q1 = new ProducerConsumerQueue(INT_MAX);
1965   Q2 = new ProducerConsumerQueue(INT_MAX);
1966   MyThreadArray t(Getter, Getter, Putter1, Putter2);
1967   t.Start();
1968   t.Join();
1969   printf("\tGLOB=%d\n", GLOB);
1970   delete Q1;
1971   delete Q2;
1972 }
1973 REGISTER_TEST(Run, 38);
1974 }  // namespace test38
1975 
1976 // test39: FP. Barrier. {{{1
1977 namespace test39 {
1978 #ifndef NO_BARRIER
1979 // Same as test17 but uses Barrier class (pthread_barrier_t).
1980 int     GLOB = 0;
1981 const int N_threads = 3;
1982 Barrier barrier(N_threads);
1983 Mutex   MU;
1984 
Worker()1985 void Worker() {
1986   MU.Lock();
1987   GLOB++;
1988   MU.Unlock();
1989   barrier.Block();
1990   CHECK(GLOB == N_threads);
1991 }
Run()1992 void Run() {
1993   ANNOTATE_TRACE_MEMORY(&GLOB);
1994 //  ANNOTATE_EXPECT_RACE(&GLOB, "test39. FP. Fixed by MSMProp1. Barrier.");
1995   printf("test39: negative\n");
1996   {
1997     ThreadPool pool(N_threads);
1998     pool.StartWorkers();
1999     for (int i = 0; i < N_threads; i++) {
2000       pool.Add(NewCallback(Worker));
2001     }
2002   } // all folks are joined here.
2003   printf("\tGLOB=%d\n", GLOB);
2004 }
2005 REGISTER_TEST(Run, 39);
2006 #endif // NO_BARRIER
2007 }  // namespace test39
2008 
2009 
2010 // test40: FP. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1
2011 namespace test40 {
2012 // Similar to test38 but with different order of events (due to sleep).
2013 
2014 // Putter1:            Putter2:           Getter1:       Getter2:
2015 //    MU1.Lock()          MU1.Lock()
2016 //    write(GLOB)         write(GLOB)
2017 //    MU1.Unlock()        MU1.Unlock()
2018 //    Q1.Put()            Q2.Put()
2019 //    Q1.Put()            Q2.Put()
2020 //                                        Q1.Get()       Q1.Get()
2021 //                                        Q2.Get()       Q2.Get()
2022 //                                        MU2.Lock()     MU2.Lock()
2023 //                                        write(GLOB)    write(GLOB)
2024 //                                        MU2.Unlock()   MU2.Unlock()
2025 //
2026 //    MU1.Lock()          MU1.Lock()
2027 //    MU2.Lock()          MU2.Lock()
2028 //    write(GLOB)         write(GLOB)
2029 //    MU2.Unlock()        MU2.Unlock()
2030 //    MU1.Unlock()        MU1.Unlock()
2031 
2032 
2033 ProducerConsumerQueue *Q1, *Q2;
2034 int     GLOB = 0;
2035 Mutex   MU, MU1, MU2;
2036 
Putter(ProducerConsumerQueue * q)2037 void Putter(ProducerConsumerQueue *q) {
2038   MU1.Lock();
2039   GLOB++;
2040   MU1.Unlock();
2041 
2042   q->Put(NULL);
2043   q->Put(NULL);
2044   usleep(100000);
2045 
2046   MU1.Lock();
2047   MU2.Lock();
2048   GLOB++;
2049   MU2.Unlock();
2050   MU1.Unlock();
2051 
2052 }
2053 
Putter1()2054 void Putter1() { Putter(Q1); }
Putter2()2055 void Putter2() { Putter(Q2); }
2056 
Getter()2057 void Getter() {
2058   Q1->Get();
2059   Q2->Get();
2060 
2061   MU2.Lock();
2062   GLOB++;
2063   MU2.Unlock();
2064 
2065   usleep(48000); //  TODO: remove this when FP in test32 is fixed.
2066 }
2067 
Run()2068 void Run() {
2069 //  ANNOTATE_EXPECT_RACE(&GLOB, "test40. FP. Fixed by MSMProp1. Complex Stuff.");
2070   printf("test40: negative\n");
2071   Q1 = new ProducerConsumerQueue(INT_MAX);
2072   Q2 = new ProducerConsumerQueue(INT_MAX);
2073   MyThreadArray t(Getter, Getter, Putter1, Putter2);
2074   t.Start();
2075   t.Join();
2076   printf("\tGLOB=%d\n", GLOB);
2077   delete Q1;
2078   delete Q2;
2079 }
2080 REGISTER_TEST(Run, 40);
2081 }  // namespace test40
2082 
2083 // test41: TN. Test for race that appears when loading a dynamic symbol. {{{1
2084 namespace test41 {
Worker()2085 void Worker() {
2086   ANNOTATE_NO_OP(NULL); // An empty function, loaded from dll.
2087 }
Run()2088 void Run() {
2089   printf("test41: negative\n");
2090   MyThreadArray t(Worker, Worker, Worker);
2091   t.Start();
2092   t.Join();
2093 }
2094 REGISTER_TEST2(Run, 41, FEATURE|NEEDS_ANNOTATIONS);
2095 }  // namespace test41
2096 
2097 
2098 // test42: TN. Using the same cond var several times. {{{1
2099 namespace test42 {
2100 int GLOB = 0;
2101 int COND = 0;
2102 int N_threads = 3;
2103 Mutex   MU;
2104 
Worker1()2105 void Worker1() {
2106   GLOB=1;
2107 
2108   MU.Lock();
2109   COND = 1;
2110   CV.Signal();
2111   MU.Unlock();
2112 
2113   MU.Lock();
2114   while (COND != 0)
2115     CV.Wait(&MU);
2116   ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2117   MU.Unlock();
2118 
2119   GLOB=3;
2120 
2121 }
2122 
Worker2()2123 void Worker2() {
2124 
2125   MU.Lock();
2126   while (COND != 1)
2127     CV.Wait(&MU);
2128   ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2129   MU.Unlock();
2130 
2131   GLOB=2;
2132 
2133   MU.Lock();
2134   COND = 0;
2135   CV.Signal();
2136   MU.Unlock();
2137 
2138 }
2139 
Run()2140 void Run() {
2141 //  ANNOTATE_EXPECT_RACE(&GLOB, "test42. TN. debugging.");
2142   printf("test42: negative\n");
2143   MyThreadArray t(Worker1, Worker2);
2144   t.Start();
2145   t.Join();
2146   printf("\tGLOB=%d\n", GLOB);
2147 }
2148 REGISTER_TEST2(Run, 42, FEATURE|NEEDS_ANNOTATIONS);
2149 }  // namespace test42
2150 
2151 
2152 
2153 // test43: TN. {{{1
2154 namespace test43 {
2155 //
2156 // Putter:            Getter:
2157 // 1. write
2158 // 2. Q.Put() --\     .
2159 // 3. read       \--> a. Q.Get()
2160 //                    b. read
2161 int     GLOB = 0;
2162 ProducerConsumerQueue Q(INT_MAX);
Putter()2163 void Putter() {
2164   GLOB = 1;
2165   Q.Put(NULL);
2166   CHECK(GLOB == 1);
2167 }
Getter()2168 void Getter() {
2169   Q.Get();
2170   usleep(100000);
2171   CHECK(GLOB == 1);
2172 }
Run()2173 void Run() {
2174   printf("test43: negative\n");
2175   MyThreadArray t(Putter, Getter);
2176   t.Start();
2177   t.Join();
2178   printf("\tGLOB=%d\n", GLOB);
2179 }
2180 REGISTER_TEST(Run, 43)
2181 }  // namespace test43
2182 
2183 
2184 // test44: FP. {{{1
2185 namespace test44 {
2186 //
2187 // Putter:            Getter:
2188 // 1. read
2189 // 2. Q.Put() --\     .
2190 // 3. MU.Lock()  \--> a. Q.Get()
2191 // 4. write
2192 // 5. MU.Unlock()
2193 //                    b. MU.Lock()
2194 //                    c. write
2195 //                    d. MU.Unlock();
2196 int     GLOB = 0;
2197 Mutex   MU;
2198 ProducerConsumerQueue Q(INT_MAX);
Putter()2199 void Putter() {
2200   CHECK(GLOB == 0);
2201   Q.Put(NULL);
2202   MU.Lock();
2203   GLOB = 1;
2204   MU.Unlock();
2205 }
Getter()2206 void Getter() {
2207   Q.Get();
2208   usleep(100000);
2209   MU.Lock();
2210   GLOB = 1;
2211   MU.Unlock();
2212 }
Run()2213 void Run() {
2214 //  ANNOTATE_EXPECT_RACE(&GLOB, "test44. FP. Fixed by MSMProp1.");
2215   printf("test44: negative\n");
2216   MyThreadArray t(Putter, Getter);
2217   t.Start();
2218   t.Join();
2219   printf("\tGLOB=%d\n", GLOB);
2220 }
2221 REGISTER_TEST(Run, 44)
2222 }  // namespace test44
2223 
2224 
2225 // test45: TN. {{{1
2226 namespace test45 {
2227 //
2228 // Putter:            Getter:
2229 // 1. read
2230 // 2. Q.Put() --\     .
2231 // 3. MU.Lock()  \--> a. Q.Get()
2232 // 4. write
2233 // 5. MU.Unlock()
2234 //                    b. MU.Lock()
2235 //                    c. read
2236 //                    d. MU.Unlock();
2237 int     GLOB = 0;
2238 Mutex   MU;
2239 ProducerConsumerQueue Q(INT_MAX);
Putter()2240 void Putter() {
2241   CHECK(GLOB == 0);
2242   Q.Put(NULL);
2243   MU.Lock();
2244   GLOB++;
2245   MU.Unlock();
2246 }
Getter()2247 void Getter() {
2248   Q.Get();
2249   usleep(100000);
2250   MU.Lock();
2251   CHECK(GLOB <= 1);
2252   MU.Unlock();
2253 }
Run()2254 void Run() {
2255   printf("test45: negative\n");
2256   MyThreadArray t(Putter, Getter);
2257   t.Start();
2258   t.Join();
2259   printf("\tGLOB=%d\n", GLOB);
2260 }
2261 REGISTER_TEST(Run, 45)
2262 }  // namespace test45
2263 
2264 
2265 // test46: FN. {{{1
2266 namespace test46 {
2267 //
2268 // First:                             Second:
2269 // 1. write
2270 // 2. MU.Lock()
2271 // 3. write
2272 // 4. MU.Unlock()                      (sleep)
2273 //                                    a. MU.Lock()
2274 //                                    b. write
2275 //                                    c. MU.Unlock();
2276 int     GLOB = 0;
2277 Mutex   MU;
First()2278 void First() {
2279   GLOB++;
2280   MU.Lock();
2281   GLOB++;
2282   MU.Unlock();
2283 }
Second()2284 void Second() {
2285   usleep(480000);
2286   MU.Lock();
2287   GLOB++;
2288   MU.Unlock();
2289 
2290   // just a print.
2291   // If we move it to Run()  we will get report in MSMHelgrind
2292   // due to its false positive (test32).
2293   MU.Lock();
2294   printf("\tGLOB=%d\n", GLOB);
2295   MU.Unlock();
2296 }
Run()2297 void Run() {
2298   ANNOTATE_TRACE_MEMORY(&GLOB);
2299   MyThreadArray t(First, Second);
2300   t.Start();
2301   t.Join();
2302 }
2303 REGISTER_TEST(Run, 46)
2304 }  // namespace test46
2305 
2306 
2307 // test47: TP. Not detected by pure happens-before detectors. {{{1
2308 namespace test47 {
2309 // A true race that can not be detected by a pure happens-before
2310 // race detector.
2311 //
2312 // First:                             Second:
2313 // 1. write
2314 // 2. MU.Lock()
2315 // 3. MU.Unlock()                      (sleep)
2316 //                                    a. MU.Lock()
2317 //                                    b. MU.Unlock();
2318 //                                    c. write
2319 int     GLOB = 0;
2320 Mutex   MU;
First()2321 void First() {
2322   GLOB=1;
2323   MU.Lock();
2324   MU.Unlock();
2325 }
Second()2326 void Second() {
2327   usleep(480000);
2328   MU.Lock();
2329   MU.Unlock();
2330   GLOB++;
2331 }
Run()2332 void Run() {
2333   FAST_MODE_INIT(&GLOB);
2334   if (!Tsan_PureHappensBefore())
2335     ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test47. TP. Not detected by pure HB.");
2336   printf("test47: positive\n");
2337   MyThreadArray t(First, Second);
2338   t.Start();
2339   t.Join();
2340   printf("\tGLOB=%d\n", GLOB);
2341 }
2342 REGISTER_TEST(Run, 47)
2343 }  // namespace test47
2344 
2345 
2346 // test48: FN. Simple race (single write vs multiple reads). {{{1
2347 namespace test48 {
2348 int     GLOB = 0;
2349 // same as test10 but with single writer and  multiple readers
2350 // A simple data race between single writer and  multiple readers.
2351 // Write happens before Reads (enforced by sleep(1)),
2352 
2353 //
2354 // Writer:                    Readers:
2355 // 1. write(GLOB)             a. sleep(long enough so that GLOB
2356 //                                is most likely initialized by Writer)
2357 //                            b. read(GLOB)
2358 //
2359 //
2360 // Eraser algorithm does not detect the race here,
2361 // see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html.
2362 //
Writer()2363 void Writer() {
2364   GLOB = 3;
2365 }
Reader()2366 void Reader() {
2367   usleep(100000);
2368   CHECK(GLOB != -777);
2369 }
2370 
Run()2371 void Run() {
2372   FAST_MODE_INIT(&GLOB);
2373   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test48. TP. FN in MSMHelgrind.");
2374   printf("test48: positive\n");
2375   MyThreadArray t(Writer, Reader,Reader,Reader);
2376   t.Start();
2377   t.Join();
2378   printf("\tGLOB=%d\n", GLOB);
2379 }
2380 REGISTER_TEST(Run, 48)
2381 }  // namespace test48
2382 
2383 
2384 // test49: FN. Simple race (single write vs multiple reads). {{{1
2385 namespace test49 {
2386 int     GLOB = 0;
2387 // same as test10 but with multiple read operations done by a single reader
2388 // A simple data race between writer and readers.
2389 // Write happens before Read (enforced by sleep(1)),
2390 //
2391 // Writer:                    Reader:
2392 // 1. write(GLOB)             a. sleep(long enough so that GLOB
2393 //                                is most likely initialized by Writer)
2394 //                            b. read(GLOB)
2395 //                            c. read(GLOB)
2396 //                            d. read(GLOB)
2397 //                            e. read(GLOB)
2398 //
2399 //
2400 // Eraser algorithm does not detect the race here,
2401 // see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html.
2402 //
Writer()2403 void Writer() {
2404   GLOB = 3;
2405 }
Reader()2406 void Reader() {
2407   usleep(100000);
2408   CHECK(GLOB != -777);
2409   CHECK(GLOB != -777);
2410   CHECK(GLOB != -777);
2411   CHECK(GLOB != -777);
2412 }
2413 
Run()2414 void Run() {
2415   FAST_MODE_INIT(&GLOB);
2416   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test49. TP. FN in MSMHelgrind.");
2417   printf("test49: positive\n");
2418   MyThreadArray t(Writer, Reader);
2419   t.Start();
2420   t.Join();
2421   printf("\tGLOB=%d\n", GLOB);
2422 }
2423 REGISTER_TEST(Run, 49);
2424 }  // namespace test49
2425 
2426 
2427 // test50: TP. Synchronization via CondVar. {{{1
2428 namespace test50 {
2429 int     GLOB = 0;
2430 Mutex   MU;
2431 // Two last write accesses to GLOB are not synchronized
2432 //
2433 // Waiter:                      Waker:
2434 // 1. COND = 0
2435 // 2. Start(Waker)
2436 // 3. MU.Lock()                 a. write(GLOB)
2437 //                              b. MU.Lock()
2438 //                              c. COND = 1
2439 //                         /--- d. CV.Signal()
2440 //  4. while(COND != 1)   /     e. MU.Unlock()
2441 //       CV.Wait(MU) <---/
2442 //  5. MU.Unlock()
2443 //  6. write(GLOB)              f. MU.Lock()
2444 //                              g. write(GLOB)
2445 //                              h. MU.Unlock()
2446 
2447 
Waker()2448 void Waker() {
2449   usleep(100000);  // Make sure the waiter blocks.
2450 
2451   GLOB = 1;
2452 
2453   MU.Lock();
2454   COND = 1;
2455   CV.Signal();
2456   MU.Unlock();
2457 
2458   usleep(100000);
2459   MU.Lock();
2460   GLOB = 3;
2461   MU.Unlock();
2462 }
2463 
Waiter()2464 void Waiter() {
2465   ThreadPool pool(1);
2466   pool.StartWorkers();
2467   COND = 0;
2468   pool.Add(NewCallback(Waker));
2469 
2470   MU.Lock();
2471   while(COND != 1)
2472     CV.Wait(&MU);
2473   ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2474   MU.Unlock();
2475 
2476   GLOB = 2;
2477 }
Run()2478 void Run() {
2479   FAST_MODE_INIT(&GLOB);
2480   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test50. TP.");
2481   printf("test50: positive\n");
2482   Waiter();
2483   printf("\tGLOB=%d\n", GLOB);
2484 }
2485 REGISTER_TEST2(Run, 50, FEATURE|NEEDS_ANNOTATIONS);
2486 }  // namespace test50
2487 
2488 
2489 // test51: TP. Synchronization via CondVar: problem with several signals. {{{1
2490 namespace test51 {
2491 int     GLOB = 0;
2492 int     COND = 0;
2493 Mutex   MU;
2494 
2495 
2496 // scheduler dependent results because of several signals
2497 // second signal will be lost
2498 //
2499 // Waiter:                      Waker:
2500 // 1. Start(Waker)
2501 // 2. MU.Lock()
2502 // 3. while(COND)
2503 //       CV.Wait(MU)<-\         .
2504 // 4. MU.Unlock()      \        .
2505 // 5. write(GLOB)       \       a. write(GLOB)
2506 //                       \      b. MU.Lock()
2507 //                        \     c. COND = 1
2508 //                         \--- d. CV.Signal()
2509 //                              e. MU.Unlock()
2510 //
2511 //                              f. write(GLOB)
2512 //
2513 //                              g. MU.Lock()
2514 //                              h. COND = 1
2515 //                    LOST<---- i. CV.Signal()
2516 //                              j. MU.Unlock()
2517 
Waker()2518 void Waker() {
2519 
2520   usleep(10000);  // Make sure the waiter blocks.
2521 
2522   GLOB = 1;
2523 
2524   MU.Lock();
2525   COND = 1;
2526   CV.Signal();
2527   MU.Unlock();
2528 
2529   usleep(10000);  // Make sure the waiter is signalled.
2530 
2531   GLOB = 2;
2532 
2533   MU.Lock();
2534   COND = 1;
2535   CV.Signal();   //Lost Signal
2536   MU.Unlock();
2537 }
2538 
Waiter()2539 void Waiter() {
2540 
2541   ThreadPool pool(1);
2542   pool.StartWorkers();
2543   pool.Add(NewCallback(Waker));
2544 
2545   MU.Lock();
2546   while(COND != 1)
2547     CV.Wait(&MU);
2548   MU.Unlock();
2549 
2550 
2551   GLOB = 3;
2552 }
Run()2553 void Run() {
2554   FAST_MODE_INIT(&GLOB);
2555   ANNOTATE_EXPECT_RACE(&GLOB, "test51. TP.");
2556   printf("test51: positive\n");
2557   Waiter();
2558   printf("\tGLOB=%d\n", GLOB);
2559 }
2560 REGISTER_TEST(Run, 51);
2561 }  // namespace test51
2562 
2563 
2564 // test52: TP. Synchronization via CondVar: problem with several signals. {{{1
2565 namespace test52 {
2566 int     GLOB = 0;
2567 int     COND = 0;
2568 Mutex   MU;
2569 
2570 // same as test51 but the first signal will be lost
2571 // scheduler dependent results because of several signals
2572 //
2573 // Waiter:                      Waker:
2574 // 1. Start(Waker)
2575 //                              a. write(GLOB)
2576 //                              b. MU.Lock()
2577 //                              c. COND = 1
2578 //                    LOST<---- d. CV.Signal()
2579 //                              e. MU.Unlock()
2580 //
2581 // 2. MU.Lock()
2582 // 3. while(COND)
2583 //       CV.Wait(MU)<-\         .
2584 // 4. MU.Unlock()      \        f. write(GLOB)
2585 // 5. write(GLOB)       \       .
2586 //                       \      g. MU.Lock()
2587 //                        \     h. COND = 1
2588 //                         \--- i. CV.Signal()
2589 //                              j. MU.Unlock()
2590 
Waker()2591 void Waker() {
2592 
2593   GLOB = 1;
2594 
2595   MU.Lock();
2596   COND = 1;
2597   CV.Signal();    //lost signal
2598   MU.Unlock();
2599 
2600   usleep(20000);  // Make sure the waiter blocks
2601 
2602   GLOB = 2;
2603 
2604   MU.Lock();
2605   COND = 1;
2606   CV.Signal();
2607   MU.Unlock();
2608 }
2609 
Waiter()2610 void Waiter() {
2611   ThreadPool pool(1);
2612   pool.StartWorkers();
2613   pool.Add(NewCallback(Waker));
2614 
2615   usleep(10000);  // Make sure the first signal will be lost
2616 
2617   MU.Lock();
2618   while(COND != 1)
2619     CV.Wait(&MU);
2620   MU.Unlock();
2621 
2622   GLOB = 3;
2623 }
Run()2624 void Run() {
2625   FAST_MODE_INIT(&GLOB);
2626   ANNOTATE_EXPECT_RACE(&GLOB, "test52. TP.");
2627   printf("test52: positive\n");
2628   Waiter();
2629   printf("\tGLOB=%d\n", GLOB);
2630 }
2631 REGISTER_TEST(Run, 52);
2632 }  // namespace test52
2633 
2634 
2635 // test53: FP. Synchronization via implicit semaphore. {{{1
2636 namespace test53 {
2637 // Correctly synchronized test, but the common lockset is empty.
2638 // The variable FLAG works as an implicit semaphore.
2639 // MSMHelgrind still does not complain since it does not maintain the lockset
2640 // at the exclusive state. But MSMProp1 does complain.
2641 // See also test54.
2642 //
2643 //
2644 // Initializer:                  Users
2645 // 1. MU1.Lock()
2646 // 2. write(GLOB)
2647 // 3. FLAG = true
2648 // 4. MU1.Unlock()
2649 //                               a. MU1.Lock()
2650 //                               b. f = FLAG;
2651 //                               c. MU1.Unlock()
2652 //                               d. if (!f) goto a.
2653 //                               e. MU2.Lock()
2654 //                               f. write(GLOB)
2655 //                               g. MU2.Unlock()
2656 //
2657 
2658 int     GLOB = 0;
2659 bool    FLAG = false;
2660 Mutex   MU1, MU2;
2661 
Initializer()2662 void Initializer() {
2663   MU1.Lock();
2664   GLOB = 1000;
2665   FLAG = true;
2666   MU1.Unlock();
2667   usleep(100000); // just in case
2668 }
2669 
User()2670 void User() {
2671   bool f = false;
2672   while(!f) {
2673     MU1.Lock();
2674     f = FLAG;
2675     MU1.Unlock();
2676     usleep(10000);
2677   }
2678   // at this point Initializer will not access GLOB again
2679   MU2.Lock();
2680   CHECK(GLOB >= 1000);
2681   GLOB++;
2682   MU2.Unlock();
2683 }
2684 
Run()2685 void Run() {
2686   FAST_MODE_INIT(&GLOB);
2687   if (!Tsan_PureHappensBefore())
2688     ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test53. FP. Implicit semaphore");
2689   printf("test53: FP. false positive, Implicit semaphore\n");
2690   MyThreadArray t(Initializer, User, User);
2691   t.Start();
2692   t.Join();
2693   printf("\tGLOB=%d\n", GLOB);
2694 }
2695 REGISTER_TEST(Run, 53)
2696 }  // namespace test53
2697 
2698 
2699 // test54: TN. Synchronization via implicit semaphore. Annotated {{{1
2700 namespace test54 {
2701 // Same as test53, but annotated.
2702 int     GLOB = 0;
2703 bool    FLAG = false;
2704 Mutex   MU1, MU2;
2705 
Initializer()2706 void Initializer() {
2707   MU1.Lock();
2708   GLOB = 1000;
2709   FLAG = true;
2710   ANNOTATE_CONDVAR_SIGNAL(&GLOB);
2711   MU1.Unlock();
2712   usleep(100000); // just in case
2713 }
2714 
User()2715 void User() {
2716   bool f = false;
2717   while(!f) {
2718     MU1.Lock();
2719     f = FLAG;
2720     MU1.Unlock();
2721     usleep(10000);
2722   }
2723   // at this point Initializer will not access GLOB again
2724   ANNOTATE_CONDVAR_WAIT(&GLOB);
2725   MU2.Lock();
2726   CHECK(GLOB >= 1000);
2727   GLOB++;
2728   MU2.Unlock();
2729 }
2730 
Run()2731 void Run() {
2732   printf("test54: negative\n");
2733   MyThreadArray t(Initializer, User, User);
2734   t.Start();
2735   t.Join();
2736   printf("\tGLOB=%d\n", GLOB);
2737 }
2738 REGISTER_TEST2(Run, 54, FEATURE|NEEDS_ANNOTATIONS)
2739 }  // namespace test54
2740 
2741 
2742 // test55: FP. Synchronization with TryLock. Not easy for race detectors {{{1
2743 namespace test55 {
2744 // "Correct" synchronization with TryLock and Lock.
2745 //
2746 // This scheme is actually very risky.
2747 // It is covered in detail in this video:
2748 // http://youtube.com/watch?v=mrvAqvtWYb4 (slide 36, near 50-th minute).
2749 int     GLOB = 0;
2750 Mutex   MU;
2751 
Worker_Lock()2752 void Worker_Lock() {
2753   GLOB = 1;
2754   MU.Lock();
2755 }
2756 
Worker_TryLock()2757 void Worker_TryLock() {
2758   while (true) {
2759     if (!MU.TryLock()) {
2760       MU.Unlock();
2761       break;
2762     }
2763     else
2764       MU.Unlock();
2765     usleep(100);
2766   }
2767   GLOB = 2;
2768 }
2769 
Run()2770 void Run() {
2771   printf("test55:\n");
2772   MyThreadArray t(Worker_Lock, Worker_TryLock);
2773   t.Start();
2774   t.Join();
2775   printf("\tGLOB=%d\n", GLOB);
2776 }
2777 REGISTER_TEST2(Run, 55, FEATURE|EXCLUDE_FROM_ALL);
2778 }  // namespace test55
2779 
2780 
2781 
2782 // test56: TP. Use of ANNOTATE_BENIGN_RACE. {{{1
2783 namespace test56 {
2784 // For whatever reason the user wants to treat
2785 // a race on GLOB as a benign race.
2786 int     GLOB = 0;
2787 int     GLOB2 = 0;
2788 
Worker()2789 void Worker() {
2790   GLOB++;
2791 }
2792 
Run()2793 void Run() {
2794   ANNOTATE_BENIGN_RACE(&GLOB, "test56. Use of ANNOTATE_BENIGN_RACE.");
2795   ANNOTATE_BENIGN_RACE(&GLOB2, "No race. The tool should be silent");
2796   printf("test56: positive\n");
2797   MyThreadArray t(Worker, Worker, Worker, Worker);
2798   t.Start();
2799   t.Join();
2800   printf("\tGLOB=%d\n", GLOB);
2801 }
2802 REGISTER_TEST2(Run, 56, FEATURE|NEEDS_ANNOTATIONS)
2803 }  // namespace test56
2804 
2805 
2806 // test57: TN: Correct use of atomics. {{{1
2807 namespace test57 {
2808 int     GLOB = 0;
Writer()2809 void Writer() {
2810   for (int i = 0; i < 10; i++) {
2811     AtomicIncrement(&GLOB, 1);
2812     usleep(1000);
2813   }
2814 }
Reader()2815 void Reader() {
2816   while (GLOB < 20) usleep(1000);
2817 }
Run()2818 void Run() {
2819   printf("test57: negative\n");
2820   MyThreadArray t(Writer, Writer, Reader, Reader);
2821   t.Start();
2822   t.Join();
2823   CHECK(GLOB == 20);
2824   printf("\tGLOB=%d\n", GLOB);
2825 }
2826 REGISTER_TEST(Run, 57)
2827 }  // namespace test57
2828 
2829 
2830 // test58: TN. User defined synchronization. {{{1
2831 namespace test58 {
2832 int     GLOB1 = 1;
2833 int     GLOB2 = 2;
2834 int     FLAG1 = 0;
2835 int     FLAG2 = 0;
2836 
2837 // Correctly synchronized test, but the common lockset is empty.
2838 // The variables FLAG1 and FLAG2 used for synchronization and as
2839 // temporary variables for swapping two global values.
2840 // Such kind of synchronization is rarely used (Excluded from all tests??).
2841 
Worker2()2842 void Worker2() {
2843   FLAG1=GLOB2;
2844 
2845   while(!FLAG2)
2846     ;
2847   GLOB2=FLAG2;
2848 }
2849 
Worker1()2850 void Worker1() {
2851   FLAG2=GLOB1;
2852 
2853   while(!FLAG1)
2854     ;
2855   GLOB1=FLAG1;
2856 }
2857 
Run()2858 void Run() {
2859   printf("test58:\n");
2860   MyThreadArray t(Worker1, Worker2);
2861   t.Start();
2862   t.Join();
2863   printf("\tGLOB1=%d\n", GLOB1);
2864   printf("\tGLOB2=%d\n", GLOB2);
2865 }
2866 REGISTER_TEST2(Run, 58, FEATURE|EXCLUDE_FROM_ALL)
2867 }  // namespace test58
2868 
2869 
2870 
2871 // test59: TN. User defined synchronization. Annotated {{{1
2872 namespace test59 {
2873 int     COND1 = 0;
2874 int     COND2 = 0;
2875 int     GLOB1 = 1;
2876 int     GLOB2 = 2;
2877 int     FLAG1 = 0;
2878 int     FLAG2 = 0;
2879 // same as test 58 but annotated
2880 
Worker2()2881 void Worker2() {
2882   FLAG1=GLOB2;
2883   ANNOTATE_CONDVAR_SIGNAL(&COND2);
2884   while(!FLAG2) usleep(1);
2885   ANNOTATE_CONDVAR_WAIT(&COND1);
2886   GLOB2=FLAG2;
2887 }
2888 
Worker1()2889 void Worker1() {
2890   FLAG2=GLOB1;
2891   ANNOTATE_CONDVAR_SIGNAL(&COND1);
2892   while(!FLAG1) usleep(1);
2893   ANNOTATE_CONDVAR_WAIT(&COND2);
2894   GLOB1=FLAG1;
2895 }
2896 
Run()2897 void Run() {
2898   printf("test59: negative\n");
2899   ANNOTATE_BENIGN_RACE(&FLAG1, "synchronization via 'safe' race");
2900   ANNOTATE_BENIGN_RACE(&FLAG2, "synchronization via 'safe' race");
2901   MyThreadArray t(Worker1, Worker2);
2902   t.Start();
2903   t.Join();
2904   printf("\tGLOB1=%d\n", GLOB1);
2905   printf("\tGLOB2=%d\n", GLOB2);
2906 }
2907 REGISTER_TEST2(Run, 59, FEATURE|NEEDS_ANNOTATIONS)
2908 }  // namespace test59
2909 
2910 
2911 // test60: TN. Correct synchronization using signal-wait {{{1
2912 namespace test60 {
2913 int     COND1 = 0;
2914 int     COND2 = 0;
2915 int     GLOB1 = 1;
2916 int     GLOB2 = 2;
2917 int     FLAG2 = 0;
2918 int     FLAG1 = 0;
2919 Mutex   MU;
2920 // same as test 59 but synchronized with signal-wait.
2921 
Worker2()2922 void Worker2() {
2923   FLAG1=GLOB2;
2924 
2925   MU.Lock();
2926   COND1 = 1;
2927   CV.Signal();
2928   MU.Unlock();
2929 
2930   MU.Lock();
2931   while(COND2 != 1)
2932     CV.Wait(&MU);
2933   ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2934   MU.Unlock();
2935 
2936   GLOB2=FLAG2;
2937 }
2938 
Worker1()2939 void Worker1() {
2940   FLAG2=GLOB1;
2941 
2942   MU.Lock();
2943   COND2 = 1;
2944   CV.Signal();
2945   MU.Unlock();
2946 
2947   MU.Lock();
2948   while(COND1 != 1)
2949     CV.Wait(&MU);
2950   ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2951   MU.Unlock();
2952 
2953   GLOB1=FLAG1;
2954 }
2955 
Run()2956 void Run() {
2957   printf("test60: negative\n");
2958   MyThreadArray t(Worker1, Worker2);
2959   t.Start();
2960   t.Join();
2961   printf("\tGLOB1=%d\n", GLOB1);
2962   printf("\tGLOB2=%d\n", GLOB2);
2963 }
2964 REGISTER_TEST2(Run, 60, FEATURE|NEEDS_ANNOTATIONS)
2965 }  // namespace test60
2966 
2967 
2968 // test61: TN. Synchronization via Mutex as in happens-before, annotated. {{{1
2969 namespace test61 {
2970 Mutex MU;
2971 int     GLOB = 0;
2972 int     *P1 = NULL, *P2 = NULL;
2973 
2974 // In this test Mutex lock/unlock operations introduce happens-before relation.
2975 // We annotate the code so that MU is treated as in pure happens-before detector.
2976 
2977 
Putter()2978 void Putter() {
2979   ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
2980   MU.Lock();
2981   if (P1 == NULL) {
2982     P1 = &GLOB;
2983     *P1 = 1;
2984   }
2985   MU.Unlock();
2986 }
2987 
Getter()2988 void Getter() {
2989   bool done  = false;
2990   while (!done) {
2991     MU.Lock();
2992     if (P1) {
2993       done = true;
2994       P2 = P1;
2995       P1 = NULL;
2996     }
2997     MU.Unlock();
2998   }
2999   *P2 = 2;
3000 }
3001 
3002 
Run()3003 void Run() {
3004   printf("test61: negative\n");
3005   MyThreadArray t(Putter, Getter);
3006   t.Start();
3007   t.Join();
3008   printf("\tGLOB=%d\n", GLOB);
3009 }
3010 REGISTER_TEST2(Run, 61, FEATURE|NEEDS_ANNOTATIONS)
3011 }  // namespace test61
3012 
3013 
3014 // test62: STAB. Create as many segments as possible. {{{1
3015 namespace test62 {
3016 // Helgrind 3.3.0 will fail as it has a hard limit of < 2^24 segments.
3017 // A better scheme is to implement garbage collection for segments.
3018 ProducerConsumerQueue Q(INT_MAX);
3019 const int N = 1 << 22;
3020 
Putter()3021 void Putter() {
3022   for (int i = 0; i < N; i++){
3023     if ((i % (N / 8)) == 0) {
3024       printf("i=%d\n", i);
3025     }
3026     Q.Put(NULL);
3027   }
3028 }
3029 
Getter()3030 void Getter() {
3031   for (int i = 0; i < N; i++)
3032     Q.Get();
3033 }
3034 
Run()3035 void Run() {
3036   printf("test62:\n");
3037   MyThreadArray t(Putter, Getter);
3038   t.Start();
3039   t.Join();
3040 }
3041 REGISTER_TEST2(Run, 62, STABILITY|EXCLUDE_FROM_ALL)
3042 }  // namespace test62
3043 
3044 
3045 // test63: STAB. Create as many segments as possible and do it fast. {{{1
3046 namespace test63 {
3047 // Helgrind 3.3.0 will fail as it has a hard limit of < 2^24 segments.
3048 // A better scheme is to implement garbage collection for segments.
3049 const int N = 1 << 24;
3050 int C = 0;
3051 
Putter()3052 void Putter() {
3053   for (int i = 0; i < N; i++){
3054     if ((i % (N / 8)) == 0) {
3055       printf("i=%d\n", i);
3056     }
3057     ANNOTATE_CONDVAR_SIGNAL(&C);
3058   }
3059 }
3060 
Getter()3061 void Getter() {
3062 }
3063 
Run()3064 void Run() {
3065   printf("test63:\n");
3066   MyThreadArray t(Putter, Getter);
3067   t.Start();
3068   t.Join();
3069 }
3070 REGISTER_TEST2(Run, 63, STABILITY|EXCLUDE_FROM_ALL)
3071 }  // namespace test63
3072 
3073 
3074 // test64: TP. T2 happens-before T3, but T1 is independent. Reads in T1/T2. {{{1
3075 namespace test64 {
3076 // True race between T1 and T3:
3077 //
3078 // T1:                   T2:                   T3:
3079 // 1. read(GLOB)         (sleep)
3080 //                       a. read(GLOB)
3081 //                       b. Q.Put() ----->    A. Q.Get()
3082 //                                            B. write(GLOB)
3083 //
3084 //
3085 
3086 int     GLOB = 0;
3087 ProducerConsumerQueue Q(INT_MAX);
3088 
T1()3089 void T1() {
3090   CHECK(GLOB == 0);
3091 }
3092 
T2()3093 void T2() {
3094   usleep(100000);
3095   CHECK(GLOB == 0);
3096   Q.Put(NULL);
3097 }
3098 
T3()3099 void T3() {
3100   Q.Get();
3101   GLOB = 1;
3102 }
3103 
3104 
Run()3105 void Run() {
3106   FAST_MODE_INIT(&GLOB);
3107   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test64: TP.");
3108   printf("test64: positive\n");
3109   MyThreadArray t(T1, T2, T3);
3110   t.Start();
3111   t.Join();
3112   printf("\tGLOB=%d\n", GLOB);
3113 }
3114 REGISTER_TEST(Run, 64)
3115 }  // namespace test64
3116 
3117 
3118 // test65: TP. T2 happens-before T3, but T1 is independent. Writes in T1/T2. {{{1
3119 namespace test65 {
3120 // Similar to test64.
3121 // True race between T1 and T3:
3122 //
3123 // T1:                   T2:                   T3:
3124 // 1. MU.Lock()
3125 // 2. write(GLOB)
3126 // 3. MU.Unlock()         (sleep)
3127 //                       a. MU.Lock()
3128 //                       b. write(GLOB)
3129 //                       c. MU.Unlock()
3130 //                       d. Q.Put() ----->    A. Q.Get()
3131 //                                            B. write(GLOB)
3132 //
3133 //
3134 
3135 int     GLOB = 0;
3136 Mutex   MU;
3137 ProducerConsumerQueue Q(INT_MAX);
3138 
T1()3139 void T1() {
3140   MU.Lock();
3141   GLOB++;
3142   MU.Unlock();
3143 }
3144 
T2()3145 void T2() {
3146   usleep(100000);
3147   MU.Lock();
3148   GLOB++;
3149   MU.Unlock();
3150   Q.Put(NULL);
3151 }
3152 
T3()3153 void T3() {
3154   Q.Get();
3155   GLOB = 1;
3156 }
3157 
3158 
Run()3159 void Run() {
3160   FAST_MODE_INIT(&GLOB);
3161   if (!Tsan_PureHappensBefore())
3162     ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test65. TP.");
3163   printf("test65: positive\n");
3164   MyThreadArray t(T1, T2, T3);
3165   t.Start();
3166   t.Join();
3167   printf("\tGLOB=%d\n", GLOB);
3168 }
3169 REGISTER_TEST(Run, 65)
3170 }  // namespace test65
3171 
3172 
3173 // test66: TN. Two separate pairs of signaller/waiter using the same CV. {{{1
3174 namespace test66 {
3175 int     GLOB1 = 0;
3176 int     GLOB2 = 0;
3177 int     C1 = 0;
3178 int     C2 = 0;
3179 Mutex   MU;
3180 
Signaller1()3181 void Signaller1() {
3182   GLOB1 = 1;
3183   MU.Lock();
3184   C1 = 1;
3185   CV.Signal();
3186   MU.Unlock();
3187 }
3188 
Signaller2()3189 void Signaller2() {
3190   GLOB2 = 1;
3191   usleep(100000);
3192   MU.Lock();
3193   C2 = 1;
3194   CV.Signal();
3195   MU.Unlock();
3196 }
3197 
Waiter1()3198 void Waiter1() {
3199   MU.Lock();
3200   while (C1 != 1) CV.Wait(&MU);
3201   ANNOTATE_CONDVAR_WAIT(&CV);
3202   MU.Unlock();
3203   GLOB1 = 2;
3204 }
3205 
Waiter2()3206 void Waiter2() {
3207   MU.Lock();
3208   while (C2 != 1) CV.Wait(&MU);
3209   ANNOTATE_CONDVAR_WAIT(&CV);
3210   MU.Unlock();
3211   GLOB2 = 2;
3212 }
3213 
Run()3214 void Run() {
3215   printf("test66: negative\n");
3216   MyThreadArray t(Signaller1, Signaller2, Waiter1, Waiter2);
3217   t.Start();
3218   t.Join();
3219   printf("\tGLOB=%d/%d\n", GLOB1, GLOB2);
3220 }
3221 REGISTER_TEST2(Run, 66, FEATURE|NEEDS_ANNOTATIONS)
3222 }  // namespace test66
3223 
3224 
3225 // test67: FN. Race between Signaller1 and Waiter2 {{{1
3226 namespace test67 {
3227 // Similar to test66, but there is a real race here.
3228 //
3229 // Here we create a happens-before arc between Signaller1 and Waiter2
3230 // even though there should be no such arc.
3231 // However, it's probably improssible (or just very hard) to avoid it.
3232 int     GLOB = 0;
3233 int     C1 = 0;
3234 int     C2 = 0;
3235 Mutex   MU;
3236 
Signaller1()3237 void Signaller1() {
3238   GLOB = 1;
3239   MU.Lock();
3240   C1 = 1;
3241   CV.Signal();
3242   MU.Unlock();
3243 }
3244 
Signaller2()3245 void Signaller2() {
3246   usleep(100000);
3247   MU.Lock();
3248   C2 = 1;
3249   CV.Signal();
3250   MU.Unlock();
3251 }
3252 
Waiter1()3253 void Waiter1() {
3254   MU.Lock();
3255   while (C1 != 1) CV.Wait(&MU);
3256   ANNOTATE_CONDVAR_WAIT(&CV);
3257   MU.Unlock();
3258 }
3259 
Waiter2()3260 void Waiter2() {
3261   MU.Lock();
3262   while (C2 != 1) CV.Wait(&MU);
3263   ANNOTATE_CONDVAR_WAIT(&CV);
3264   MU.Unlock();
3265   GLOB = 2;
3266 }
3267 
Run()3268 void Run() {
3269   FAST_MODE_INIT(&GLOB);
3270   ANNOTATE_EXPECT_RACE(&GLOB, "test67. FN. Race between Signaller1 and Waiter2");
3271   printf("test67: positive\n");
3272   MyThreadArray t(Signaller1, Signaller2, Waiter1, Waiter2);
3273   t.Start();
3274   t.Join();
3275   printf("\tGLOB=%d\n", GLOB);
3276 }
3277 REGISTER_TEST2(Run, 67, FEATURE|NEEDS_ANNOTATIONS|EXCLUDE_FROM_ALL)
3278 }  // namespace test67
3279 
3280 
3281 // test68: TP. Writes are protected by MU, reads are not. {{{1
3282 namespace test68 {
3283 // In this test, all writes to GLOB are protected by a mutex
3284 // but some reads go unprotected.
3285 // This is certainly a race, but in some cases such code could occur in
3286 // a correct program. For example, the unprotected reads may be used
3287 // for showing statistics and are not required to be precise.
3288 int     GLOB = 0;
3289 int     COND = 0;
3290 const int N_writers = 3;
3291 Mutex MU, MU1;
3292 
Writer()3293 void Writer() {
3294   for (int i = 0; i < 100; i++) {
3295     MU.Lock();
3296     GLOB++;
3297     MU.Unlock();
3298   }
3299 
3300   // we are done
3301   MU1.Lock();
3302   COND++;
3303   MU1.Unlock();
3304 }
3305 
Reader()3306 void Reader() {
3307   bool cont = true;
3308   while (cont) {
3309     CHECK(GLOB >= 0);
3310 
3311     // are we done?
3312     MU1.Lock();
3313     if (COND == N_writers)
3314       cont = false;
3315     MU1.Unlock();
3316     usleep(100);
3317   }
3318 }
3319 
Run()3320 void Run() {
3321   FAST_MODE_INIT(&GLOB);
3322   ANNOTATE_EXPECT_RACE(&GLOB, "TP. Writes are protected, reads are not.");
3323   printf("test68: positive\n");
3324   MyThreadArray t(Reader, Writer, Writer, Writer);
3325   t.Start();
3326   t.Join();
3327   printf("\tGLOB=%d\n", GLOB);
3328 }
3329 REGISTER_TEST(Run, 68)
3330 }  // namespace test68
3331 
3332 
3333 // test69:  {{{1
3334 namespace test69 {
3335 // This is the same as test68, but annotated.
3336 // We do not want to annotate GLOB as a benign race
3337 // because we want to allow racy reads only in certain places.
3338 //
3339 // TODO:
3340 int     GLOB = 0;
3341 int     COND = 0;
3342 const int N_writers = 3;
3343 int     FAKE_MU = 0;
3344 Mutex MU, MU1;
3345 
Writer()3346 void Writer() {
3347   for (int i = 0; i < 10; i++) {
3348     MU.Lock();
3349     GLOB++;
3350     MU.Unlock();
3351   }
3352 
3353   // we are done
3354   MU1.Lock();
3355   COND++;
3356   MU1.Unlock();
3357 }
3358 
Reader()3359 void Reader() {
3360   bool cont = true;
3361   while (cont) {
3362     ANNOTATE_IGNORE_READS_BEGIN();
3363     CHECK(GLOB >= 0);
3364     ANNOTATE_IGNORE_READS_END();
3365 
3366     // are we done?
3367     MU1.Lock();
3368     if (COND == N_writers)
3369       cont = false;
3370     MU1.Unlock();
3371     usleep(100);
3372   }
3373 }
3374 
Run()3375 void Run() {
3376   printf("test69: negative\n");
3377   MyThreadArray t(Reader, Writer, Writer, Writer);
3378   t.Start();
3379   t.Join();
3380   printf("\tGLOB=%d\n", GLOB);
3381 }
3382 REGISTER_TEST(Run, 69)
3383 }  // namespace test69
3384 
3385 // test70: STAB. Check that TRACE_MEMORY works. {{{1
3386 namespace test70 {
3387 int     GLOB = 0;
Run()3388 void Run() {
3389   printf("test70: negative\n");
3390   ANNOTATE_TRACE_MEMORY(&GLOB);
3391   GLOB = 1;
3392   printf("\tGLOB=%d\n", GLOB);
3393 }
3394 REGISTER_TEST(Run, 70)
3395 }  // namespace test70
3396 
3397 
3398 
3399 // test71: TN. strlen, index. {{{1
3400 namespace test71 {
3401 // This test is a reproducer for a benign race in strlen (as well as index, etc).
3402 // Some implementations of strlen may read up to 7 bytes past the end of the string
3403 // thus touching memory which may not belong to this string.
3404 // Such race is benign because the data read past the end of the string is not used.
3405 //
3406 // Here, we allocate a 8-byte aligned string str and initialize first 5 bytes.
3407 // Then one thread calls strlen(str) (as well as index & rindex)
3408 // and another thread initializes str[5]..str[7].
3409 //
3410 // This can be fixed in Helgrind by intercepting strlen and replacing it
3411 // with a simpler implementation.
3412 
3413 char    *str;
WorkerX()3414 void WorkerX() {
3415   usleep(100000);
3416   CHECK(strlen(str) == 4);
3417   CHECK(index(str, 'X') == str);
3418   CHECK(index(str, 'x') == str+1);
3419   CHECK(index(str, 'Y') == NULL);
3420   CHECK(rindex(str, 'X') == str+2);
3421   CHECK(rindex(str, 'x') == str+3);
3422   CHECK(rindex(str, 'Y') == NULL);
3423 }
WorkerY()3424 void WorkerY() {
3425   str[5] = 'Y';
3426   str[6] = 'Y';
3427   str[7] = '\0';
3428 }
3429 
Run()3430 void Run() {
3431   str = new char[8];
3432   str[0] = 'X';
3433   str[1] = 'x';
3434   str[2] = 'X';
3435   str[3] = 'x';
3436   str[4] = '\0';
3437 
3438   printf("test71: negative (strlen & index)\n");
3439   MyThread t1(WorkerY);
3440   MyThread t2(WorkerX);
3441   t1.Start();
3442   t2.Start();
3443   t1.Join();
3444   t2.Join();
3445   printf("\tstrX=%s; strY=%s\n", str, str+5);
3446 }
3447 REGISTER_TEST(Run, 71)
3448 }  // namespace test71
3449 
3450 
3451 // test72: STAB. Stress test for the number of segment sets (SSETs). {{{1
3452 namespace test72 {
3453 #ifndef NO_BARRIER
3454 // Variation of test33.
3455 // Instead of creating Nlog*N_iter threads,
3456 // we create Nlog threads and do N_iter barriers.
3457 int     GLOB = 0;
3458 const int N_iter = 30;
3459 const int Nlog  = 16;
3460 const int N     = 1 << Nlog;
3461 static int64_t ARR1[N];
3462 static int64_t ARR2[N];
3463 Barrier *barriers[N_iter];
3464 Mutex   MU;
3465 
Worker()3466 void Worker() {
3467   MU.Lock();
3468   int n = ++GLOB;
3469   MU.Unlock();
3470 
3471   n %= Nlog;
3472 
3473   long t0 = clock();
3474   long t __attribute__((unused)) = t0;
3475 
3476   for (int it = 0; it < N_iter; it++) {
3477     if(n == 0) {
3478       //printf("Iter: %d; %ld %ld\n", it, clock() - t, clock() - t0);
3479       t = clock();
3480     }
3481     // Iterate N_iter times, block on barrier after each iteration.
3482     // This way Helgrind will create new segments after each barrier.
3483 
3484     for (int x = 0; x < 2; x++) {
3485       // run the inner loop twice.
3486       // When a memory location is accessed second time it is likely
3487       // that the state (SVal) will be unchanged.
3488       // The memory machine may optimize this case.
3489       for (int i = 0; i < N; i++) {
3490         // ARR1[i] and ARR2[N-1-i] are accessed by threads from i-th subset
3491         if (i & (1 << n)) {
3492           CHECK(ARR1[i] == 0);
3493           CHECK(ARR2[N-1-i] == 0);
3494         }
3495       }
3496     }
3497     barriers[it]->Block();
3498   }
3499 }
3500 
3501 
Run()3502 void Run() {
3503   printf("test72:\n");
3504 
3505   std::vector<MyThread*> vec(Nlog);
3506 
3507   for (int i = 0; i < N_iter; i++)
3508     barriers[i] = new Barrier(Nlog);
3509 
3510   // Create and start Nlog threads
3511   for (int i = 0; i < Nlog; i++) {
3512     vec[i] = new MyThread(Worker);
3513     vec[i]->Start();
3514   }
3515 
3516   // Join all threads.
3517   for (int i = 0; i < Nlog; i++) {
3518     vec[i]->Join();
3519     delete vec[i];
3520   }
3521   for (int i = 0; i < N_iter; i++)
3522     delete barriers[i];
3523 
3524   /*printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n",
3525          GLOB, (int)ARR1[1], (int)ARR1[7], (int)ARR1[N-1]);*/
3526 }
3527 REGISTER_TEST2(Run, 72, STABILITY|PERFORMANCE|EXCLUDE_FROM_ALL);
3528 #endif // NO_BARRIER
3529 }  // namespace test72
3530 
3531 
3532 // test73: STAB. Stress test for the number of (SSETs), different access sizes. {{{1
3533 namespace test73 {
3534 #ifndef NO_BARRIER
3535 // Variation of test72.
3536 // We perform accesses of different sizes to the same location.
3537 int     GLOB = 0;
3538 const int N_iter = 2;
3539 const int Nlog  = 16;
3540 const int N     = 1 << Nlog;
3541 union uint64_union {
3542   uint64_t u64[1];
3543   uint32_t u32[2];
3544   uint16_t u16[4];
3545   uint8_t  u8 [8];
3546 };
3547 static uint64_union ARR1[N];
3548 union uint32_union {
3549   uint32_t u32[1];
3550   uint16_t u16[2];
3551   uint8_t  u8 [4];
3552 };
3553 static uint32_union ARR2[N];
3554 Barrier *barriers[N_iter];
3555 Mutex   MU;
3556 
Worker()3557 void Worker() {
3558   MU.Lock();
3559   int n = ++GLOB;
3560   MU.Unlock();
3561 
3562   n %= Nlog;
3563 
3564   for (int it = 0; it < N_iter; it++) {
3565     // Iterate N_iter times, block on barrier after each iteration.
3566     // This way Helgrind will create new segments after each barrier.
3567 
3568     for (int x = 0; x < 4; x++) {
3569       for (int i = 0; i < N; i++) {
3570         // ARR1[i] are accessed by threads from i-th subset
3571         if (i & (1 << n)) {
3572           for (int off = 0; off < (1 << x); off++) {
3573             switch(x) {
3574               case 0: CHECK(ARR1[i].u64[off] == 0); break;
3575               case 1: CHECK(ARR1[i].u32[off] == 0); break;
3576               case 2: CHECK(ARR1[i].u16[off] == 0); break;
3577               case 3: CHECK(ARR1[i].u8 [off] == 0); break;
3578             }
3579             switch(x) {
3580               case 1: CHECK(ARR2[i].u32[off] == 0); break;
3581               case 2: CHECK(ARR2[i].u16[off] == 0); break;
3582               case 3: CHECK(ARR2[i].u8 [off] == 0); break;
3583             }
3584           }
3585         }
3586       }
3587     }
3588     barriers[it]->Block();
3589   }
3590 }
3591 
3592 
3593 
Run()3594 void Run() {
3595   printf("test73:\n");
3596 
3597   std::vector<MyThread*> vec(Nlog);
3598 
3599   for (int i = 0; i < N_iter; i++)
3600     barriers[i] = new Barrier(Nlog);
3601 
3602   // Create and start Nlog threads
3603   for (int i = 0; i < Nlog; i++) {
3604     vec[i] = new MyThread(Worker);
3605     vec[i]->Start();
3606   }
3607 
3608   // Join all threads.
3609   for (int i = 0; i < Nlog; i++) {
3610     vec[i]->Join();
3611     delete vec[i];
3612   }
3613   for (int i = 0; i < N_iter; i++)
3614     delete barriers[i];
3615 
3616   /*printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n",
3617          GLOB, (int)ARR1[1], (int)ARR1[7], (int)ARR1[N-1]);*/
3618 }
3619 REGISTER_TEST2(Run, 73, STABILITY|PERFORMANCE|EXCLUDE_FROM_ALL);
3620 #endif // NO_BARRIER
3621 }  // namespace test73
3622 
3623 
3624 // test74: PERF. A lot of lock/unlock calls. {{{1
3625 namespace    test74 {
3626 const int N = 100000;
3627 Mutex   MU;
Run()3628 void Run() {
3629   printf("test74: perf\n");
3630   for (int i = 0; i < N; i++ ) {
3631     MU.Lock();
3632     MU.Unlock();
3633   }
3634 }
3635 REGISTER_TEST(Run, 74)
3636 }  // namespace test74
3637 
3638 
3639 // test75: TN. Test for sem_post, sem_wait, sem_trywait. {{{1
3640 namespace test75 {
3641 int     GLOB = 0;
3642 sem_t   sem[2];
3643 
Poster()3644 void Poster() {
3645   GLOB = 1;
3646   sem_post(&sem[0]);
3647   sem_post(&sem[1]);
3648 }
3649 
Waiter()3650 void Waiter() {
3651   sem_wait(&sem[0]);
3652   CHECK(GLOB==1);
3653 }
TryWaiter()3654 void TryWaiter() {
3655   usleep(500000);
3656   sem_trywait(&sem[1]);
3657   CHECK(GLOB==1);
3658 }
3659 
Run()3660 void Run() {
3661 #ifndef DRT_NO_SEM
3662   sem_init(&sem[0], 0, 0);
3663   sem_init(&sem[1], 0, 0);
3664 
3665   printf("test75: negative\n");
3666   {
3667     MyThreadArray t(Poster, Waiter);
3668     t.Start();
3669     t.Join();
3670   }
3671   GLOB = 2;
3672   {
3673     MyThreadArray t(Poster, TryWaiter);
3674     t.Start();
3675     t.Join();
3676   }
3677   printf("\tGLOB=%d\n", GLOB);
3678 
3679   sem_destroy(&sem[0]);
3680   sem_destroy(&sem[1]);
3681 #endif
3682 }
3683 REGISTER_TEST(Run, 75)
3684 }  // namespace test75
3685 
3686 // RefCountedClass {{{1
3687 struct RefCountedClass {
3688  public:
RefCountedClassRefCountedClass3689   RefCountedClass() {
3690     annotate_unref_ = false;
3691     ref_ = 0;
3692     data_ = 0;
3693   }
3694 
~RefCountedClassRefCountedClass3695   ~RefCountedClass() {
3696     CHECK(ref_ == 0);     // race may be reported here
3697     int data_val = data_; // and here
3698                           // if MU is not annotated
3699     data_ = 0;
3700     ref_ = -1;
3701     printf("\tRefCountedClass::data_ = %d\n", data_val);
3702   }
3703 
AccessDataRefCountedClass3704   void AccessData() {
3705     this->mu_.Lock();
3706     this->data_++;
3707     this->mu_.Unlock();
3708   }
3709 
RefRefCountedClass3710   void Ref() {
3711     MU.Lock();
3712     CHECK(ref_ >= 0);
3713     ref_++;
3714     MU.Unlock();
3715   }
3716 
UnrefRefCountedClass3717   void Unref() {
3718     MU.Lock();
3719     CHECK(ref_ > 0);
3720     ref_--;
3721     bool do_delete = ref_ == 0;
3722     if (annotate_unref_) {
3723       ANNOTATE_CONDVAR_SIGNAL(this);
3724     }
3725     MU.Unlock();
3726     if (do_delete) {
3727       if (annotate_unref_) {
3728         ANNOTATE_CONDVAR_WAIT(this);
3729       }
3730       delete this;
3731     }
3732   }
3733 
Annotate_MURefCountedClass3734   static void Annotate_MU() {
3735     ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
3736   }
AnnotateUnrefRefCountedClass3737   void AnnotateUnref() {
3738     annotate_unref_ = true;
3739   }
Annotate_RaceRefCountedClass3740   void Annotate_Race() {
3741     ANNOTATE_BENIGN_RACE(&this->data_, "needs annotation");
3742     ANNOTATE_BENIGN_RACE(&this->ref_, "needs annotation");
3743   }
3744  private:
3745   bool annotate_unref_;
3746 
3747   int data_;
3748   Mutex mu_; // protects data_
3749 
3750   int ref_;
3751   static Mutex MU; // protects ref_
3752 };
3753 
3754 Mutex RefCountedClass::MU;
3755 
3756 // test76: FP. Ref counting, no annotations. {{{1
3757 namespace test76 {
3758 #ifndef NO_BARRIER
3759 int     GLOB = 0;
3760 Barrier barrier(4);
3761 RefCountedClass *object = NULL;
Worker()3762 void Worker() {
3763   object->Ref();
3764   barrier.Block();
3765   object->AccessData();
3766   object->Unref();
3767 }
Run()3768 void Run() {
3769   printf("test76: false positive (ref counting)\n");
3770   object = new RefCountedClass;
3771   object->Annotate_Race();
3772   MyThreadArray t(Worker, Worker, Worker, Worker);
3773   t.Start();
3774   t.Join();
3775 }
3776 REGISTER_TEST2(Run, 76, FEATURE)
3777 #endif // NO_BARRIER
3778 }  // namespace test76
3779 
3780 
3781 
3782 // test77: TN. Ref counting, MU is annotated. {{{1
3783 namespace test77 {
3784 #ifndef NO_BARRIER
3785 // same as test76, but RefCountedClass::MU is annotated.
3786 int     GLOB = 0;
3787 Barrier barrier(4);
3788 RefCountedClass *object = NULL;
Worker()3789 void Worker() {
3790   object->Ref();
3791   barrier.Block();
3792   object->AccessData();
3793   object->Unref();
3794 }
Run()3795 void Run() {
3796   printf("test77: true negative (ref counting), mutex is annotated\n");
3797   RefCountedClass::Annotate_MU();
3798   object = new RefCountedClass;
3799   MyThreadArray t(Worker, Worker, Worker, Worker);
3800   t.Start();
3801   t.Join();
3802 }
3803 REGISTER_TEST(Run, 77)
3804 #endif // NO_BARRIER
3805 }  // namespace test77
3806 
3807 
3808 
3809 // test78: TN. Ref counting, Unref is annotated. {{{1
3810 namespace test78 {
3811 #ifndef NO_BARRIER
3812 // same as test76, but RefCountedClass::Unref is annotated.
3813 int     GLOB = 0;
3814 Barrier barrier(4);
3815 RefCountedClass *object = NULL;
Worker()3816 void Worker() {
3817   object->Ref();
3818   barrier.Block();
3819   object->AccessData();
3820   object->Unref();
3821 }
Run()3822 void Run() {
3823   printf("test78: true negative (ref counting), Unref is annotated\n");
3824   RefCountedClass::Annotate_MU();
3825   object = new RefCountedClass;
3826   MyThreadArray t(Worker, Worker, Worker, Worker);
3827   t.Start();
3828   t.Join();
3829 }
3830 REGISTER_TEST(Run, 78)
3831 #endif // NO_BARRIER
3832 }  // namespace test78
3833 
3834 
3835 
3836 // test79 TN. Swap. {{{1
3837 namespace test79 {
3838 #if 0
3839 typedef __gnu_cxx::hash_map<int, int> map_t;
3840 #else
3841 typedef std::map<int, int> map_t;
3842 #endif
3843 map_t   MAP;
3844 Mutex   MU;
3845 
3846 // Here we use swap to pass MAP between threads.
3847 // The synchronization is correct, but w/o ANNOTATE_MUTEX_IS_USED_AS_CONDVAR
3848 // Helgrind will complain.
3849 
Worker1()3850 void Worker1() {
3851   map_t tmp;
3852   MU.Lock();
3853   // We swap the new empty map 'tmp' with 'MAP'.
3854   MAP.swap(tmp);
3855   MU.Unlock();
3856   // tmp (which is the old version of MAP) is destroyed here.
3857 }
3858 
Worker2()3859 void Worker2() {
3860   MU.Lock();
3861   MAP[1]++;  // Just update MAP under MU.
3862   MU.Unlock();
3863 }
3864 
Worker3()3865 void Worker3() { Worker1(); }
Worker4()3866 void Worker4() { Worker2(); }
3867 
Run()3868 void Run() {
3869   ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
3870   printf("test79: negative\n");
3871   MyThreadArray t(Worker1, Worker2, Worker3, Worker4);
3872   t.Start();
3873   t.Join();
3874 }
3875 REGISTER_TEST(Run, 79)
3876 }  // namespace test79
3877 
3878 
3879 // AtomicRefCountedClass. {{{1
3880 // Same as RefCountedClass, but using atomic ops instead of mutex.
3881 struct AtomicRefCountedClass {
3882  public:
AtomicRefCountedClassAtomicRefCountedClass3883   AtomicRefCountedClass() {
3884     annotate_unref_ = false;
3885     ref_ = 0;
3886     data_ = 0;
3887   }
3888 
~AtomicRefCountedClassAtomicRefCountedClass3889   ~AtomicRefCountedClass() {
3890     CHECK(ref_ == 0);     // race may be reported here
3891     int data_val = data_; // and here
3892     data_ = 0;
3893     ref_ = -1;
3894     printf("\tRefCountedClass::data_ = %d\n", data_val);
3895   }
3896 
AccessDataAtomicRefCountedClass3897   void AccessData() {
3898     this->mu_.Lock();
3899     this->data_++;
3900     this->mu_.Unlock();
3901   }
3902 
RefAtomicRefCountedClass3903   void Ref() {
3904     AtomicIncrement(&ref_, 1);
3905   }
3906 
UnrefAtomicRefCountedClass3907   void Unref() {
3908     // DISCLAIMER: I am not sure I've implemented this correctly
3909     // (might require some memory barrier, etc).
3910     // But this implementation of reference counting is enough for
3911     // the purpose of Helgrind demonstration.
3912     AtomicIncrement(&ref_, -1);
3913     if (annotate_unref_) { ANNOTATE_CONDVAR_SIGNAL(this); }
3914     if (ref_ == 0) {
3915       if (annotate_unref_) { ANNOTATE_CONDVAR_WAIT(this); }
3916       delete this;
3917     }
3918   }
3919 
AnnotateUnrefAtomicRefCountedClass3920   void AnnotateUnref() {
3921     annotate_unref_ = true;
3922   }
Annotate_RaceAtomicRefCountedClass3923   void Annotate_Race() {
3924     ANNOTATE_BENIGN_RACE(&this->data_, "needs annotation");
3925   }
3926  private:
3927   bool annotate_unref_;
3928 
3929   Mutex mu_;
3930   int data_; // under mu_
3931 
3932   int ref_;  // used in atomic ops.
3933 };
3934 
3935 // test80: FP. Ref counting with atomics, no annotations. {{{1
3936 namespace test80 {
3937 #ifndef NO_BARRIER
3938 int     GLOB = 0;
3939 Barrier barrier(4);
3940 AtomicRefCountedClass *object = NULL;
Worker()3941 void Worker() {
3942   object->Ref();
3943   barrier.Block();
3944   object->AccessData();
3945   object->Unref(); // All the tricky stuff is here.
3946 }
Run()3947 void Run() {
3948   printf("test80: false positive (ref counting)\n");
3949   object = new AtomicRefCountedClass;
3950   object->Annotate_Race();
3951   MyThreadArray t(Worker, Worker, Worker, Worker);
3952   t.Start();
3953   t.Join();
3954 }
3955 REGISTER_TEST2(Run, 80, FEATURE|EXCLUDE_FROM_ALL)
3956 #endif // NO_BARRIER
3957 }  // namespace test80
3958 
3959 
3960 // test81: TN. Ref counting with atomics, Unref is annotated. {{{1
3961 namespace test81 {
3962 #ifndef NO_BARRIER
3963 // same as test80, but Unref is annotated.
3964 int     GLOB = 0;
3965 Barrier barrier(4);
3966 AtomicRefCountedClass *object = NULL;
Worker()3967 void Worker() {
3968   object->Ref();
3969   barrier.Block();
3970   object->AccessData();
3971   object->Unref(); // All the tricky stuff is here.
3972 }
Run()3973 void Run() {
3974   printf("test81: negative (annotated ref counting)\n");
3975   object = new AtomicRefCountedClass;
3976   object->AnnotateUnref();
3977   MyThreadArray t(Worker, Worker, Worker, Worker);
3978   t.Start();
3979   t.Join();
3980 }
3981 REGISTER_TEST2(Run, 81, FEATURE|EXCLUDE_FROM_ALL)
3982 #endif // NO_BARRIER
3983 }  // namespace test81
3984 
3985 
3986 // test82: Object published w/o synchronization. {{{1
3987 namespace test82 {
3988 
3989 // Writer creates a new object and makes the pointer visible to the Reader.
3990 // Reader waits until the object pointer is non-null and reads the object.
3991 //
3992 // On Core 2 Duo this test will sometimes (quite rarely) fail in
3993 // the CHECK below, at least if compiled with -O2.
3994 //
3995 // The sequence of events::
3996 // Thread1:                  Thread2:
3997 //   a. arr_[...] = ...
3998 //   b. foo[i]    = ...
3999 //                           A. ... = foo[i]; // non NULL
4000 //                           B. ... = arr_[...];
4001 //
4002 //  Since there is no proper synchronization, during the even (B)
4003 //  Thread2 may not see the result of the event (a).
4004 //  On x86 and x86_64 this happens due to compiler reordering instructions.
4005 //  On other arcitectures it may also happen due to cashe inconsistency.
4006 
4007 class FOO {
4008  public:
FOO()4009   FOO() {
4010     idx_ = rand() % 1024;
4011     arr_[idx_] = 77777;
4012   //   __asm__ __volatile__("" : : : "memory"); // this fixes!
4013   }
check(volatile FOO * foo)4014   static void check(volatile FOO *foo) {
4015     CHECK(foo->arr_[foo->idx_] == 77777);
4016   }
4017  private:
4018   int idx_;
4019   int arr_[1024];
4020 };
4021 
4022 const int N = 100000;
4023 static volatile FOO *foo[N];
4024 Mutex   MU;
4025 
Writer()4026 void Writer() {
4027   for (int i = 0; i < N; i++) {
4028     foo[i] = new FOO;
4029     usleep(100);
4030   }
4031 }
4032 
Reader()4033 void Reader() {
4034   for (int i = 0; i < N; i++) {
4035     while (!foo[i]) {
4036       MU.Lock();   // this is NOT a synchronization,
4037       MU.Unlock(); // it just helps foo[i] to become visible in Reader.
4038     }
4039     if ((i % 100) == 0) {
4040       printf("rd %d\n", i);
4041     }
4042     // At this point Reader() sees the new value of foo[i]
4043     // but in very rare cases will not see the new value of foo[i]->arr_.
4044     // Thus this CHECK will sometimes fail.
4045     FOO::check(foo[i]);
4046   }
4047 }
4048 
Run()4049 void Run() {
4050   printf("test82: positive\n");
4051   MyThreadArray t(Writer, Reader);
4052   t.Start();
4053   t.Join();
4054 }
4055 REGISTER_TEST2(Run, 82, FEATURE|EXCLUDE_FROM_ALL)
4056 }  // namespace test82
4057 
4058 
4059 // test83: Object published w/o synchronization (simple version){{{1
4060 namespace test83 {
4061 // A simplified version of test83 (example of a wrong code).
4062 // This test, though incorrect, will almost never fail.
4063 volatile static int *ptr = NULL;
4064 Mutex   MU;
4065 
Writer()4066 void Writer() {
4067   usleep(100);
4068   ptr = new int(777);
4069 }
4070 
Reader()4071 void Reader() {
4072   while(!ptr) {
4073     MU.Lock(); // Not a synchronization!
4074     MU.Unlock();
4075   }
4076   CHECK(*ptr == 777);
4077 }
4078 
Run()4079 void Run() {
4080 //  printf("test83: positive\n");
4081   MyThreadArray t(Writer, Reader);
4082   t.Start();
4083   t.Join();
4084 }
4085 REGISTER_TEST2(Run, 83, FEATURE|EXCLUDE_FROM_ALL)
4086 }  // namespace test83
4087 
4088 
4089 // test84: TP. True race (regression test for a bug related to atomics){{{1
4090 namespace test84 {
4091 // Helgrind should not create HB arcs for the bus lock even when
4092 // --pure-happens-before=yes is used.
4093 // Bug found in by Bart Van Assche, the test is taken from
4094 // valgrind file drd/tests/atomic_var.c.
4095 static int s_x = 0;
4096 /* s_dummy[] ensures that s_x and s_y are not in the same cache line. */
4097 static char s_dummy[512] = {0};
4098 static int s_y;
4099 
thread_func_1()4100 void thread_func_1()
4101 {
4102   s_y = 1;
4103   AtomicIncrement(&s_x, 1);
4104 }
4105 
thread_func_2()4106 void thread_func_2()
4107 {
4108   while (AtomicIncrement(&s_x, 0) == 0)
4109     ;
4110   printf("y = %d\n", s_y);
4111 }
4112 
4113 
Run()4114 void Run() {
4115   CHECK(s_dummy[0] == 0);  // Avoid compiler warning about 's_dummy unused'.
4116   printf("test84: positive\n");
4117   FAST_MODE_INIT(&s_y);
4118   ANNOTATE_EXPECT_RACE_FOR_TSAN(&s_y, "test84: TP. true race.");
4119   MyThreadArray t(thread_func_1, thread_func_2);
4120   t.Start();
4121   t.Join();
4122 }
4123 REGISTER_TEST(Run, 84)
4124 }  // namespace test84
4125 
4126 
4127 // test85: Test for RunningOnValgrind(). {{{1
4128 namespace  test85 {
4129 int     GLOB = 0;
Run()4130 void Run() {
4131   printf("test85: RunningOnValgrind() = %d\n", RunningOnValgrind());
4132 }
4133 REGISTER_TEST(Run, 85)
4134 }  // namespace test85
4135 
4136 
4137 // test86: Test for race inside DTOR: racey write to vptr. Benign. {{{1
4138 namespace test86 {
4139 // This test shows a racey access to vptr (the pointer to vtbl).
4140 // We have class A and class B derived from A.
4141 // Both classes have a virtual function f() and a virtual DTOR.
4142 // We create an object 'A *a = new B'
4143 // and pass this object from Thread1 to Thread2.
4144 // Thread2 calls a->f(). This call reads a->vtpr.
4145 // Thread1 deletes the object. B::~B waits untill the object can be destroyed
4146 // (flag_stopped == true) but at the very beginning of B::~B
4147 // a->vptr is written to.
4148 // So, we have a race on a->vptr.
4149 // On this particular test this race is benign, but test87 shows
4150 // how such race could harm.
4151 //
4152 //
4153 //
4154 // Threa1:                                            Thread2:
4155 // 1. A a* = new B;
4156 // 2. Q.Put(a); ------------\                         .
4157 //                           \-------------------->   a. a = Q.Get();
4158 //                                                    b. a->f();
4159 //                                       /---------   c. flag_stopped = true;
4160 // 3. delete a;                         /
4161 //    waits untill flag_stopped <------/
4162 //    inside the dtor
4163 //
4164 
4165 bool flag_stopped = false;
4166 Mutex mu;
4167 
4168 ProducerConsumerQueue Q(INT_MAX);  // Used to pass A* between threads.
4169 
4170 struct A {
Atest86::A4171   A()  { printf("A::A()\n"); }
~Atest86::A4172   virtual ~A() { printf("A::~A()\n"); }
ftest86::A4173   virtual void f() { }
4174 
4175   uintptr_t padding[15];
4176 } __attribute__ ((aligned (64)));
4177 
4178 struct B: A {
Btest86::B4179   B()  { printf("B::B()\n"); }
~Btest86::B4180   virtual ~B() {
4181     // The race is here.    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
4182     printf("B::~B()\n");
4183     // wait until flag_stopped is true.
4184     mu.LockWhen(Condition(&ArgIsTrue, &flag_stopped));
4185     mu.Unlock();
4186     printf("B::~B() done\n");
4187   }
ftest86::B4188   virtual void f() { }
4189 };
4190 
Waiter()4191 void Waiter() {
4192   A *a = new B;
4193   if (!Tsan_FastMode())
4194     ANNOTATE_EXPECT_RACE(a, "test86: expected race on a->vptr");
4195   printf("Waiter: B created\n");
4196   Q.Put(a);
4197   usleep(100000); // so that Worker calls a->f() first.
4198   printf("Waiter: deleting B\n");
4199   delete a;
4200   printf("Waiter: B deleted\n");
4201   usleep(100000);
4202   printf("Waiter: done\n");
4203 }
4204 
Worker()4205 void Worker() {
4206   A *a = reinterpret_cast<A*>(Q.Get());
4207   printf("Worker: got A\n");
4208   a->f();
4209 
4210   mu.Lock();
4211   flag_stopped = true;
4212   mu.Unlock();
4213   usleep(200000);
4214   printf("Worker: done\n");
4215 }
4216 
Run()4217 void Run() {
4218   printf("test86: positive, race inside DTOR\n");
4219   MyThreadArray t(Waiter, Worker);
4220   t.Start();
4221   t.Join();
4222 }
4223 REGISTER_TEST(Run, 86)
4224 }  // namespace test86
4225 
4226 
4227 // test87: Test for race inside DTOR: racey write to vptr. Harmful.{{{1
4228 namespace test87 {
4229 // A variation of test86 where the race is harmful.
4230 // Here we have class C derived from B.
4231 // We create an object 'A *a = new C' in Thread1 and pass it to Thread2.
4232 // Thread2 calls a->f().
4233 // Thread1 calls 'delete a'.
4234 // It first calls C::~C, then B::~B where it rewrites the vptr to point
4235 // to B::vtbl. This is a problem because Thread2 might not have called a->f()
4236 // and now it will call B::f instead of C::f.
4237 //
4238 bool flag_stopped = false;
4239 Mutex mu;
4240 
4241 ProducerConsumerQueue Q(INT_MAX);  // Used to pass A* between threads.
4242 
4243 struct A {
Atest87::A4244   A()  { printf("A::A()\n"); }
~Atest87::A4245   virtual ~A() { printf("A::~A()\n"); }
4246   virtual void f() = 0; // pure virtual.
4247 };
4248 
4249 struct B: A {
Btest87::B4250   B()  { printf("B::B()\n"); }
~Btest87::B4251   virtual ~B() {
4252     // The race is here.    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
4253     printf("B::~B()\n");
4254     // wait until flag_stopped is true.
4255     mu.LockWhen(Condition(&ArgIsTrue, &flag_stopped));
4256     mu.Unlock();
4257     printf("B::~B() done\n");
4258   }
4259   virtual void f() = 0; // pure virtual.
4260 };
4261 
4262 struct C: B {
Ctest87::C4263   C()  { printf("C::C()\n"); }
~Ctest87::C4264   virtual ~C() { printf("C::~C()\n"); }
ftest87::C4265   virtual void f() { }
4266 };
4267 
Waiter()4268 void Waiter() {
4269   A *a = new C;
4270   Q.Put(a);
4271   delete a;
4272 }
4273 
Worker()4274 void Worker() {
4275   A *a = reinterpret_cast<A*>(Q.Get());
4276   a->f();
4277 
4278   mu.Lock();
4279   flag_stopped = true;
4280   ANNOTATE_CONDVAR_SIGNAL(&mu);
4281   mu.Unlock();
4282 }
4283 
Run()4284 void Run() {
4285   printf("test87: positive, race inside DTOR\n");
4286   MyThreadArray t(Waiter, Worker);
4287   t.Start();
4288   t.Join();
4289 }
4290 REGISTER_TEST2(Run, 87, FEATURE|EXCLUDE_FROM_ALL)
4291 }  // namespace test87
4292 
4293 
4294 // test88: Test for ANNOTATE_IGNORE_WRITES_*{{{1
4295 namespace test88 {
4296 // a recey write annotated with ANNOTATE_IGNORE_WRITES_BEGIN/END.
4297 int     GLOB = 0;
Worker()4298 void Worker() {
4299   ANNOTATE_IGNORE_WRITES_BEGIN();
4300   GLOB = 1;
4301   ANNOTATE_IGNORE_WRITES_END();
4302 }
Run()4303 void Run() {
4304   printf("test88: negative, test for ANNOTATE_IGNORE_WRITES_*\n");
4305   MyThread t(Worker);
4306   t.Start();
4307   GLOB = 1;
4308   t.Join();
4309   printf("\tGLOB=%d\n", GLOB);
4310 }
4311 REGISTER_TEST(Run, 88)
4312 }  // namespace test88
4313 
4314 
4315 // test89: Test for debug info. {{{1
4316 namespace test89 {
4317 // Simlpe races with different objects (stack, heap globals; scalars, structs).
4318 // Also, if run with --trace-level=2 this test will show a sequence of
4319 // CTOR and DTOR calls.
4320 struct STRUCT {
4321   int a, b, c;
4322 };
4323 
4324 struct A {
4325   int a;
Atest89::A4326   A() {
4327     ANNOTATE_TRACE_MEMORY(&a);
4328     a = 1;
4329   }
~Atest89::A4330   virtual ~A() {
4331     a = 4;
4332   }
4333 };
4334 
4335 struct B : A {
Btest89::B4336   B()  { CHECK(a == 1); }
~Btest89::B4337   virtual ~B() { CHECK(a == 3); }
4338 };
4339 struct C : B {
Ctest89::C4340   C()  { a = 2; }
~Ctest89::C4341   virtual ~C() { a = 3; }
4342 };
4343 
4344 int            GLOBAL = 0;
4345 int           *STACK  = 0;
4346 STRUCT         GLOB_STRUCT;
4347 STRUCT        *STACK_STRUCT;
4348 STRUCT        *HEAP_STRUCT;
4349 
Worker()4350 void Worker() {
4351   GLOBAL = 1;
4352   *STACK = 1;
4353   GLOB_STRUCT.b   = 1;
4354   STACK_STRUCT->b = 1;
4355   HEAP_STRUCT->b  = 1;
4356 }
4357 
Run()4358 void Run() {
4359   int stack_var = 0;
4360   STACK = &stack_var;
4361 
4362   STRUCT stack_struct;
4363   STACK_STRUCT = &stack_struct;
4364 
4365   HEAP_STRUCT = new STRUCT;
4366 
4367   printf("test89: negative\n");
4368   MyThreadArray t(Worker, Worker);
4369   t.Start();
4370   t.Join();
4371 
4372   delete HEAP_STRUCT;
4373 
4374   A *a = new C;
4375   printf("Using 'a->a':  %d\n", a->a);
4376   delete a;
4377 }
4378 REGISTER_TEST2(Run, 89, FEATURE|EXCLUDE_FROM_ALL)
4379 }  // namespace test89
4380 
4381 
4382 // test90: FP. Test for a safely-published pointer (read-only). {{{1
4383 namespace test90 {
4384 // The Publisher creates an object and safely publishes it under a mutex.
4385 // Readers access the object read-only.
4386 // See also test91.
4387 //
4388 // Without annotations Helgrind will issue a false positive in Reader().
4389 //
4390 // Choices for annotations:
4391 //   -- ANNOTATE_CONDVAR_SIGNAL/ANNOTATE_CONDVAR_WAIT
4392 //   -- ANNOTATE_MUTEX_IS_USED_AS_CONDVAR
4393 //   -- ANNOTATE_PUBLISH_MEMORY_RANGE.
4394 
4395 int     *GLOB = 0;
4396 Mutex   MU;
4397 
Publisher()4398 void Publisher() {
4399   MU.Lock();
4400   GLOB = (int*)memalign(64, sizeof(int));
4401   *GLOB = 777;
4402   if (!Tsan_PureHappensBefore() && !Tsan_FastMode())
4403     ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test90. FP. This is a false positve");
4404   MU.Unlock();
4405   usleep(200000);
4406 }
4407 
Reader()4408 void Reader() {
4409   usleep(10000);
4410   while (true) {
4411     MU.Lock();
4412     int *p = GLOB;
4413     MU.Unlock();
4414     if (p) {
4415       CHECK(*p == 777);  // Race is reported here.
4416       break;
4417     }
4418   }
4419 }
4420 
Run()4421 void Run() {
4422   printf("test90: false positive (safely published pointer).\n");
4423   MyThreadArray t(Publisher, Reader, Reader, Reader);
4424   t.Start();
4425   t.Join();
4426   printf("\t*GLOB=%d\n", *GLOB);
4427   free(GLOB);
4428 }
4429 REGISTER_TEST(Run, 90)
4430 }  // namespace test90
4431 
4432 
4433 // test91: FP. Test for a safely-published pointer (read-write). {{{1
4434 namespace test91 {
4435 // Similar to test90.
4436 // The Publisher creates an object and safely publishes it under a mutex MU1.
4437 // Accessors get the object under MU1 and access it (read/write) under MU2.
4438 //
4439 // Without annotations Helgrind will issue a false positive in Accessor().
4440 //
4441 
4442 int     *GLOB = 0;
4443 Mutex   MU, MU1, MU2;
4444 
Publisher()4445 void Publisher() {
4446   MU1.Lock();
4447   GLOB = (int*)memalign(64, sizeof(int));
4448   *GLOB = 777;
4449   if (!Tsan_PureHappensBefore() && !Tsan_FastMode())
4450     ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test91. FP. This is a false positve");
4451   MU1.Unlock();
4452 }
4453 
Accessor()4454 void Accessor() {
4455   usleep(10000);
4456   while (true) {
4457     MU1.Lock();
4458     int *p = GLOB;
4459     MU1.Unlock();
4460     if (p) {
4461       MU2.Lock();
4462       (*p)++;  // Race is reported here.
4463       CHECK(*p >  777);
4464       MU2.Unlock();
4465       break;
4466     }
4467   }
4468 }
4469 
Run()4470 void Run() {
4471   printf("test91: false positive (safely published pointer, read/write).\n");
4472   MyThreadArray t(Publisher, Accessor, Accessor, Accessor);
4473   t.Start();
4474   t.Join();
4475   printf("\t*GLOB=%d\n", *GLOB);
4476   free(GLOB);
4477 }
4478 REGISTER_TEST(Run, 91)
4479 }  // namespace test91
4480 
4481 
4482 // test92: TN. Test for a safely-published pointer (read-write), annotated. {{{1
4483 namespace test92 {
4484 // Similar to test91, but annotated with ANNOTATE_PUBLISH_MEMORY_RANGE.
4485 //
4486 //
4487 // Publisher:                                       Accessors:
4488 //
4489 // 1. MU1.Lock()
4490 // 2. Create GLOB.
4491 // 3. ANNOTATE_PUBLISH_...(GLOB) -------\            .
4492 // 4. MU1.Unlock()                       \           .
4493 //                                        \          a. MU1.Lock()
4494 //                                         \         b. Get GLOB
4495 //                                          \        c. MU1.Unlock()
4496 //                                           \-->    d. Access GLOB
4497 //
4498 //  A happens-before arc is created between ANNOTATE_PUBLISH_MEMORY_RANGE and
4499 //  accesses to GLOB.
4500 
4501 struct ObjType {
4502   int arr[10];
4503 };
4504 
4505 ObjType *GLOB = 0;
4506 Mutex   MU, MU1, MU2;
4507 
Publisher()4508 void Publisher() {
4509   MU1.Lock();
4510   GLOB = new ObjType;
4511   for (int i = 0; i < 10; i++) {
4512     GLOB->arr[i] = 777;
4513   }
4514   // This annotation should go right before the object is published.
4515   ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB, sizeof(*GLOB));
4516   MU1.Unlock();
4517 }
4518 
Accessor(int index)4519 void Accessor(int index) {
4520   while (true) {
4521     MU1.Lock();
4522     ObjType *p = GLOB;
4523     MU1.Unlock();
4524     if (p) {
4525       MU2.Lock();
4526       p->arr[index]++;  // W/o the annotations the race will be reported here.
4527       CHECK(p->arr[index] ==  778);
4528       MU2.Unlock();
4529       break;
4530     }
4531   }
4532 }
4533 
Accessor0()4534 void Accessor0() { Accessor(0); }
Accessor5()4535 void Accessor5() { Accessor(5); }
Accessor9()4536 void Accessor9() { Accessor(9); }
4537 
Run()4538 void Run() {
4539   printf("test92: safely published pointer, read/write, annotated.\n");
4540   MyThreadArray t(Publisher, Accessor0, Accessor5, Accessor9);
4541   t.Start();
4542   t.Join();
4543   printf("\t*GLOB=%d\n", GLOB->arr[0]);
4544 }
4545 REGISTER_TEST(Run, 92)
4546 }  // namespace test92
4547 
4548 
4549 // test93: TP. Test for incorrect usage of ANNOTATE_PUBLISH_MEMORY_RANGE. {{{1
4550 namespace test93 {
4551 int     GLOB = 0;
4552 
Reader()4553 void Reader() {
4554   CHECK(GLOB == 0);
4555 }
4556 
Publisher()4557 void Publisher() {
4558   usleep(10000);
4559   // Incorrect, used after the memory has been accessed in another thread.
4560   ANNOTATE_PUBLISH_MEMORY_RANGE(&GLOB, sizeof(GLOB));
4561 }
4562 
Run()4563 void Run() {
4564   printf("test93: positive, misuse of ANNOTATE_PUBLISH_MEMORY_RANGE\n");
4565   MyThreadArray t(Reader, Publisher);
4566   t.Start();
4567   t.Join();
4568   printf("\tGLOB=%d\n", GLOB);
4569 }
4570 REGISTER_TEST2(Run, 93, FEATURE|EXCLUDE_FROM_ALL)
4571 }  // namespace test93
4572 
4573 
4574 // test94: TP. Check do_cv_signal/fake segment logic {{{1
4575 namespace test94 {
4576 int     GLOB;
4577 
4578 int COND  = 0;
4579 int COND2 = 0;
4580 Mutex MU, MU2;
4581 CondVar CV, CV2;
4582 
Thr1()4583 void Thr1() {
4584   usleep(10000);  // Make sure the waiter blocks.
4585 
4586   GLOB = 1; // WRITE
4587 
4588   MU.Lock();
4589   COND = 1;
4590   CV.Signal();
4591   MU.Unlock();
4592 }
Thr2()4593 void Thr2() {
4594   usleep(1000*1000); // Make sure CV2.Signal() "happens after" CV.Signal()
4595   usleep(10000);  // Make sure the waiter blocks.
4596 
4597   MU2.Lock();
4598   COND2 = 1;
4599   CV2.Signal();
4600   MU2.Unlock();
4601 }
Thr3()4602 void Thr3() {
4603   MU.Lock();
4604   while(COND != 1)
4605     CV.Wait(&MU);
4606   MU.Unlock();
4607 }
Thr4()4608 void Thr4() {
4609   MU2.Lock();
4610   while(COND2 != 1)
4611     CV2.Wait(&MU2);
4612   MU2.Unlock();
4613   GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait !
4614 }
Run()4615 void Run() {
4616   FAST_MODE_INIT(&GLOB);
4617   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test94: TP.");
4618   printf("test94: TP. Check do_cv_signal/fake segment logic\n");
4619   MyThreadArray mta(Thr1, Thr2, Thr3, Thr4);
4620   mta.Start();
4621   mta.Join();
4622   printf("\tGLOB=%d\n", GLOB);
4623 }
4624 REGISTER_TEST(Run, 94);
4625 }  // namespace test94
4626 
4627 // test95: TP. Check do_cv_signal/fake segment logic {{{1
4628 namespace test95 {
4629 int     GLOB = 0;
4630 
4631 int COND  = 0;
4632 int COND2 = 0;
4633 Mutex MU, MU2;
4634 CondVar CV, CV2;
4635 
Thr1()4636 void Thr1() {
4637   usleep(1000*1000); // Make sure CV2.Signal() "happens before" CV.Signal()
4638   usleep(10000);  // Make sure the waiter blocks.
4639 
4640   GLOB = 1; // WRITE
4641 
4642   MU.Lock();
4643   COND = 1;
4644   CV.Signal();
4645   MU.Unlock();
4646 }
Thr2()4647 void Thr2() {
4648   usleep(10000);  // Make sure the waiter blocks.
4649 
4650   MU2.Lock();
4651   COND2 = 1;
4652   CV2.Signal();
4653   MU2.Unlock();
4654 }
Thr3()4655 void Thr3() {
4656   MU.Lock();
4657   while(COND != 1)
4658     CV.Wait(&MU);
4659   MU.Unlock();
4660 }
Thr4()4661 void Thr4() {
4662   MU2.Lock();
4663   while(COND2 != 1)
4664     CV2.Wait(&MU2);
4665   MU2.Unlock();
4666   GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait !
4667 }
Run()4668 void Run() {
4669   FAST_MODE_INIT(&GLOB);
4670   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test95: TP.");
4671   printf("test95: TP. Check do_cv_signal/fake segment logic\n");
4672   MyThreadArray mta(Thr1, Thr2, Thr3, Thr4);
4673   mta.Start();
4674   mta.Join();
4675   printf("\tGLOB=%d\n", GLOB);
4676 }
4677 REGISTER_TEST(Run, 95);
4678 }  // namespace test95
4679 
4680 // test96: TN. tricky LockSet behaviour {{{1
4681 // 3 threads access the same memory with three different
4682 // locksets: {A, B}, {B, C}, {C, A}.
4683 // These locksets have empty intersection
4684 namespace test96 {
4685 int     GLOB = 0;
4686 
4687 Mutex A, B, C;
4688 
Thread1()4689 void Thread1() {
4690   MutexLock a(&A);
4691   MutexLock b(&B);
4692   GLOB++;
4693 }
4694 
Thread2()4695 void Thread2() {
4696   MutexLock b(&B);
4697   MutexLock c(&C);
4698   GLOB++;
4699 }
4700 
Thread3()4701 void Thread3() {
4702   MutexLock a(&A);
4703   MutexLock c(&C);
4704   GLOB++;
4705 }
4706 
Run()4707 void Run() {
4708   printf("test96: FP. tricky LockSet behaviour\n");
4709   ANNOTATE_TRACE_MEMORY(&GLOB);
4710   MyThreadArray mta(Thread1, Thread2, Thread3);
4711   mta.Start();
4712   mta.Join();
4713   CHECK(GLOB == 3);
4714   printf("\tGLOB=%d\n", GLOB);
4715 }
4716 REGISTER_TEST(Run, 96);
4717 }  // namespace test96
4718 
4719 // test97: This test shows false negative with --fast-mode=yes {{{1
4720 namespace test97 {
4721 const int HG_CACHELINE_SIZE = 64;
4722 
4723 Mutex MU;
4724 
4725 const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4726 int array[ARRAY_SIZE];
4727 int * GLOB = &array[ARRAY_SIZE/2];
4728 /*
4729   We use sizeof(array) == 4 * HG_CACHELINE_SIZE to be sure that GLOB points
4730   to a memory inside a CacheLineZ which is inside array's memory range
4731  */
4732 
Reader()4733 void Reader() {
4734   usleep(500000);
4735   CHECK(777 == *GLOB);
4736 }
4737 
Run()4738 void Run() {
4739   MyThreadArray t(Reader);
4740   if (!Tsan_FastMode())
4741     ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test97: TP. FN with --fast-mode=yes");
4742   printf("test97: This test shows false negative with --fast-mode=yes\n");
4743 
4744   t.Start();
4745   *GLOB = 777;
4746   t.Join();
4747 }
4748 
4749 REGISTER_TEST2(Run, 97, FEATURE)
4750 }  // namespace test97
4751 
4752 // test98: Synchronization via read/write (or send/recv). {{{1
4753 namespace test98 {
4754 // The synchronization here is done by a pair of read/write calls
4755 // that create a happens-before arc. Same may be done with send/recv.
4756 // Such synchronization is quite unusual in real programs
4757 // (why would one synchronizae via a file or socket?), but
4758 // quite possible in unittests where one threads runs for producer
4759 // and one for consumer.
4760 //
4761 // A race detector has to create a happens-before arcs for
4762 // {read,send}->{write,recv} even if the file descriptors are different.
4763 //
4764 int     GLOB = 0;
4765 int fd_out = -1;
4766 int fd_in  = -1;
4767 
Writer()4768 void Writer() {
4769   usleep(1000);
4770   GLOB = 1;
4771   const char *str = "Hey there!\n";
4772   IGNORE_RETURN_VALUE(write(fd_out, str, strlen(str) + 1));
4773 }
4774 
Reader()4775 void Reader() {
4776   char buff[100];
4777   while (read(fd_in, buff, 100) == 0)
4778     sleep(1);
4779   printf("read: %s\n", buff);
4780   GLOB = 2;
4781 }
4782 
Run()4783 void Run() {
4784   printf("test98: negative, synchronization via I/O\n");
4785   char in_name[100];
4786   char out_name[100];
4787   // we open two files, on for reading and one for writing,
4788   // but the files are actually the same (symlinked).
4789   sprintf(out_name, "/tmp/racecheck_unittest_out.%d", getpid());
4790   fd_out = creat(out_name, O_WRONLY | S_IRWXU);
4791 #ifdef VGO_darwin
4792   // symlink() is not supported on Darwin. Copy the output file name.
4793   strcpy(in_name, out_name);
4794 #else
4795   sprintf(in_name,  "/tmp/racecheck_unittest_in.%d", getpid());
4796   IGNORE_RETURN_VALUE(symlink(out_name, in_name));
4797 #endif
4798   fd_in  = open(in_name, 0, O_RDONLY);
4799   CHECK(fd_out >= 0);
4800   CHECK(fd_in  >= 0);
4801   MyThreadArray t(Writer, Reader);
4802   t.Start();
4803   t.Join();
4804   printf("\tGLOB=%d\n", GLOB);
4805   // cleanup
4806   close(fd_in);
4807   close(fd_out);
4808   unlink(in_name);
4809   unlink(out_name);
4810 }
4811 REGISTER_TEST(Run, 98)
4812 }  // namespace test98
4813 
4814 
4815 // test99: TP. Unit test for a bug in LockWhen*. {{{1
4816 namespace test99 {
4817 
4818 
4819 bool GLOB = false;
4820 Mutex mu;
4821 
Thread1()4822 static void Thread1() {
4823   for (int i = 0; i < 100; i++) {
4824     mu.LockWhenWithTimeout(Condition(&ArgIsTrue, &GLOB), 5);
4825     GLOB = false;
4826     mu.Unlock();
4827     usleep(10000);
4828   }
4829 }
4830 
Thread2()4831 static void Thread2() {
4832   for (int i = 0; i < 100; i++) {
4833     mu.Lock();
4834     mu.Unlock();
4835     usleep(10000);
4836   }
4837 }
4838 
Run()4839 void Run() {
4840   printf("test99: regression test for LockWhen*\n");
4841   MyThreadArray t(Thread1, Thread2);
4842   t.Start();
4843   t.Join();
4844 }
4845 REGISTER_TEST(Run, 99);
4846 }  // namespace test99
4847 
4848 
4849 // test100: Test for initialization bit. {{{1
4850 namespace test100 {
4851 int     G1 = 0;
4852 int     G2 = 0;
4853 int     G3 = 0;
4854 int     G4 = 0;
4855 
Creator()4856 void Creator() {
4857   G1 = 1; CHECK(G1);
4858   G2 = 1;
4859   G3 = 1; CHECK(G3);
4860   G4 = 1;
4861 }
4862 
Worker1()4863 void Worker1() {
4864   usleep(100000);
4865   CHECK(G1);
4866   CHECK(G2);
4867   G3 = 3;
4868   G4 = 3;
4869 }
4870 
Worker2()4871 void Worker2() {
4872 
4873 }
4874 
4875 
Run()4876 void Run() {
4877   printf("test100: test for initialization bit. \n");
4878   MyThreadArray t(Creator, Worker1, Worker2);
4879   ANNOTATE_TRACE_MEMORY(&G1);
4880   ANNOTATE_TRACE_MEMORY(&G2);
4881   ANNOTATE_TRACE_MEMORY(&G3);
4882   ANNOTATE_TRACE_MEMORY(&G4);
4883   t.Start();
4884   t.Join();
4885 }
4886 REGISTER_TEST2(Run, 100, FEATURE|EXCLUDE_FROM_ALL)
4887 }  // namespace test100
4888 
4889 
4890 // test101: TN. Two signals and two waits. {{{1
4891 namespace test101 {
4892 Mutex MU;
4893 CondVar CV;
4894 int     GLOB = 0;
4895 
4896 int C1 = 0, C2 = 0;
4897 
Signaller()4898 void Signaller() {
4899   usleep(100000);
4900   MU.Lock();
4901   C1 = 1;
4902   CV.Signal();
4903   printf("signal\n");
4904   MU.Unlock();
4905 
4906   GLOB = 1;
4907 
4908   usleep(500000);
4909   MU.Lock();
4910   C2 = 1;
4911   CV.Signal();
4912   printf("signal\n");
4913   MU.Unlock();
4914 }
4915 
Waiter()4916 void Waiter() {
4917   MU.Lock();
4918   while(!C1)
4919     CV.Wait(&MU);
4920   printf("wait\n");
4921   MU.Unlock();
4922 
4923   MU.Lock();
4924   while(!C2)
4925     CV.Wait(&MU);
4926   printf("wait\n");
4927   MU.Unlock();
4928 
4929   GLOB = 2;
4930 
4931 }
4932 
Run()4933 void Run() {
4934   printf("test101: negative\n");
4935   MyThreadArray t(Waiter, Signaller);
4936   t.Start();
4937   t.Join();
4938   printf("\tGLOB=%d\n", GLOB);
4939 }
4940 REGISTER_TEST(Run, 101)
4941 }  // namespace test101
4942 
4943 // test102: --fast-mode=yes vs. --initialization-bit=yes {{{1
4944 namespace test102 {
4945 const int HG_CACHELINE_SIZE = 64;
4946 
4947 Mutex MU;
4948 
4949 const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4950 int array[ARRAY_SIZE + 1];
4951 int * GLOB = &array[ARRAY_SIZE/2];
4952 /*
4953   We use sizeof(array) == 4 * HG_CACHELINE_SIZE to be sure that GLOB points
4954   to a memory inside a CacheLineZ which is inside array's memory range
4955 */
4956 
Reader()4957 void Reader() {
4958   usleep(200000);
4959   CHECK(777 == GLOB[0]);
4960   usleep(400000);
4961   CHECK(777 == GLOB[1]);
4962 }
4963 
Run()4964 void Run() {
4965   MyThreadArray t(Reader);
4966   if (!Tsan_FastMode())
4967     ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB+0, "test102: TP. FN with --fast-mode=yes");
4968   ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB+1, "test102: TP");
4969   printf("test102: --fast-mode=yes vs. --initialization-bit=yes\n");
4970 
4971   t.Start();
4972   GLOB[0] = 777;
4973   usleep(400000);
4974   GLOB[1] = 777;
4975   t.Join();
4976 }
4977 
4978 REGISTER_TEST2(Run, 102, FEATURE)
4979 }  // namespace test102
4980 
4981 // test103: Access different memory locations with different LockSets {{{1
4982 namespace test103 {
4983 const int N_MUTEXES = 6;
4984 const int LOCKSET_INTERSECTION_SIZE = 3;
4985 
4986 int data[1 << LOCKSET_INTERSECTION_SIZE] = {0};
4987 Mutex MU[N_MUTEXES];
4988 
LS_to_idx(int ls)4989 inline int LS_to_idx (int ls) {
4990   return (ls >> (N_MUTEXES - LOCKSET_INTERSECTION_SIZE))
4991       & ((1 << LOCKSET_INTERSECTION_SIZE) - 1);
4992 }
4993 
Worker()4994 void Worker() {
4995   for (int ls = 0; ls < (1 << N_MUTEXES); ls++) {
4996     if (LS_to_idx(ls) == 0)
4997       continue;
4998     for (int m = 0; m < N_MUTEXES; m++)
4999       if (ls & (1 << m))
5000         MU[m].Lock();
5001 
5002     data[LS_to_idx(ls)]++;
5003 
5004     for (int m = N_MUTEXES - 1; m >= 0; m--)
5005       if (ls & (1 << m))
5006         MU[m].Unlock();
5007   }
5008 }
5009 
Run()5010 void Run() {
5011   printf("test103: Access different memory locations with different LockSets\n");
5012   MyThreadArray t(Worker, Worker, Worker, Worker);
5013   t.Start();
5014   t.Join();
5015 }
5016 REGISTER_TEST2(Run, 103, FEATURE)
5017 }  // namespace test103
5018 
5019 // test104: TP. Simple race (write vs write). Heap mem. {{{1
5020 namespace test104 {
5021 int     *GLOB = NULL;
Worker()5022 void Worker() {
5023   *GLOB = 1;
5024 }
5025 
Parent()5026 void Parent() {
5027   MyThread t(Worker);
5028   t.Start();
5029   usleep(100000);
5030   *GLOB = 2;
5031   t.Join();
5032 }
Run()5033 void Run() {
5034   GLOB = (int*)memalign(64, sizeof(int));
5035   *GLOB = 0;
5036   ANNOTATE_EXPECT_RACE(GLOB, "test104. TP.");
5037   ANNOTATE_TRACE_MEMORY(GLOB);
5038   printf("test104: positive\n");
5039   Parent();
5040   printf("\tGLOB=%d\n", *GLOB);
5041   free(GLOB);
5042 }
5043 REGISTER_TEST(Run, 104);
5044 }  // namespace test104
5045 
5046 
5047 // test105: Checks how stack grows. {{{1
5048 namespace test105 {
5049 int     GLOB = 0;
5050 
F1()5051 void F1() {
5052   int ar[32] __attribute__((unused));
5053 //  ANNOTATE_TRACE_MEMORY(&ar[0]);
5054 //  ANNOTATE_TRACE_MEMORY(&ar[31]);
5055   ar[0] = 1;
5056   ar[31] = 1;
5057 }
5058 
Worker()5059 void Worker() {
5060   int ar[32] __attribute__((unused));
5061 //  ANNOTATE_TRACE_MEMORY(&ar[0]);
5062 //  ANNOTATE_TRACE_MEMORY(&ar[31]);
5063   ar[0] = 1;
5064   ar[31] = 1;
5065   F1();
5066 }
5067 
Run()5068 void Run() {
5069   printf("test105: negative\n");
5070   Worker();
5071   MyThread t(Worker);
5072   t.Start();
5073   t.Join();
5074   printf("\tGLOB=%d\n", GLOB);
5075 }
5076 REGISTER_TEST(Run, 105)
5077 }  // namespace test105
5078 
5079 
5080 // test106: TN. pthread_once. {{{1
5081 namespace test106 {
5082 int     *GLOB = NULL;
5083 static pthread_once_t once = PTHREAD_ONCE_INIT;
Init()5084 void Init() {
5085   GLOB = new int;
5086   ANNOTATE_TRACE_MEMORY(GLOB);
5087   *GLOB = 777;
5088 }
5089 
Worker0()5090 void Worker0() {
5091   pthread_once(&once, Init);
5092 }
Worker1()5093 void Worker1() {
5094   usleep(100000);
5095   pthread_once(&once, Init);
5096   CHECK(*GLOB == 777);
5097 }
5098 
5099 
Run()5100 void Run() {
5101   printf("test106: negative\n");
5102   MyThreadArray t(Worker0, Worker1, Worker1, Worker1);
5103   t.Start();
5104   t.Join();
5105   printf("\tGLOB=%d\n", *GLOB);
5106 }
5107 REGISTER_TEST2(Run, 106, FEATURE)
5108 }  // namespace test106
5109 
5110 
5111 // test107: Test for ANNOTATE_EXPECT_RACE {{{1
5112 namespace test107 {
5113 int     GLOB = 0;
Run()5114 void Run() {
5115   printf("test107: negative\n");
5116   ANNOTATE_EXPECT_RACE(&GLOB, "No race in fact. Just checking the tool.");
5117   printf("\tGLOB=%d\n", GLOB);
5118 }
5119 REGISTER_TEST2(Run, 107, FEATURE|EXCLUDE_FROM_ALL)
5120 }  // namespace test107
5121 
5122 
5123 // test108: TN. initialization of static object. {{{1
5124 namespace test108 {
5125 // Here we have a function-level static object.
5126 // Starting from gcc 4 this is therad safe,
5127 // but is is not thread safe with many other compilers.
5128 //
5129 // Helgrind supports this kind of initialization by
5130 // intercepting __cxa_guard_acquire/__cxa_guard_release
5131 // and ignoring all accesses between them.
5132 // Helgrind also intercepts pthread_once in the same manner.
5133 class Foo {
5134  public:
Foo()5135   Foo() {
5136     ANNOTATE_TRACE_MEMORY(&a_);
5137     a_ = 42;
5138   }
Check() const5139   void Check() const { CHECK(a_ == 42); }
5140  private:
5141   int a_;
5142 };
5143 
GetFoo()5144 const Foo *GetFoo() {
5145   static const Foo *foo = new Foo();
5146   return foo;
5147 }
Worker0()5148 void Worker0() {
5149   GetFoo();
5150 }
5151 
Worker()5152 void Worker() {
5153   usleep(200000);
5154   const Foo *foo = GetFoo();
5155   foo->Check();
5156 }
5157 
5158 
Run()5159 void Run() {
5160   printf("test108: negative, initialization of static object\n");
5161   MyThreadArray t(Worker0, Worker, Worker);
5162   t.Start();
5163   t.Join();
5164 }
5165 REGISTER_TEST2(Run, 108, FEATURE)
5166 }  // namespace test108
5167 
5168 
5169 // test109: TN. Checking happens before between parent and child threads. {{{1
5170 namespace test109 {
5171 // Check that the detector correctly connects
5172 //   pthread_create with the new thread
5173 // and
5174 //   thread exit with pthread_join
5175 const int N = 32;
5176 static int GLOB[N];
5177 
Worker(void * a)5178 void Worker(void *a) {
5179   usleep(10000);
5180 //  printf("--Worker : %ld %p\n", (int*)a - GLOB, (void*)pthread_self());
5181   int *arg = (int*)a;
5182   (*arg)++;
5183 }
5184 
Run()5185 void Run() {
5186   printf("test109: negative\n");
5187   MyThread *t[N];
5188   for (int i  = 0; i < N; i++) {
5189     t[i] = new MyThread(Worker, &GLOB[i]);
5190   }
5191   for (int i  = 0; i < N; i++) {
5192     ANNOTATE_TRACE_MEMORY(&GLOB[i]);
5193     GLOB[i] = 1;
5194     t[i]->Start();
5195 //    printf("--Started: %p\n", (void*)t[i]->tid());
5196   }
5197   for (int i  = 0; i < N; i++) {
5198 //    printf("--Joining: %p\n", (void*)t[i]->tid());
5199     t[i]->Join();
5200 //    printf("--Joined : %p\n", (void*)t[i]->tid());
5201     GLOB[i]++;
5202   }
5203   for (int i  = 0; i < N; i++) delete t[i];
5204 
5205   printf("\tGLOB=%d\n", GLOB[13]);
5206 }
5207 REGISTER_TEST(Run, 109)
5208 }  // namespace test109
5209 
5210 
5211 // test110: TP. Simple races with stack, global and heap objects. {{{1
5212 namespace test110 {
5213 int        GLOB = 0;
5214 static int STATIC;
5215 
5216 int       *STACK = 0;
5217 
5218 int       *MALLOC;
5219 int       *CALLOC;
5220 int       *REALLOC;
5221 int       *VALLOC;
5222 int       *PVALLOC;
5223 int       *MEMALIGN;
5224 union pi_pv_union { int* pi; void* pv; } POSIX_MEMALIGN;
5225 int       *MMAP;
5226 
5227 int       *NEW;
5228 int       *NEW_ARR;
5229 
Worker()5230 void Worker() {
5231   GLOB++;
5232   STATIC++;
5233 
5234   (*STACK)++;
5235 
5236   (*MALLOC)++;
5237   (*CALLOC)++;
5238   (*REALLOC)++;
5239   (*VALLOC)++;
5240   (*PVALLOC)++;
5241   (*MEMALIGN)++;
5242   (*(POSIX_MEMALIGN.pi))++;
5243   (*MMAP)++;
5244 
5245   (*NEW)++;
5246   (*NEW_ARR)++;
5247 }
Run()5248 void Run() {
5249   int x = 0;
5250   STACK = &x;
5251 
5252   MALLOC = (int*)malloc(sizeof(int));
5253   CALLOC = (int*)calloc(1, sizeof(int));
5254   REALLOC = (int*)realloc(NULL, sizeof(int));
5255   VALLOC = (int*)valloc(sizeof(int));
5256   PVALLOC = (int*)valloc(sizeof(int));  // TODO: pvalloc breaks helgrind.
5257   MEMALIGN = (int*)memalign(64, sizeof(int));
5258   CHECK(0 == posix_memalign(&POSIX_MEMALIGN.pv, 64, sizeof(int)));
5259   MMAP = (int*)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
5260                     MAP_PRIVATE | MAP_ANON, -1, 0);
5261 
5262   NEW     = new int;
5263   NEW_ARR = new int[10];
5264 
5265 
5266   FAST_MODE_INIT(STACK);
5267   ANNOTATE_EXPECT_RACE(STACK, "real race on stack object");
5268   FAST_MODE_INIT(&GLOB);
5269   ANNOTATE_EXPECT_RACE(&GLOB, "real race on global object");
5270   FAST_MODE_INIT(&STATIC);
5271   ANNOTATE_EXPECT_RACE(&STATIC, "real race on a static global object");
5272   FAST_MODE_INIT(MALLOC);
5273   ANNOTATE_EXPECT_RACE(MALLOC, "real race on a malloc-ed object");
5274   FAST_MODE_INIT(CALLOC);
5275   ANNOTATE_EXPECT_RACE(CALLOC, "real race on a calloc-ed object");
5276   FAST_MODE_INIT(REALLOC);
5277   ANNOTATE_EXPECT_RACE(REALLOC, "real race on a realloc-ed object");
5278   FAST_MODE_INIT(VALLOC);
5279   ANNOTATE_EXPECT_RACE(VALLOC, "real race on a valloc-ed object");
5280   FAST_MODE_INIT(PVALLOC);
5281   ANNOTATE_EXPECT_RACE(PVALLOC, "real race on a pvalloc-ed object");
5282   FAST_MODE_INIT(MEMALIGN);
5283   ANNOTATE_EXPECT_RACE(MEMALIGN, "real race on a memalign-ed object");
5284   FAST_MODE_INIT(POSIX_MEMALIGN.pi);
5285   ANNOTATE_EXPECT_RACE(POSIX_MEMALIGN.pi, "real race on a posix_memalign-ed object");
5286   FAST_MODE_INIT(MMAP);
5287   ANNOTATE_EXPECT_RACE(MMAP, "real race on a mmap-ed object");
5288 
5289   FAST_MODE_INIT(NEW);
5290   ANNOTATE_EXPECT_RACE(NEW, "real race on a new-ed object");
5291   FAST_MODE_INIT(NEW_ARR);
5292   ANNOTATE_EXPECT_RACE(NEW_ARR, "real race on a new[]-ed object");
5293 
5294   MyThreadArray t(Worker, Worker, Worker);
5295   t.Start();
5296   t.Join();
5297   printf("test110: positive (race on a stack object)\n");
5298   printf("\tSTACK=%d\n", *STACK);
5299   CHECK(GLOB <= 3);
5300   CHECK(STATIC <= 3);
5301 
5302   free(MALLOC);
5303   free(CALLOC);
5304   free(REALLOC);
5305   free(VALLOC);
5306   free(PVALLOC);
5307   free(MEMALIGN);
5308   free(POSIX_MEMALIGN.pv);
5309   munmap(MMAP, sizeof(int));
5310   delete NEW;
5311   delete [] NEW_ARR;
5312 }
5313 REGISTER_TEST(Run, 110)
5314 }  // namespace test110
5315 
5316 
5317 // test111: TN. Unit test for a bug related to stack handling. {{{1
5318 namespace test111 {
5319 char     *GLOB = 0;
5320 bool COND = false;
5321 Mutex mu;
5322 const int N = 3000;
5323 
write_to_p(char * p,int val)5324 void write_to_p(char *p, int val) {
5325   for (int i = 0; i < N; i++)
5326     p[i] = val;
5327 }
5328 
ArgIsTrue(bool * arg)5329 static bool ArgIsTrue(bool *arg) {
5330 //  printf("ArgIsTrue: %d tid=%d\n", *arg, (int)pthread_self());
5331   return *arg == true;
5332 }
5333 
f1()5334 void f1() {
5335   char some_stack[N];
5336   write_to_p(some_stack, 1);
5337   mu.LockWhen(Condition(&ArgIsTrue, &COND));
5338   mu.Unlock();
5339 }
5340 
f2()5341 void f2() {
5342   char some_stack[N];
5343   char some_more_stack[N];
5344   write_to_p(some_stack, 2);
5345   write_to_p(some_more_stack, 2);
5346 }
5347 
f0()5348 void f0() { f2(); }
5349 
Worker1()5350 void Worker1() {
5351   f0();
5352   f1();
5353   f2();
5354 }
5355 
Worker2()5356 void Worker2() {
5357   usleep(100000);
5358   mu.Lock();
5359   COND = true;
5360   mu.Unlock();
5361 }
5362 
Run()5363 void Run() {
5364   printf("test111: regression test\n");
5365   MyThreadArray t(Worker1, Worker1, Worker2);
5366 //  AnnotateSetVerbosity(__FILE__, __LINE__, 3);
5367   t.Start();
5368   t.Join();
5369 //  AnnotateSetVerbosity(__FILE__, __LINE__, 1);
5370 }
5371 REGISTER_TEST2(Run, 111, FEATURE)
5372 }  // namespace test111
5373 
5374 // test112: STAB. Test for ANNOTATE_PUBLISH_MEMORY_RANGE{{{1
5375 namespace test112 {
5376 char     *GLOB = 0;
5377 const int N = 64 * 5;
5378 Mutex mu;
5379 bool ready = false; // under mu
5380 int beg, end; // under mu
5381 
5382 Mutex mu1;
5383 
Worker()5384 void Worker() {
5385 
5386   bool is_ready = false;
5387   int b, e;
5388   while (!is_ready) {
5389     mu.Lock();
5390     is_ready = ready;
5391     b = beg;
5392     e = end;
5393     mu.Unlock();
5394     usleep(1000);
5395   }
5396 
5397   mu1.Lock();
5398   for (int i = b; i < e; i++) {
5399     GLOB[i]++;
5400   }
5401   mu1.Unlock();
5402 }
5403 
PublishRange(int b,int e)5404 void PublishRange(int b, int e) {
5405   MyThreadArray t(Worker, Worker);
5406   ready = false; // runs before other threads
5407   t.Start();
5408 
5409   ANNOTATE_NEW_MEMORY(GLOB + b, e - b);
5410   ANNOTATE_TRACE_MEMORY(GLOB + b);
5411   for (int j = b; j < e; j++) {
5412     GLOB[j] = 0;
5413   }
5414   ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB + b, e - b);
5415 
5416   // hand off
5417   mu.Lock();
5418   ready = true;
5419   beg = b;
5420   end = e;
5421   mu.Unlock();
5422 
5423   t.Join();
5424 }
5425 
Run()5426 void Run() {
5427   printf("test112: stability (ANNOTATE_PUBLISH_MEMORY_RANGE)\n");
5428   GLOB = new char [N];
5429 
5430   PublishRange(0, 10);
5431   PublishRange(3, 5);
5432 
5433   PublishRange(12, 13);
5434   PublishRange(10, 14);
5435 
5436   PublishRange(15, 17);
5437   PublishRange(16, 18);
5438 
5439   // do few more random publishes.
5440   for (int i = 0; i < 20; i++) {
5441     const int begin = rand() % N;
5442     const int size = (rand() % (N - begin)) + 1;
5443     CHECK(size > 0);
5444     CHECK(begin + size <= N);
5445     PublishRange(begin, begin + size);
5446   }
5447 
5448   printf("GLOB = %d\n", (int)GLOB[0]);
5449 }
5450 REGISTER_TEST2(Run, 112, STABILITY)
5451 }  // namespace test112
5452 
5453 
5454 // test113: PERF. A lot of lock/unlock calls. Many locks {{{1
5455 namespace    test113 {
5456 const int kNumIter = 100000;
5457 const int kNumLocks = 7;
5458 Mutex   MU[kNumLocks];
Run()5459 void Run() {
5460   printf("test113: perf\n");
5461   for (int i = 0; i < kNumIter; i++ ) {
5462     for (int j = 0; j < kNumLocks; j++) {
5463       if (i & (1 << j)) MU[j].Lock();
5464     }
5465     for (int j = kNumLocks - 1; j >= 0; j--) {
5466       if (i & (1 << j)) MU[j].Unlock();
5467     }
5468   }
5469 }
5470 REGISTER_TEST(Run, 113)
5471 }  // namespace test113
5472 
5473 
5474 // test114: STAB. Recursive lock. {{{1
5475 namespace    test114 {
Bar()5476 int Bar() {
5477   static int bar = 1;
5478   return bar;
5479 }
Foo()5480 int Foo() {
5481   static int foo = Bar();
5482   return foo;
5483 }
Worker()5484 void Worker() {
5485   static int x = Foo();
5486   CHECK(x == 1);
5487 }
Run()5488 void Run() {
5489   printf("test114: stab\n");
5490   MyThreadArray t(Worker, Worker);
5491   t.Start();
5492   t.Join();
5493 }
5494 REGISTER_TEST(Run, 114)
5495 }  // namespace test114
5496 
5497 
5498 // test115: TN. sem_open. {{{1
5499 namespace    test115 {
5500 int tid = 0;
5501 Mutex mu;
5502 const char *kSemName = "drt-test-sem";
5503 
5504 int GLOB = 0;
5505 
DoSemOpen()5506 sem_t *DoSemOpen() {
5507   // TODO: there is some race report inside sem_open
5508   // for which suppressions do not work... (???)
5509   ANNOTATE_IGNORE_WRITES_BEGIN();
5510   sem_t *sem = sem_open(kSemName, O_CREAT, 0600, 3);
5511   ANNOTATE_IGNORE_WRITES_END();
5512   return sem;
5513 }
5514 
Worker()5515 void Worker() {
5516   mu.Lock();
5517   int my_tid = tid++;
5518   mu.Unlock();
5519 
5520   if (my_tid == 0) {
5521     GLOB = 1;
5522   }
5523 
5524   // if the detector observes a happens-before arc between
5525   // sem_open and sem_wait, it will be silent.
5526   sem_t *sem = DoSemOpen();
5527   usleep(100000);
5528   CHECK(sem != SEM_FAILED);
5529   CHECK(sem_wait(sem) == 0);
5530 
5531   if (my_tid > 0) {
5532     CHECK(GLOB == 1);
5533   }
5534 }
5535 
Run()5536 void Run() {
5537   printf("test115: stab (sem_open())\n");
5538 
5539   // just check that sem_open is not completely broken
5540   sem_unlink(kSemName);
5541   sem_t* sem = DoSemOpen();
5542   CHECK(sem != SEM_FAILED);
5543   CHECK(sem_wait(sem) == 0);
5544   sem_unlink(kSemName);
5545 
5546   // check that sem_open and sem_wait create a happens-before arc.
5547   MyThreadArray t(Worker, Worker, Worker);
5548   t.Start();
5549   t.Join();
5550   // clean up
5551   sem_unlink(kSemName);
5552 }
5553 REGISTER_TEST(Run, 115)
5554 }  // namespace test115
5555 
5556 
5557 // test116: TN. some operations with string<> objects. {{{1
5558 namespace test116 {
5559 
Worker()5560 void Worker() {
5561   string A[10], B[10], C[10];
5562   for (int i = 0; i < 1000; i++) {
5563     for (int j = 0; j < 10; j++) {
5564       string &a = A[j];
5565       string &b = B[j];
5566       string &c = C[j];
5567       a = "sdl;fkjhasdflksj df";
5568       b = "sdf sdf;ljsd ";
5569       c = "'sfdf df";
5570       c = b;
5571       a = c;
5572       b = a;
5573       swap(a,b);
5574       swap(b,c);
5575     }
5576     for (int j = 0; j < 10; j++) {
5577       string &a = A[j];
5578       string &b = B[j];
5579       string &c = C[j];
5580       a.clear();
5581       b.clear();
5582       c.clear();
5583     }
5584   }
5585 }
5586 
Run()5587 void Run() {
5588   printf("test116: negative (strings)\n");
5589   MyThreadArray t(Worker, Worker, Worker);
5590   t.Start();
5591   t.Join();
5592 }
5593 REGISTER_TEST2(Run, 116, FEATURE|EXCLUDE_FROM_ALL)
5594 }  // namespace test116
5595 
5596 // test117: TN. Many calls to function-scope static init. {{{1
5597 namespace test117 {
5598 const int N = 50;
5599 
Foo()5600 int Foo() {
5601   usleep(20000);
5602   return 1;
5603 }
5604 
Worker(void * a)5605 void Worker(void *a) {
5606   static int foo = Foo();
5607   CHECK(foo == 1);
5608 }
5609 
Run()5610 void Run() {
5611   printf("test117: negative\n");
5612   MyThread *t[N];
5613   for (int i  = 0; i < N; i++) {
5614     t[i] = new MyThread(Worker);
5615   }
5616   for (int i  = 0; i < N; i++) {
5617     t[i]->Start();
5618   }
5619   for (int i  = 0; i < N; i++) {
5620     t[i]->Join();
5621   }
5622   for (int i  = 0; i < N; i++) delete t[i];
5623 }
5624 REGISTER_TEST(Run, 117)
5625 }  // namespace test117
5626 
5627 
5628 
5629 // test118 PERF: One signal, multiple waits. {{{1
5630 namespace   test118 {
5631 int     GLOB = 0;
5632 const int kNumIter = 2000000;
Signaller()5633 void Signaller() {
5634   usleep(50000);
5635   ANNOTATE_CONDVAR_SIGNAL(&GLOB);
5636 }
Waiter()5637 void Waiter() {
5638   for (int i = 0; i < kNumIter; i++) {
5639     ANNOTATE_CONDVAR_WAIT(&GLOB);
5640     if (i == kNumIter / 2)
5641       usleep(100000);
5642   }
5643 }
Run()5644 void Run() {
5645   printf("test118: perf\n");
5646   MyThreadArray t(Signaller, Waiter, Signaller, Waiter);
5647   t.Start();
5648   t.Join();
5649   printf("\tGLOB=%d\n", GLOB);
5650 }
5651 REGISTER_TEST(Run, 118)
5652 }  // namespace test118
5653 
5654 
5655 // test119: TP. Testing that malloc does not introduce any HB arc. {{{1
5656 namespace test119 {
5657 int     GLOB = 0;
Worker1()5658 void Worker1() {
5659   GLOB = 1;
5660   free(malloc(123));
5661 }
Worker2()5662 void Worker2() {
5663   usleep(100000);
5664   free(malloc(345));
5665   GLOB = 2;
5666 }
Run()5667 void Run() {
5668   printf("test119: positive (checking if malloc creates HB arcs)\n");
5669   FAST_MODE_INIT(&GLOB);
5670   if (!(Tsan_PureHappensBefore() && kMallocUsesMutex))
5671     ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "true race");
5672   MyThreadArray t(Worker1, Worker2);
5673   t.Start();
5674   t.Join();
5675   printf("\tGLOB=%d\n", GLOB);
5676 }
5677 REGISTER_TEST(Run, 119)
5678 }  // namespace test119
5679 
5680 
5681 // test120: TP. Thread1: write then read. Thread2: read. {{{1
5682 namespace test120 {
5683 int     GLOB = 0;
5684 
Thread1()5685 void Thread1() {
5686   GLOB = 1;           // write
5687   CHECK(GLOB);        // read
5688 }
5689 
Thread2()5690 void Thread2() {
5691   usleep(100000);
5692   CHECK(GLOB >= 0);   // read
5693 }
5694 
Run()5695 void Run() {
5696   FAST_MODE_INIT(&GLOB);
5697   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "TP (T1: write then read, T2: read)");
5698   printf("test120: positive\n");
5699   MyThreadArray t(Thread1, Thread2);
5700   GLOB = 1;
5701   t.Start();
5702   t.Join();
5703   printf("\tGLOB=%d\n", GLOB);
5704 }
5705 REGISTER_TEST(Run, 120)
5706 }  // namespace test120
5707 
5708 
5709 // test121: TP. Example of double-checked-locking  {{{1
5710 namespace test121 {
5711 struct Foo {
5712   uintptr_t a, b[15];
5713 } __attribute__ ((aligned (64)));
5714 
5715 static Mutex mu;
5716 static Foo  *foo;
5717 
InitMe()5718 void InitMe() {
5719   if (!foo) {
5720     MutexLock lock(&mu);
5721     if (!foo) {
5722       ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo, "test121. Double-checked locking (ptr)");
5723       foo = new Foo;
5724       if (!Tsan_FastMode())
5725         ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo->a, "test121. Double-checked locking (obj)");
5726       foo->a = 42;
5727     }
5728   }
5729 }
5730 
UseMe()5731 void UseMe() {
5732   InitMe();
5733   CHECK(foo && foo->a == 42);
5734 }
5735 
Worker1()5736 void Worker1() { UseMe(); }
Worker2()5737 void Worker2() { UseMe(); }
Worker3()5738 void Worker3() { UseMe(); }
5739 
5740 
Run()5741 void Run() {
5742   FAST_MODE_INIT(&foo);
5743   printf("test121: TP. Example of double-checked-locking\n");
5744   MyThreadArray t1(Worker1, Worker2, Worker3);
5745   t1.Start();
5746   t1.Join();
5747   delete foo;
5748 }
5749 REGISTER_TEST(Run, 121)
5750 }  // namespace test121
5751 
5752 // test122 TP: Simple test with RWLock {{{1
5753 namespace  test122 {
5754 int     VAR1 = 0;
5755 int     VAR2 = 0;
5756 RWLock mu;
5757 
WriteWhileHoldingReaderLock(int * p)5758 void WriteWhileHoldingReaderLock(int *p) {
5759   usleep(100000);
5760   ReaderLockScoped lock(&mu);  // Reader lock for writing. -- bug.
5761   (*p)++;
5762 }
5763 
CorrectWrite(int * p)5764 void CorrectWrite(int *p) {
5765   WriterLockScoped lock(&mu);
5766   (*p)++;
5767 }
5768 
Thread1()5769 void Thread1() { WriteWhileHoldingReaderLock(&VAR1); }
Thread2()5770 void Thread2() { CorrectWrite(&VAR1); }
Thread3()5771 void Thread3() { CorrectWrite(&VAR2); }
Thread4()5772 void Thread4() { WriteWhileHoldingReaderLock(&VAR2); }
5773 
5774 
Run()5775 void Run() {
5776   printf("test122: positive (rw-lock)\n");
5777   VAR1 = 0;
5778   VAR2 = 0;
5779   ANNOTATE_TRACE_MEMORY(&VAR1);
5780   ANNOTATE_TRACE_MEMORY(&VAR2);
5781   if (!Tsan_PureHappensBefore()) {
5782     ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR1, "test122. TP. ReaderLock-ed while writing");
5783     ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR2, "test122. TP. ReaderLock-ed while writing");
5784   }
5785   MyThreadArray t(Thread1, Thread2, Thread3, Thread4);
5786   t.Start();
5787   t.Join();
5788 }
5789 REGISTER_TEST(Run, 122)
5790 }  // namespace test122
5791 
5792 
5793 // test123 TP: accesses of different sizes. {{{1
5794 namespace test123 {
5795 
5796 union uint_union {
5797   uint64_t u64[1];
5798   uint32_t u32[2];
5799   uint16_t u16[4];
5800   uint8_t  u8[8];
5801 };
5802 
5803 uint_union MEM[8];
5804 
5805 // Q. Hey dude, why so many functions?
5806 // A. I need different stack traces for different accesses.
5807 
Wr64_0()5808 void Wr64_0() { MEM[0].u64[0] = 1; }
Wr64_1()5809 void Wr64_1() { MEM[1].u64[0] = 1; }
Wr64_2()5810 void Wr64_2() { MEM[2].u64[0] = 1; }
Wr64_3()5811 void Wr64_3() { MEM[3].u64[0] = 1; }
Wr64_4()5812 void Wr64_4() { MEM[4].u64[0] = 1; }
Wr64_5()5813 void Wr64_5() { MEM[5].u64[0] = 1; }
Wr64_6()5814 void Wr64_6() { MEM[6].u64[0] = 1; }
Wr64_7()5815 void Wr64_7() { MEM[7].u64[0] = 1; }
5816 
Wr32_0()5817 void Wr32_0() { MEM[0].u32[0] = 1; }
Wr32_1()5818 void Wr32_1() { MEM[1].u32[1] = 1; }
Wr32_2()5819 void Wr32_2() { MEM[2].u32[0] = 1; }
Wr32_3()5820 void Wr32_3() { MEM[3].u32[1] = 1; }
Wr32_4()5821 void Wr32_4() { MEM[4].u32[0] = 1; }
Wr32_5()5822 void Wr32_5() { MEM[5].u32[1] = 1; }
Wr32_6()5823 void Wr32_6() { MEM[6].u32[0] = 1; }
Wr32_7()5824 void Wr32_7() { MEM[7].u32[1] = 1; }
5825 
Wr16_0()5826 void Wr16_0() { MEM[0].u16[0] = 1; }
Wr16_1()5827 void Wr16_1() { MEM[1].u16[1] = 1; }
Wr16_2()5828 void Wr16_2() { MEM[2].u16[2] = 1; }
Wr16_3()5829 void Wr16_3() { MEM[3].u16[3] = 1; }
Wr16_4()5830 void Wr16_4() { MEM[4].u16[0] = 1; }
Wr16_5()5831 void Wr16_5() { MEM[5].u16[1] = 1; }
Wr16_6()5832 void Wr16_6() { MEM[6].u16[2] = 1; }
Wr16_7()5833 void Wr16_7() { MEM[7].u16[3] = 1; }
5834 
Wr8_0()5835 void Wr8_0() { MEM[0].u8[0] = 1; }
Wr8_1()5836 void Wr8_1() { MEM[1].u8[1] = 1; }
Wr8_2()5837 void Wr8_2() { MEM[2].u8[2] = 1; }
Wr8_3()5838 void Wr8_3() { MEM[3].u8[3] = 1; }
Wr8_4()5839 void Wr8_4() { MEM[4].u8[4] = 1; }
Wr8_5()5840 void Wr8_5() { MEM[5].u8[5] = 1; }
Wr8_6()5841 void Wr8_6() { MEM[6].u8[6] = 1; }
Wr8_7()5842 void Wr8_7() { MEM[7].u8[7] = 1; }
5843 
WriteAll64()5844 void WriteAll64() {
5845   Wr64_0();
5846   Wr64_1();
5847   Wr64_2();
5848   Wr64_3();
5849   Wr64_4();
5850   Wr64_5();
5851   Wr64_6();
5852   Wr64_7();
5853 }
5854 
WriteAll32()5855 void WriteAll32() {
5856   Wr32_0();
5857   Wr32_1();
5858   Wr32_2();
5859   Wr32_3();
5860   Wr32_4();
5861   Wr32_5();
5862   Wr32_6();
5863   Wr32_7();
5864 }
5865 
WriteAll16()5866 void WriteAll16() {
5867   Wr16_0();
5868   Wr16_1();
5869   Wr16_2();
5870   Wr16_3();
5871   Wr16_4();
5872   Wr16_5();
5873   Wr16_6();
5874   Wr16_7();
5875 }
5876 
WriteAll8()5877 void WriteAll8() {
5878   Wr8_0();
5879   Wr8_1();
5880   Wr8_2();
5881   Wr8_3();
5882   Wr8_4();
5883   Wr8_5();
5884   Wr8_6();
5885   Wr8_7();
5886 }
5887 
W00()5888 void W00() { WriteAll64(); }
W01()5889 void W01() { WriteAll64(); }
W02()5890 void W02() { WriteAll64(); }
5891 
W10()5892 void W10() { WriteAll32(); }
W11()5893 void W11() { WriteAll32(); }
W12()5894 void W12() { WriteAll32(); }
5895 
W20()5896 void W20() { WriteAll16(); }
W21()5897 void W21() { WriteAll16(); }
W22()5898 void W22() { WriteAll16(); }
5899 
W30()5900 void W30() { WriteAll8(); }
W31()5901 void W31() { WriteAll8(); }
W32()5902 void W32() { WriteAll8(); }
5903 
5904 typedef void (*F)(void);
5905 
TestTwoSizes(F f1,F f2)5906 void TestTwoSizes(F f1, F f2) {
5907   // first f1, then f2
5908   ANNOTATE_NEW_MEMORY(&MEM, sizeof(MEM));
5909   memset(&MEM, 0, sizeof(MEM));
5910   MyThreadArray t1(f1, f2);
5911   t1.Start();
5912   t1.Join();
5913   // reverse order
5914   ANNOTATE_NEW_MEMORY(&MEM, sizeof(MEM));
5915   memset(&MEM, 0, sizeof(MEM));
5916   MyThreadArray t2(f2, f1);
5917   t2.Start();
5918   t2.Join();
5919 }
5920 
Run()5921 void Run() {
5922   printf("test123: positive (different sizes)\n");
5923   TestTwoSizes(W00, W10);
5924 //  TestTwoSizes(W01, W20);
5925 //  TestTwoSizes(W02, W30);
5926 //  TestTwoSizes(W11, W21);
5927 //  TestTwoSizes(W12, W31);
5928 //  TestTwoSizes(W22, W32);
5929 
5930 }
5931 REGISTER_TEST2(Run, 123, FEATURE|EXCLUDE_FROM_ALL)
5932 }  // namespace test123
5933 
5934 
5935 // test124: What happens if we delete an unlocked lock? {{{1
5936 namespace test124 {
5937 // This test does not worg with pthreads (you can't call
5938 // pthread_mutex_destroy on a locked lock).
5939 int     GLOB = 0;
5940 const int N = 1000;
Worker()5941 void Worker() {
5942   Mutex *a_large_local_array_of_mutexes;
5943   a_large_local_array_of_mutexes = new Mutex[N];
5944   for (int i = 0; i < N; i++) {
5945     a_large_local_array_of_mutexes[i].Lock();
5946   }
5947   delete []a_large_local_array_of_mutexes;
5948   GLOB = 1;
5949 }
5950 
Run()5951 void Run() {
5952   printf("test124: negative\n");
5953   MyThreadArray t(Worker, Worker, Worker);
5954   t.Start();
5955   t.Join();
5956   printf("\tGLOB=%d\n", GLOB);
5957 }
5958 REGISTER_TEST2(Run, 124, FEATURE|EXCLUDE_FROM_ALL)
5959 }  // namespace test124
5960 
5961 
5962 // test125 TN: Backwards lock (annotated). {{{1
5963 namespace test125 {
5964 // This test uses "Backwards mutex" locking protocol.
5965 // We take a *reader* lock when writing to a per-thread data
5966 // (GLOB[thread_num])  and we take a *writer* lock when we
5967 // are reading from the entire array at once.
5968 //
5969 // Such locking protocol is not understood by ThreadSanitizer's
5970 // hybrid state machine. So, you either have to use a pure-happens-before
5971 // detector ("tsan --pure-happens-before") or apply pure happens-before mode
5972 // to this particular lock by using ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu).
5973 
5974 const int n_threads = 3;
5975 RWLock   mu;
5976 int     GLOB[n_threads];
5977 
5978 int adder_num; // updated atomically.
5979 
Adder()5980 void Adder() {
5981   int my_num = AtomicIncrement(&adder_num, 1);
5982 
5983   ReaderLockScoped lock(&mu);
5984   GLOB[my_num]++;
5985 }
5986 
Aggregator()5987 void Aggregator() {
5988   int sum = 0;
5989   {
5990     WriterLockScoped lock(&mu);
5991     for (int i = 0; i < n_threads; i++) {
5992       sum += GLOB[i];
5993     }
5994   }
5995   printf("sum=%d\n", sum);
5996 }
5997 
Run()5998 void Run() {
5999   printf("test125: negative\n");
6000 
6001   ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu);
6002 
6003   // run Adders, then Aggregator
6004   {
6005     MyThreadArray t(Adder, Adder, Adder, Aggregator);
6006     t.Start();
6007     t.Join();
6008   }
6009 
6010   // Run Aggregator first.
6011   adder_num = 0;
6012   {
6013     MyThreadArray t(Aggregator, Adder, Adder, Adder);
6014     t.Start();
6015     t.Join();
6016   }
6017 
6018 }
6019 REGISTER_TEST(Run, 125)
6020 }  // namespace test125
6021 
6022 // test126 TN: test for BlockingCounter {{{1
6023 namespace  test126 {
6024 BlockingCounter *blocking_counter;
6025 int     GLOB = 0;
Worker()6026 void Worker() {
6027   CHECK(blocking_counter);
6028   CHECK(GLOB == 0);
6029   blocking_counter->DecrementCount();
6030 }
Run()6031 void Run() {
6032   printf("test126: negative\n");
6033   MyThreadArray t(Worker, Worker, Worker);
6034   blocking_counter = new BlockingCounter(3);
6035   t.Start();
6036   blocking_counter->Wait();
6037   GLOB = 1;
6038   t.Join();
6039   printf("\tGLOB=%d\n", GLOB);
6040 }
6041 REGISTER_TEST(Run, 126)
6042 }  // namespace test126
6043 
6044 
6045 // test127. Bad code: unlocking a mutex locked by another thread. {{{1
6046 namespace test127 {
6047 Mutex mu;
Thread1()6048 void Thread1() {
6049   mu.Lock();
6050 }
Thread2()6051 void Thread2() {
6052   usleep(100000);
6053   mu.Unlock();
6054 }
Run()6055 void Run() {
6056   printf("test127: unlocking a mutex locked by another thread.\n");
6057   MyThreadArray t(Thread1, Thread2);
6058   t.Start();
6059   t.Join();
6060 }
6061 REGISTER_TEST(Run, 127)
6062 }  // namespace test127
6063 
6064 // test128. Suppressed code in concurrent accesses {{{1
6065 // Please use --suppressions=unittest.supp flag when running this test.
6066 namespace test128 {
6067 Mutex mu;
6068 int GLOB = 0;
Worker()6069 void Worker() {
6070   usleep(100000);
6071   mu.Lock();
6072   GLOB++;
6073   mu.Unlock();
6074 }
ThisFunctionShouldBeSuppressed()6075 void ThisFunctionShouldBeSuppressed() {
6076   GLOB++;
6077 }
Run()6078 void Run() {
6079   printf("test128: Suppressed code in concurrent accesses.\n");
6080   MyThreadArray t(Worker, ThisFunctionShouldBeSuppressed);
6081   t.Start();
6082   t.Join();
6083 }
6084 REGISTER_TEST2(Run, 128, FEATURE | EXCLUDE_FROM_ALL)
6085 }  // namespace test128
6086 
6087 // test129: TN. Synchronization via ReaderLockWhen(). {{{1
6088 namespace test129 {
6089 int     GLOB = 0;
6090 Mutex   MU;
WeirdCondition(int * param)6091 bool WeirdCondition(int* param) {
6092   *param = GLOB;  // a write into Waiter's memory
6093   return GLOB > 0;
6094 }
Waiter()6095 void Waiter() {
6096   int param = 0;
6097   MU.ReaderLockWhen(Condition(WeirdCondition, &param));
6098   MU.ReaderUnlock();
6099   CHECK(GLOB > 0);
6100   CHECK(param > 0);
6101 }
Waker()6102 void Waker() {
6103   usleep(100000);  // Make sure the waiter blocks.
6104   MU.Lock();
6105   GLOB++;
6106   MU.Unlock();     // calls ANNOTATE_CONDVAR_SIGNAL;
6107 }
Run()6108 void Run() {
6109   printf("test129: Synchronization via ReaderLockWhen()\n");
6110   MyThread mt(Waiter, NULL, "Waiter Thread");
6111   mt.Start();
6112   Waker();
6113   mt.Join();
6114   printf("\tGLOB=%d\n", GLOB);
6115 }
6116 REGISTER_TEST2(Run, 129, FEATURE);
6117 }  // namespace test129
6118 
6119 // test130: TN. Per-thread. {{{1
6120 namespace test130 {
6121 #ifndef NO_TLS
6122 // This test verifies that the race detector handles
6123 // thread-local storage (TLS) correctly.
6124 // As of 09-03-30 ThreadSanitizer has a bug:
6125 //   - Thread1 starts
6126 //   - Thread1 touches per_thread_global
6127 //   - Thread1 ends
6128 //   - Thread2 starts (and there is no happens-before relation between it and
6129 //   Thread1)
6130 //   - Thread2 touches per_thread_global
6131 // It may happen so that Thread2 will have per_thread_global in the same address
6132 // as Thread1. Since there is no happens-before relation between threads,
6133 // ThreadSanitizer reports a race.
6134 //
6135 // test131 does the same for stack.
6136 
6137 static __thread int per_thread_global[10] = {0};
6138 
RealWorker()6139 void RealWorker() {  // Touch per_thread_global.
6140   per_thread_global[1]++;
6141   errno++;
6142 }
6143 
Worker()6144 void Worker() {  // Spawn few threads that touch per_thread_global.
6145   MyThreadArray t(RealWorker, RealWorker);
6146   t.Start();
6147   t.Join();
6148 }
Worker0()6149 void Worker0() { sleep(0); Worker(); }
Worker1()6150 void Worker1() { sleep(1); Worker(); }
Worker2()6151 void Worker2() { sleep(2); Worker(); }
Worker3()6152 void Worker3() { sleep(3); Worker(); }
6153 
Run()6154 void Run() {
6155   printf("test130: Per-thread\n");
6156   MyThreadArray t1(Worker0, Worker1, Worker2, Worker3);
6157   t1.Start();
6158   t1.Join();
6159   printf("\tper_thread_global=%d\n", per_thread_global[1]);
6160 }
6161 REGISTER_TEST(Run, 130)
6162 #endif // NO_TLS
6163 }  // namespace test130
6164 
6165 
6166 // test131: TN. Stack. {{{1
6167 namespace test131 {
6168 // Same as test130, but for stack.
6169 
RealWorker()6170 void RealWorker() {  // Touch stack.
6171   int stack_var = 0;
6172   stack_var++;
6173 }
6174 
Worker()6175 void Worker() {  // Spawn few threads that touch stack.
6176   MyThreadArray t(RealWorker, RealWorker);
6177   t.Start();
6178   t.Join();
6179 }
Worker0()6180 void Worker0() { sleep(0); Worker(); }
Worker1()6181 void Worker1() { sleep(1); Worker(); }
Worker2()6182 void Worker2() { sleep(2); Worker(); }
Worker3()6183 void Worker3() { sleep(3); Worker(); }
6184 
Run()6185 void Run() {
6186   printf("test131: stack\n");
6187   MyThreadArray t(Worker0, Worker1, Worker2, Worker3);
6188   t.Start();
6189   t.Join();
6190 }
6191 REGISTER_TEST(Run, 131)
6192 }  // namespace test131
6193 
6194 
6195 // test132: TP. Simple race (write vs write). Works in fast-mode. {{{1
6196 namespace test132 {
6197 int     GLOB = 0;
Worker()6198 void Worker() { GLOB = 1; }
6199 
Run1()6200 void Run1() {
6201   FAST_MODE_INIT(&GLOB);
6202   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test132");
6203   printf("test132: positive; &GLOB=%p\n", &GLOB);
6204   ANNOTATE_TRACE_MEMORY(&GLOB);
6205   GLOB = 7;
6206   MyThreadArray t(Worker, Worker);
6207   t.Start();
6208   t.Join();
6209 }
6210 
Run()6211 void Run() {
6212   Run1();
6213 }
6214 REGISTER_TEST(Run, 132);
6215 }  // namespace test132
6216 
6217 
6218 // test133: TP. Simple race (write vs write). Works in fast mode. {{{1
6219 namespace test133 {
6220 // Same as test132, but everything is run from a separate thread spawned from
6221 // the main thread.
6222 int     GLOB = 0;
Worker()6223 void Worker() { GLOB = 1; }
6224 
Run1()6225 void Run1() {
6226   FAST_MODE_INIT(&GLOB);
6227   ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test133");
6228   printf("test133: positive; &GLOB=%p\n", &GLOB);
6229   ANNOTATE_TRACE_MEMORY(&GLOB);
6230   GLOB = 7;
6231   MyThreadArray t(Worker, Worker);
6232   t.Start();
6233   t.Join();
6234 }
Run()6235 void Run() {
6236   MyThread t(Run1);
6237   t.Start();
6238   t.Join();
6239 }
6240 REGISTER_TEST(Run, 133);
6241 }  // namespace test133
6242 
6243 
6244 // test134 TN. Swap. Variant of test79. {{{1
6245 namespace test134 {
6246 #if 0
6247 typedef __gnu_cxx::hash_map<int, int> map_t;
6248 #else
6249 typedef std::map<int, int> map_t;
6250 #endif
6251 map_t   map;
6252 Mutex   mu;
6253 // Here we use swap to pass map between threads.
6254 // The synchronization is correct, but w/o the annotation
6255 // any hybrid detector will complain.
6256 
6257 // Swap is very unfriendly to the lock-set (and hybrid) race detectors.
6258 // Since tmp is destructed outside the mutex, we need to have a happens-before
6259 // arc between any prior access to map and here.
6260 // Since the internals of tmp are created ouside the mutex and are passed to
6261 // other thread, we need to have a h-b arc between here and any future access.
6262 // These arcs can be created by HAPPENS_{BEFORE,AFTER} annotations, but it is
6263 // much simpler to apply pure-happens-before mode to the mutex mu.
Swapper()6264 void Swapper() {
6265   map_t tmp;
6266   MutexLock lock(&mu);
6267   ANNOTATE_HAPPENS_AFTER(&map);
6268   // We swap the new empty map 'tmp' with 'map'.
6269   map.swap(tmp);
6270   ANNOTATE_HAPPENS_BEFORE(&map);
6271   // tmp (which is the old version of map) is destroyed here.
6272 }
6273 
Worker()6274 void Worker() {
6275   MutexLock lock(&mu);
6276   ANNOTATE_HAPPENS_AFTER(&map);
6277   map[1]++;
6278   ANNOTATE_HAPPENS_BEFORE(&map);
6279 }
6280 
Run()6281 void Run() {
6282   printf("test134: negative (swap)\n");
6283   // ********************** Shorter way: ***********************
6284   // ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu);
6285   MyThreadArray t(Worker, Worker, Swapper, Worker, Worker);
6286   t.Start();
6287   t.Join();
6288 }
6289 REGISTER_TEST(Run, 134)
6290 }  // namespace test134
6291 
6292 // test135 TN. Swap. Variant of test79. {{{1
6293 namespace test135 {
6294 
SubWorker()6295 void SubWorker() {
6296   const long SIZE = 65536;
6297   for (int i = 0; i < 32; i++) {
6298     int *ptr = (int*)mmap(NULL, SIZE, PROT_READ | PROT_WRITE,
6299                           MAP_PRIVATE | MAP_ANON, -1, 0);
6300     *ptr = 42;
6301     munmap(ptr, SIZE);
6302   }
6303 }
6304 
Worker()6305 void Worker() {
6306   MyThreadArray t(SubWorker, SubWorker, SubWorker, SubWorker);
6307   t.Start();
6308   t.Join();
6309 }
6310 
Run()6311 void Run() {
6312   printf("test135: negative (mmap)\n");
6313   MyThreadArray t(Worker, Worker, Worker, Worker);
6314   t.Start();
6315   t.Join();
6316 }
6317 REGISTER_TEST(Run, 135)
6318 }  // namespace test135
6319 
6320 // test136. Unlock twice. {{{1
6321 namespace test136 {
Run()6322 void Run() {
6323   printf("test136: unlock twice\n");
6324   pthread_mutexattr_t attr;
6325   CHECK(0 == pthread_mutexattr_init(&attr));
6326   CHECK(0 == pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK));
6327 
6328   pthread_mutex_t mu;
6329   CHECK(0 == pthread_mutex_init(&mu, &attr));
6330   CHECK(0 == pthread_mutex_lock(&mu));
6331   CHECK(0 == pthread_mutex_unlock(&mu));
6332   int ret_unlock = pthread_mutex_unlock(&mu);  // unlocking twice.
6333   int ret_destroy = pthread_mutex_destroy(&mu);
6334   printf("  pthread_mutex_unlock returned %d\n", ret_unlock);
6335   printf("  pthread_mutex_destroy returned %d\n", ret_destroy);
6336 
6337 }
6338 
6339 REGISTER_TEST(Run, 136)
6340 }  // namespace test136
6341 
6342 // test137 TP. Races on stack variables. {{{1
6343 namespace test137 {
6344 int GLOB = 0;
6345 ProducerConsumerQueue q(10);
6346 
Worker()6347 void Worker() {
6348   int stack;
6349   int *tmp = (int*)q.Get();
6350   (*tmp)++;
6351   int *racey = &stack;
6352   q.Put(racey);
6353   (*racey)++;
6354   usleep(150000);
6355   // We may miss the races if we sleep less due to die_memory events...
6356 }
6357 
Run()6358 void Run() {
6359   int tmp = 0;
6360   printf("test137: TP. Races on stack variables.\n");
6361   q.Put(&tmp);
6362   MyThreadArray t(Worker, Worker, Worker, Worker);
6363   t.Start();
6364   t.Join();
6365   q.Get();
6366 }
6367 
6368 REGISTER_TEST2(Run, 137, FEATURE | EXCLUDE_FROM_ALL)
6369 }  // namespace test137
6370 
6371 // test138 FN. Two closures hit the same thread in ThreadPool. {{{1
6372 namespace test138 {
6373 int GLOB = 0;
6374 
Worker()6375 void Worker() {
6376   usleep(100000);
6377   GLOB++;
6378 }
6379 
Run()6380 void Run() {
6381   FAST_MODE_INIT(&GLOB);
6382   printf("test138: FN. Two closures hit the same thread in ThreadPool.\n");
6383 
6384   // When using thread pools, two concurrent callbacks might be scheduled
6385   // onto the same executor thread. As a result, unnecessary happens-before
6386   // relation may be introduced between callbacks.
6387   // If we set the number of executor threads to 1, any known data
6388   // race detector will be silent. However, the same situation may happen
6389   // with any number of executor threads (with some probability).
6390   ThreadPool tp(1);
6391   tp.StartWorkers();
6392   tp.Add(NewCallback(Worker));
6393   tp.Add(NewCallback(Worker));
6394 }
6395 
6396 REGISTER_TEST2(Run, 138, FEATURE)
6397 }  // namespace test138
6398 
6399 // test139: FN. A true race hidden by reference counting annotation. {{{1
6400 namespace test139 {
6401 int GLOB = 0;
6402 RefCountedClass *obj;
6403 
Worker1()6404 void Worker1() {
6405   GLOB++;  // First access.
6406   obj->Unref();
6407 }
6408 
Worker2()6409 void Worker2() {
6410   usleep(100000);
6411   obj->Unref();
6412   GLOB++;  // Second access.
6413 }
6414 
Run()6415 void Run() {
6416   FAST_MODE_INIT(&GLOB);
6417   printf("test139: FN. A true race hidden by reference counting annotation.\n");
6418 
6419   obj = new RefCountedClass;
6420   obj->AnnotateUnref();
6421   obj->Ref();
6422   obj->Ref();
6423   MyThreadArray mt(Worker1, Worker2);
6424   mt.Start();
6425   mt.Join();
6426 }
6427 
6428 REGISTER_TEST2(Run, 139, FEATURE)
6429 }  // namespace test139
6430 
6431 // test140 TN. Swap. Variant of test79 and test134. {{{1
6432 namespace test140 {
6433 #if 0
6434 typedef __gnu_cxx::hash_map<int, int> Container;
6435 #else
6436 typedef std::map<int,int>             Container;
6437 #endif
6438 Mutex mu;
6439 static Container container;
6440 
6441 // Here we use swap to pass a Container between threads.
6442 // The synchronization is correct, but w/o the annotation
6443 // any hybrid detector will complain.
6444 //
6445 // Unlike the test134, we try to have a minimal set of annotations
6446 // so that extra h-b arcs do not hide other races.
6447 
6448 // Swap is very unfriendly to the lock-set (and hybrid) race detectors.
6449 // Since tmp is destructed outside the mutex, we need to have a happens-before
6450 // arc between any prior access to map and here.
6451 // Since the internals of tmp are created ouside the mutex and are passed to
6452 // other thread, we need to have a h-b arc between here and any future access.
6453 //
6454 // We want to be able to annotate swapper so that we don't need to annotate
6455 // anything else.
Swapper()6456 void Swapper() {
6457   Container tmp;
6458   tmp[1] = tmp[2] = tmp[3] = 0;
6459   {
6460     MutexLock lock(&mu);
6461     container.swap(tmp);
6462     // we are unpublishing the old container.
6463     ANNOTATE_UNPUBLISH_MEMORY_RANGE(&container, sizeof(container));
6464     // we are publishing the new container.
6465     ANNOTATE_PUBLISH_MEMORY_RANGE(&container, sizeof(container));
6466   }
6467   tmp[1]++;
6468   tmp[2]++;
6469   // tmp (which is the old version of container) is destroyed here.
6470 }
6471 
Worker()6472 void Worker() {
6473   MutexLock lock(&mu);
6474   container[1]++;
6475   int *v = &container[2];
6476   for (int i = 0; i < 10; i++) {
6477     // if uncommented, this will break ANNOTATE_UNPUBLISH_MEMORY_RANGE():
6478     // ANNOTATE_HAPPENS_BEFORE(v);
6479     if (i % 3) {
6480       (*v)++;
6481     }
6482   }
6483 }
6484 
Run()6485 void Run() {
6486   printf("test140: negative (swap) %p\n", &container);
6487   MyThreadArray t(Worker, Worker, Swapper, Worker, Worker);
6488   t.Start();
6489   t.Join();
6490 }
6491 REGISTER_TEST(Run, 140)
6492 }  // namespace test140
6493 
6494 // test141 FP. unlink/fopen, rmdir/opendir. {{{1
6495 namespace test141 {
6496 int GLOB1 = 0,
6497     GLOB2 = 0;
6498 char *dir_name = NULL,
6499      *filename = NULL;
6500 
Waker1()6501 void Waker1() {
6502   usleep(100000);
6503   GLOB1 = 1;  // Write
6504   // unlink deletes a file 'filename'
6505   // which exits spin-loop in Waiter1().
6506   printf("  Deleting file...\n");
6507   CHECK(unlink(filename) == 0);
6508 }
6509 
Waiter1()6510 void Waiter1() {
6511   FILE *tmp;
6512   while ((tmp = fopen(filename, "r")) != NULL) {
6513     fclose(tmp);
6514     usleep(10000);
6515   }
6516   printf("  ...file has been deleted\n");
6517   GLOB1 = 2;  // Write
6518 }
6519 
Waker2()6520 void Waker2() {
6521   usleep(100000);
6522   GLOB2 = 1;  // Write
6523   // rmdir deletes a directory 'dir_name'
6524   // which exit spin-loop in Waker().
6525   printf("  Deleting directory...\n");
6526   CHECK(rmdir(dir_name) == 0);
6527 }
6528 
Waiter2()6529 void Waiter2() {
6530   DIR *tmp;
6531   while ((tmp = opendir(dir_name)) != NULL) {
6532     closedir(tmp);
6533     usleep(10000);
6534   }
6535   printf("  ...directory has been deleted\n");
6536   GLOB2 = 2;
6537 }
6538 
Run()6539 void Run() {
6540   FAST_MODE_INIT(&GLOB1);
6541   FAST_MODE_INIT(&GLOB2);
6542   printf("test141: FP. unlink/fopen, rmdir/opendir.\n");
6543 
6544   dir_name = strdup("/tmp/tsan-XXXXXX");
6545   IGNORE_RETURN_VALUE(mkdtemp(dir_name));
6546 
6547   filename = strdup((std::string() + dir_name + "/XXXXXX").c_str());
6548   const int fd = mkstemp(filename);
6549   CHECK(fd >= 0);
6550   close(fd);
6551 
6552   MyThreadArray mta1(Waker1, Waiter1);
6553   mta1.Start();
6554   mta1.Join();
6555 
6556   MyThreadArray mta2(Waker2, Waiter2);
6557   mta2.Start();
6558   mta2.Join();
6559   free(filename);
6560   filename = 0;
6561   free(dir_name);
6562   dir_name = 0;
6563 }
6564 REGISTER_TEST(Run, 141)
6565 }  // namespace test141
6566 
6567 
6568 // Simple FIFO queue annotated with PCQ annotations. {{{1
6569 class FifoMessageQueue {
6570  public:
FifoMessageQueue()6571   FifoMessageQueue() { ANNOTATE_PCQ_CREATE(this); }
~FifoMessageQueue()6572   ~FifoMessageQueue() { ANNOTATE_PCQ_DESTROY(this); }
6573   // Send a message. 'message' should be positive.
Put(int message)6574   void Put(int message) {
6575     CHECK(message);
6576     MutexLock lock(&mu_);
6577     ANNOTATE_PCQ_PUT(this);
6578     q_.push(message);
6579   }
6580   // Return the message from the queue and pop it
6581   // or return 0 if there are no messages.
Get()6582   int Get() {
6583     MutexLock lock(&mu_);
6584     if (q_.empty()) return 0;
6585     int res = q_.front();
6586     q_.pop();
6587     ANNOTATE_PCQ_GET(this);
6588     return res;
6589   }
6590  private:
6591   Mutex mu_;
6592   queue<int> q_;
6593 };
6594 
6595 
6596 // test142: TN. Check PCQ_* annotations. {{{1
6597 namespace test142 {
6598 // Putter writes to array[i] and sends a message 'i'.
6599 // Getters receive messages and read array[message].
6600 // PCQ_* annotations calm down the hybrid detectors.
6601 
6602 const int N = 1000;
6603 int array[N+1];
6604 
6605 FifoMessageQueue q;
6606 
Putter()6607 void Putter() {
6608   for (int i = 1; i <= N; i++) {
6609     array[i] = i*i;
6610     q.Put(i);
6611     usleep(1000);
6612   }
6613 }
6614 
Getter()6615 void Getter() {
6616   int non_zero_received  = 0;
6617   for (int i = 1; i <= N; i++) {
6618     int res = q.Get();
6619     if (res > 0) {
6620       CHECK(array[res] = res * res);
6621       non_zero_received++;
6622     }
6623     usleep(1000);
6624   }
6625   printf("T=%zd: non_zero_received=%d\n",
6626          (size_t)pthread_self(), non_zero_received);
6627 }
6628 
Run()6629 void Run() {
6630   printf("test142: tests PCQ annotations\n");
6631   MyThreadArray t(Putter, Getter, Getter);
6632   t.Start();
6633   t.Join();
6634 }
6635 REGISTER_TEST(Run, 142)
6636 }  // namespace test142
6637 
6638 
6639 // test143: TP. Check PCQ_* annotations. {{{1
6640 namespace test143 {
6641 // True positive.
6642 // We have a race on GLOB between Putter and one of the Getters.
6643 // Pure h-b will not see it.
6644 // If FifoMessageQueue was annotated using HAPPENS_BEFORE/AFTER, the race would
6645 // be missed too.
6646 // PCQ_* annotations do not hide this race.
6647 int     GLOB = 0;
6648 
6649 FifoMessageQueue q;
6650 
Putter()6651 void Putter() {
6652   GLOB = 1;
6653   q.Put(1);
6654 }
6655 
Getter()6656 void Getter() {
6657   usleep(10000);
6658   q.Get();
6659   CHECK(GLOB == 1);  // Race here
6660 }
6661 
Run()6662 void Run() {
6663   q.Put(1);
6664   if (!Tsan_PureHappensBefore()) {
6665     ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "true races");
6666   }
6667   printf("test143: tests PCQ annotations (true positive)\n");
6668   MyThreadArray t(Putter, Getter, Getter);
6669   t.Start();
6670   t.Join();
6671 }
6672 REGISTER_TEST(Run, 143);
6673 }  // namespace test143
6674 
6675 
6676 
6677 
6678 // test300: {{{1
6679 namespace test300 {
6680 int     GLOB = 0;
Run()6681 void Run() {
6682 }
6683 REGISTER_TEST2(Run, 300, RACE_DEMO)
6684 }  // namespace test300
6685 
6686 // test301: Simple race.  {{{1
6687 namespace test301 {
6688 Mutex mu1;  // This Mutex guards var.
6689 Mutex mu2;  // This Mutex is not related to var.
6690 int   var;  // GUARDED_BY(mu1)
6691 
Thread1()6692 void Thread1() {  // Runs in thread named 'test-thread-1'.
6693   MutexLock lock(&mu1);  // Correct Mutex.
6694   var = 1;
6695 }
6696 
Thread2()6697 void Thread2() {  // Runs in thread named 'test-thread-2'.
6698   MutexLock lock(&mu2);  // Wrong Mutex.
6699   var = 2;
6700 }
6701 
Run()6702 void Run() {
6703   var = 0;
6704   printf("test301: simple race.\n");
6705   MyThread t1(Thread1, NULL, "test-thread-1");
6706   MyThread t2(Thread2, NULL, "test-thread-2");
6707   t1.Start();
6708   t2.Start();
6709   t1.Join();
6710   t2.Join();
6711 }
6712 REGISTER_TEST2(Run, 301, RACE_DEMO)
6713 }  // namespace test301
6714 
6715 // test302: Complex race which happens at least twice.  {{{1
6716 namespace test302 {
6717 // In this test we have many different accesses to GLOB and only one access
6718 // is not synchronized properly.
6719 int     GLOB = 0;
6720 
6721 Mutex MU1;
6722 Mutex MU2;
Worker()6723 void Worker() {
6724   for(int i = 0; i < 100; i++) {
6725     switch(i % 4) {
6726       case 0:
6727         // This read is protected correctly.
6728         MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock();
6729         break;
6730       case 1:
6731         // Here we used the wrong lock! The reason of the race is here.
6732         MU2.Lock(); CHECK(GLOB >= 0); MU2.Unlock();
6733         break;
6734       case 2:
6735         // This read is protected correctly.
6736         MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock();
6737         break;
6738       case 3:
6739         // This write is protected correctly.
6740         MU1.Lock(); GLOB++; MU1.Unlock();
6741         break;
6742     }
6743     // sleep a bit so that the threads interleave
6744     // and the race happens at least twice.
6745     usleep(100);
6746   }
6747 }
6748 
Run()6749 void Run() {
6750   printf("test302: Complex race that happens twice.\n");
6751   MyThread t1(Worker), t2(Worker);
6752   t1.Start();
6753   t2.Start();
6754   t1.Join();   t2.Join();
6755 }
6756 REGISTER_TEST2(Run, 302, RACE_DEMO)
6757 }  // namespace test302
6758 
6759 
6760 // test303: Need to trace the memory to understand the report. {{{1
6761 namespace test303 {
6762 int     GLOB = 0;
6763 
6764 Mutex MU;
Worker1()6765 void Worker1() { CHECK(GLOB >= 0); }
Worker2()6766 void Worker2() { MU.Lock(); GLOB=1;  MU.Unlock();}
6767 
Run()6768 void Run() {
6769   printf("test303: a race that needs annotations.\n");
6770   ANNOTATE_TRACE_MEMORY(&GLOB);
6771   MyThreadArray t(Worker1, Worker2);
6772   t.Start();
6773   t.Join();
6774 }
6775 REGISTER_TEST2(Run, 303, RACE_DEMO)
6776 }  // namespace test303
6777 
6778 
6779 
6780 // test304: Can not trace the memory, since it is a library object. {{{1
6781 namespace test304 {
6782 string *STR;
6783 Mutex   MU;
6784 
Worker1()6785 void Worker1() {
6786   sleep(0);
6787   ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6788   MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
6789 }
Worker2()6790 void Worker2() {
6791   sleep(1);
6792   ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6793   CHECK(STR->length() >= 4); // Unprotected!
6794 }
Worker3()6795 void Worker3() {
6796   sleep(2);
6797   ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6798   MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
6799 }
Worker4()6800 void Worker4() {
6801   sleep(3);
6802   ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6803   MU.Lock(); *STR += " + a very very long string"; MU.Unlock();
6804 }
6805 
Run()6806 void Run() {
6807   STR = new string ("The String");
6808   printf("test304: a race where memory tracing does not work.\n");
6809   MyThreadArray t(Worker1, Worker2, Worker3, Worker4);
6810   t.Start();
6811   t.Join();
6812 
6813   printf("%s\n", STR->c_str());
6814   delete STR;
6815 }
6816 REGISTER_TEST2(Run, 304, RACE_DEMO)
6817 }  // namespace test304
6818 
6819 
6820 
6821 // test305: A bit more tricky: two locks used inconsistenly. {{{1
6822 namespace test305 {
6823 int     GLOB = 0;
6824 
6825 // In this test GLOB is protected by MU1 and MU2, but inconsistently.
6826 // The TRACES observed by helgrind are:
6827 // TRACE[1]: Access{T2/S2 wr} -> new State{Mod; #LS=2; #SS=1; T2/S2}
6828 // TRACE[2]: Access{T4/S9 wr} -> new State{Mod; #LS=1; #SS=2; T2/S2, T4/S9}
6829 // TRACE[3]: Access{T5/S13 wr} -> new State{Mod; #LS=1; #SS=3; T2/S2, T4/S9, T5/S13}
6830 // TRACE[4]: Access{T6/S19 wr} -> new State{Mod; #LS=0; #SS=4; T2/S2, T4/S9, T5/S13, T6/S19}
6831 //
6832 // The guilty access is either Worker2() or Worker4(), depending on
6833 // which mutex is supposed to protect GLOB.
6834 Mutex MU1;
6835 Mutex MU2;
Worker1()6836 void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
Worker2()6837 void Worker2() { MU1.Lock();             GLOB=2;               MU1.Unlock(); }
Worker3()6838 void Worker3() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
Worker4()6839 void Worker4() {             MU2.Lock(); GLOB=4; MU2.Unlock();               }
6840 
Run()6841 void Run() {
6842   ANNOTATE_TRACE_MEMORY(&GLOB);
6843   printf("test305: simple race.\n");
6844   MyThread t1(Worker1), t2(Worker2), t3(Worker3), t4(Worker4);
6845   t1.Start(); usleep(100);
6846   t2.Start(); usleep(100);
6847   t3.Start(); usleep(100);
6848   t4.Start(); usleep(100);
6849   t1.Join(); t2.Join(); t3.Join(); t4.Join();
6850 }
6851 REGISTER_TEST2(Run, 305, RACE_DEMO)
6852 }  // namespace test305
6853 
6854 // test306: Two locks are used to protect a var.  {{{1
6855 namespace test306 {
6856 int     GLOB = 0;
6857 // Thread1 and Thread2 access the var under two locks.
6858 // Thread3 uses no locks.
6859 
6860 Mutex MU1;
6861 Mutex MU2;
Worker1()6862 void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
Worker2()6863 void Worker2() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
Worker3()6864 void Worker3() {                         GLOB=4;               }
6865 
Run()6866 void Run() {
6867   ANNOTATE_TRACE_MEMORY(&GLOB);
6868   printf("test306: simple race.\n");
6869   MyThread t1(Worker1), t2(Worker2), t3(Worker3);
6870   t1.Start(); usleep(100);
6871   t2.Start(); usleep(100);
6872   t3.Start(); usleep(100);
6873   t1.Join(); t2.Join(); t3.Join();
6874 }
6875 REGISTER_TEST2(Run, 306, RACE_DEMO)
6876 }  // namespace test306
6877 
6878 // test307: Simple race, code with control flow  {{{1
6879 namespace test307 {
6880 int     *GLOB = 0;
6881 volatile /*to fake the compiler*/ bool some_condition = true;
6882 
6883 
SomeFunc()6884 void SomeFunc() { }
6885 
FunctionWithControlFlow()6886 int FunctionWithControlFlow() {
6887   int unrelated_stuff = 0;
6888   unrelated_stuff++;
6889   SomeFunc();                // "--keep-history=1" will point somewhere here.
6890   if (some_condition) {      // Or here
6891     if (some_condition) {
6892       unrelated_stuff++;     // Or here.
6893       unrelated_stuff++;
6894       (*GLOB)++;             // "--keep-history=2" will point here (experimental).
6895     }
6896   }
6897   usleep(100000);
6898   return unrelated_stuff;
6899 }
6900 
Worker1()6901 void Worker1() { FunctionWithControlFlow(); }
Worker2()6902 void Worker2() { Worker1(); }
Worker3()6903 void Worker3() { Worker2(); }
Worker4()6904 void Worker4() { Worker3(); }
6905 
Run()6906 void Run() {
6907   GLOB = new int;
6908   *GLOB = 1;
6909   printf("test307: simple race, code with control flow\n");
6910   MyThreadArray t1(Worker1, Worker2, Worker3, Worker4);
6911   t1.Start();
6912   t1.Join();
6913 }
6914 REGISTER_TEST2(Run, 307, RACE_DEMO)
6915 }  // namespace test307
6916 
6917 // test308: Example of double-checked-locking  {{{1
6918 namespace test308 {
6919 struct Foo {
6920   int a;
6921 };
6922 
6923 static int   is_inited = 0;
6924 static Mutex lock;
6925 static Foo  *foo;
6926 
InitMe()6927 void InitMe() {
6928   if (!is_inited) {
6929     lock.Lock();
6930       if (!is_inited) {
6931         foo = new Foo;
6932         foo->a = 42;
6933         is_inited = 1;
6934       }
6935     lock.Unlock();
6936   }
6937 }
6938 
UseMe()6939 void UseMe() {
6940   InitMe();
6941   CHECK(foo && foo->a == 42);
6942 }
6943 
Worker1()6944 void Worker1() { UseMe(); }
Worker2()6945 void Worker2() { UseMe(); }
Worker3()6946 void Worker3() { UseMe(); }
6947 
6948 
Run()6949 void Run() {
6950   ANNOTATE_TRACE_MEMORY(&is_inited);
6951   printf("test308: Example of double-checked-locking\n");
6952   MyThreadArray t1(Worker1, Worker2, Worker3);
6953   t1.Start();
6954   t1.Join();
6955 }
6956 REGISTER_TEST2(Run, 308, RACE_DEMO)
6957 }  // namespace test308
6958 
6959 // test309: Simple race on an STL object.  {{{1
6960 namespace test309 {
6961 string  GLOB;
6962 
Worker1()6963 void Worker1() {
6964   GLOB="Thread1";
6965 }
Worker2()6966 void Worker2() {
6967   usleep(100000);
6968   GLOB="Booooooooooo";
6969 }
6970 
Run()6971 void Run() {
6972   printf("test309: simple race on an STL object.\n");
6973   MyThread t1(Worker1), t2(Worker2);
6974   t1.Start();
6975   t2.Start();
6976   t1.Join();   t2.Join();
6977 }
6978 REGISTER_TEST2(Run, 309, RACE_DEMO)
6979 }  // namespace test309
6980 
6981 // test310: One more simple race.  {{{1
6982 namespace test310 {
6983 int     *PTR = NULL;  // GUARDED_BY(mu1)
6984 
6985 Mutex mu1;  // Protects PTR.
6986 Mutex mu2;  // Unrelated to PTR.
6987 Mutex mu3;  // Unrelated to PTR.
6988 
Writer1()6989 void Writer1() {
6990   MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
6991   MutexLock lock1(&mu1);  // Protect PTR.
6992   *PTR = 1;
6993 }
6994 
Writer2()6995 void Writer2() {
6996   MutexLock lock2(&mu2);  // This lock is unrelated to PTR.
6997   MutexLock lock1(&mu1);  // Protect PTR.
6998   int some_unrelated_stuff = 0;
6999   if (some_unrelated_stuff == 0)
7000     some_unrelated_stuff++;
7001   *PTR = 2;
7002 }
7003 
7004 
Reader()7005 void Reader() {
7006   MutexLock lock2(&mu2);  // Oh, gosh, this is a wrong mutex!
7007   CHECK(*PTR <= 2);
7008 }
7009 
7010 // Some functions to make the stack trace non-trivial.
DoWrite1()7011 void DoWrite1() { Writer1();  }
Thread1()7012 void Thread1()  { DoWrite1(); }
7013 
DoWrite2()7014 void DoWrite2() { Writer2();  }
Thread2()7015 void Thread2()  { DoWrite2(); }
7016 
DoRead()7017 void DoRead()  { Reader();  }
Thread3()7018 void Thread3() { DoRead();  }
7019 
Run()7020 void Run() {
7021   printf("test310: simple race.\n");
7022   PTR = new int;
7023   ANNOTATE_TRACE_MEMORY(PTR);
7024   *PTR = 0;
7025   MyThread t1(Thread1, NULL, "writer1"),
7026            t2(Thread2, NULL, "writer2"),
7027            t3(Thread3, NULL, "buggy reader");
7028   t1.Start();
7029   t2.Start();
7030   usleep(100000);  // Let the writers go first.
7031   t3.Start();
7032 
7033   t1.Join();
7034   t2.Join();
7035   t3.Join();
7036 }
7037 REGISTER_TEST2(Run, 310, RACE_DEMO)
7038 }  // namespace test310
7039 
7040 // test311: Yet another simple race.  {{{1
7041 namespace test311 {
7042 int     *PTR = NULL;  // GUARDED_BY(mu1)
7043 
7044 Mutex mu1;  // Protects PTR.
7045 Mutex mu2;  // Unrelated to PTR.
7046 Mutex mu3;  // Unrelated to PTR.
7047 
GoodWriter1()7048 void GoodWriter1() {
7049   MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
7050   MutexLock lock1(&mu1);  // Protect PTR.
7051   *PTR = 1;
7052 }
7053 
GoodWriter2()7054 void GoodWriter2() {
7055   MutexLock lock2(&mu2);  // This lock is unrelated to PTR.
7056   MutexLock lock1(&mu1);  // Protect PTR.
7057   *PTR = 2;
7058 }
7059 
GoodReader()7060 void GoodReader() {
7061   MutexLock lock1(&mu1);  // Protect PTR.
7062   CHECK(*PTR >= 0);
7063 }
7064 
BuggyWriter()7065 void BuggyWriter() {
7066   MutexLock lock2(&mu2);  // Wrong mutex!
7067   *PTR = 3;
7068 }
7069 
7070 // Some functions to make the stack trace non-trivial.
DoWrite1()7071 void DoWrite1() { GoodWriter1();  }
Thread1()7072 void Thread1()  { DoWrite1(); }
7073 
DoWrite2()7074 void DoWrite2() { GoodWriter2();  }
Thread2()7075 void Thread2()  { DoWrite2(); }
7076 
DoGoodRead()7077 void DoGoodRead()  { GoodReader();  }
Thread3()7078 void Thread3()     { DoGoodRead();  }
7079 
DoBadWrite()7080 void DoBadWrite()  { BuggyWriter(); }
Thread4()7081 void Thread4()     { DoBadWrite(); }
7082 
Run()7083 void Run() {
7084   printf("test311: simple race.\n");
7085   PTR = new int;
7086   ANNOTATE_TRACE_MEMORY(PTR);
7087   *PTR = 0;
7088   MyThread t1(Thread1, NULL, "good writer1"),
7089            t2(Thread2, NULL, "good writer2"),
7090            t3(Thread3, NULL, "good reader"),
7091            t4(Thread4, NULL, "buggy writer");
7092   t1.Start();
7093   t3.Start();
7094   // t2 goes after t3. This way a pure happens-before detector has no chance.
7095   usleep(10000);
7096   t2.Start();
7097   usleep(100000);  // Let the good folks go first.
7098   t4.Start();
7099 
7100   t1.Join();
7101   t2.Join();
7102   t3.Join();
7103   t4.Join();
7104 }
7105 REGISTER_TEST2(Run, 311, RACE_DEMO)
7106 }  // namespace test311
7107 
7108 // test312: A test with a very deep stack. {{{1
7109 namespace test312 {
7110 int     GLOB = 0;
RaceyWrite()7111 void RaceyWrite() { GLOB++; }
Func1()7112 void Func1() { RaceyWrite(); }
Func2()7113 void Func2() { Func1(); }
Func3()7114 void Func3() { Func2(); }
Func4()7115 void Func4() { Func3(); }
Func5()7116 void Func5() { Func4(); }
Func6()7117 void Func6() { Func5(); }
Func7()7118 void Func7() { Func6(); }
Func8()7119 void Func8() { Func7(); }
Func9()7120 void Func9() { Func8(); }
Func10()7121 void Func10() { Func9(); }
Func11()7122 void Func11() { Func10(); }
Func12()7123 void Func12() { Func11(); }
Func13()7124 void Func13() { Func12(); }
Func14()7125 void Func14() { Func13(); }
Func15()7126 void Func15() { Func14(); }
Func16()7127 void Func16() { Func15(); }
Func17()7128 void Func17() { Func16(); }
Func18()7129 void Func18() { Func17(); }
Func19()7130 void Func19() { Func18(); }
Worker()7131 void Worker() { Func19(); }
Run()7132 void Run() {
7133   printf("test312: simple race with deep stack.\n");
7134   MyThreadArray t(Worker, Worker, Worker);
7135   t.Start();
7136   t.Join();
7137 }
7138 REGISTER_TEST2(Run, 312, RACE_DEMO)
7139 }  // namespace test312
7140 
7141 // test313 TP: test for thread graph output {{{1
7142 namespace  test313 {
7143 BlockingCounter *blocking_counter;
7144 int     GLOB = 0;
7145 
7146 // Worker(N) will do 2^N increments of GLOB, each increment in a separate thread
Worker(long depth)7147 void Worker(long depth) {
7148   CHECK(depth >= 0);
7149   if (depth > 0) {
7150     ThreadPool pool(2);
7151     pool.StartWorkers();
7152     pool.Add(NewCallback(Worker, depth-1));
7153     pool.Add(NewCallback(Worker, depth-1));
7154   } else {
7155     GLOB++; // Race here
7156   }
7157 }
Run()7158 void Run() {
7159   printf("test313: positive\n");
7160   Worker(4);
7161   printf("\tGLOB=%d\n", GLOB);
7162 }
7163 REGISTER_TEST2(Run, 313, RACE_DEMO)
7164 }  // namespace test313
7165 
7166 
7167 
7168 // test400: Demo of a simple false positive. {{{1
7169 namespace test400 {
7170 static Mutex mu;
7171 static vector<int> *vec; // GUARDED_BY(mu);
7172 
InitAllBeforeStartingThreads()7173 void InitAllBeforeStartingThreads() {
7174   vec = new vector<int>;
7175   vec->push_back(1);
7176   vec->push_back(2);
7177 }
7178 
Thread1()7179 void Thread1() {
7180   MutexLock lock(&mu);
7181   vec->pop_back();
7182 }
7183 
Thread2()7184 void Thread2() {
7185   MutexLock lock(&mu);
7186   vec->pop_back();
7187 }
7188 
7189 //---- Sub-optimal code ---------
NumberOfElementsLeft()7190 size_t NumberOfElementsLeft() {
7191   MutexLock lock(&mu);
7192   return vec->size();
7193 }
7194 
WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly()7195 void WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly() {
7196   while(NumberOfElementsLeft()) {
7197     ; // sleep or print or do nothing.
7198   }
7199   // It is now safe to access vec w/o lock.
7200   // But a hybrid detector (like ThreadSanitizer) can't see it.
7201   // Solutions:
7202   //   1. Use pure happens-before detector (e.g. "tsan --pure-happens-before")
7203   //   2. Call ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu)
7204   //      in InitAllBeforeStartingThreads()
7205   //   3. (preferred) Use WaitForAllThreadsToFinish_Good() (see below).
7206   CHECK(vec->empty());
7207   delete vec;
7208 }
7209 
7210 //----- Better code -----------
7211 
NoElementsLeft(vector<int> * v)7212 bool NoElementsLeft(vector<int> *v) {
7213   return v->empty();
7214 }
7215 
WaitForAllThreadsToFinish_Good()7216 void WaitForAllThreadsToFinish_Good() {
7217   mu.LockWhen(Condition(NoElementsLeft, vec));
7218   mu.Unlock();
7219 
7220   // It is now safe to access vec w/o lock.
7221   CHECK(vec->empty());
7222   delete vec;
7223 }
7224 
7225 
Run()7226 void Run() {
7227   MyThreadArray t(Thread1, Thread2);
7228   InitAllBeforeStartingThreads();
7229   t.Start();
7230   WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly();
7231 //  WaitForAllThreadsToFinish_Good();
7232   t.Join();
7233 }
7234 REGISTER_TEST2(Run, 400, RACE_DEMO)
7235 }  // namespace test400
7236 
7237 // test401: Demo of false positive caused by reference counting. {{{1
7238 namespace test401 {
7239 // A simplified example of reference counting.
7240 // DecRef() does ref count increment in a way unfriendly to race detectors.
7241 // DecRefAnnotated() does the same in a friendly way.
7242 
7243 static vector<int> *vec;
7244 static int ref_count;
7245 
InitAllBeforeStartingThreads(int number_of_threads)7246 void InitAllBeforeStartingThreads(int number_of_threads) {
7247   vec = new vector<int>;
7248   vec->push_back(1);
7249   ref_count = number_of_threads;
7250 }
7251 
7252 // Correct, but unfriendly to race detectors.
DecRef()7253 int DecRef() {
7254   return AtomicIncrement(&ref_count, -1);
7255 }
7256 
7257 // Correct and friendly to race detectors.
DecRefAnnotated()7258 int DecRefAnnotated() {
7259   ANNOTATE_CONDVAR_SIGNAL(&ref_count);
7260   int res = AtomicIncrement(&ref_count, -1);
7261   if (res == 0) {
7262     ANNOTATE_CONDVAR_WAIT(&ref_count);
7263   }
7264   return res;
7265 }
7266 
ThreadWorker()7267 void ThreadWorker() {
7268   CHECK(ref_count > 0);
7269   CHECK(vec->size() == 1);
7270   if (DecRef() == 0) {  // Use DecRefAnnotated() instead!
7271     // No one uses vec now ==> delete it.
7272     delete vec;  // A false race may be reported here.
7273     vec = NULL;
7274   }
7275 }
7276 
Run()7277 void Run() {
7278   MyThreadArray t(ThreadWorker, ThreadWorker, ThreadWorker);
7279   InitAllBeforeStartingThreads(3 /*number of threads*/);
7280   t.Start();
7281   t.Join();
7282   CHECK(vec == 0);
7283 }
7284 REGISTER_TEST2(Run, 401, RACE_DEMO)
7285 }  // namespace test401
7286 
7287 // test501: Manually call PRINT_* annotations {{{1
7288 namespace test501 {
7289 int  COUNTER = 0;
7290 int     GLOB = 0;
7291 Mutex muCounter, muGlob[65];
7292 
Worker()7293 void Worker() {
7294    muCounter.Lock();
7295    int myId = ++COUNTER;
7296    muCounter.Unlock();
7297 
7298    usleep(100);
7299 
7300    muGlob[myId].Lock();
7301    muGlob[0].Lock();
7302    GLOB++;
7303    muGlob[0].Unlock();
7304    muGlob[myId].Unlock();
7305 }
7306 
Worker_1()7307 void Worker_1() {
7308    MyThreadArray ta (Worker, Worker, Worker, Worker);
7309    ta.Start();
7310    usleep(500000);
7311    ta.Join ();
7312 }
7313 
Worker_2()7314 void Worker_2() {
7315    MyThreadArray ta (Worker_1, Worker_1, Worker_1, Worker_1);
7316    ta.Start();
7317    usleep(300000);
7318    ta.Join ();
7319 }
7320 
Run()7321 void Run() {
7322    ANNOTATE_RESET_STATS();
7323    printf("test501: Manually call PRINT_* annotations.\n");
7324    MyThreadArray ta (Worker_2, Worker_2, Worker_2, Worker_2);
7325    ta.Start();
7326    usleep(100000);
7327    ta.Join ();
7328    ANNOTATE_PRINT_MEMORY_USAGE(0);
7329    ANNOTATE_PRINT_STATS();
7330 }
7331 
7332 REGISTER_TEST2(Run, 501, FEATURE | EXCLUDE_FROM_ALL)
7333 }  // namespace test501
7334 
7335 // test502: produce lots of segments without cross-thread relations {{{1
7336 namespace test502 {
7337 
7338 /*
7339  * This test produces ~1Gb of memory usage when run with the following options:
7340  *
7341  * --tool=helgrind
7342  * --trace-after-race=0
7343  * --num-callers=2
7344  * --more-context=no
7345  */
7346 
7347 Mutex MU;
7348 int     GLOB = 0;
7349 
TP()7350 void TP() {
7351    for (int i = 0; i < 750000; i++) {
7352       MU.Lock();
7353       GLOB++;
7354       MU.Unlock();
7355    }
7356 }
7357 
Run()7358 void Run() {
7359    MyThreadArray t(TP, TP);
7360    printf("test502: produce lots of segments without cross-thread relations\n");
7361 
7362    t.Start();
7363    t.Join();
7364 }
7365 
7366 REGISTER_TEST2(Run, 502, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL
7367                               | PERFORMANCE)
7368 }  // namespace test502
7369 
7370 // test503: produce lots of segments with simple HB-relations {{{1
7371 // HB cache-miss rate is ~55%
7372 namespace test503 {
7373 
7374 //  |- |  |  |  |  |
7375 //  | \|  |  |  |  |
7376 //  |  |- |  |  |  |
7377 //  |  | \|  |  |  |
7378 //  |  |  |- |  |  |
7379 //  |  |  | \|  |  |
7380 //  |  |  |  |- |  |
7381 //  |  |  |  | \|  |
7382 //  |  |  |  |  |- |
7383 //  |  |  |  |  | \|
7384 //  |  |  |  |  |  |----
7385 //->|  |  |  |  |  |
7386 //  |- |  |  |  |  |
7387 //  | \|  |  |  |  |
7388 //     ...
7389 
7390 const int N_threads = 32;
7391 const int ARRAY_SIZE = 128;
7392 int       GLOB[ARRAY_SIZE];
7393 ProducerConsumerQueue *Q[N_threads];
7394 int GLOB_limit = 100000;
7395 int count = -1;
7396 
Worker()7397 void Worker(){
7398    int myId = AtomicIncrement(&count, 1);
7399 
7400    ProducerConsumerQueue &myQ = *Q[myId], &nextQ = *Q[(myId+1) % N_threads];
7401 
7402    // this code produces a new SS with each new segment
7403    while (myQ.Get() != NULL) {
7404       for (int i = 0; i < ARRAY_SIZE; i++)
7405          GLOB[i]++;
7406 
7407       if (myId == 0 && GLOB[0] > GLOB_limit) {
7408          // Stop all threads
7409          for (int i = 0; i < N_threads; i++)
7410             Q[i]->Put(NULL);
7411       } else
7412          nextQ.Put(GLOB);
7413    }
7414 }
7415 
Run()7416 void Run() {
7417    printf("test503: produce lots of segments with simple HB-relations\n");
7418    for (int i = 0; i < N_threads; i++)
7419       Q[i] = new ProducerConsumerQueue(1);
7420    Q[0]->Put(GLOB);
7421 
7422    {
7423       ThreadPool pool(N_threads);
7424       pool.StartWorkers();
7425       for (int i = 0; i < N_threads; i++) {
7426          pool.Add(NewCallback(Worker));
7427       }
7428    } // all folks are joined here.
7429 
7430    for (int i = 0; i < N_threads; i++)
7431       delete Q[i];
7432 }
7433 
7434 REGISTER_TEST2(Run, 503, MEMORY_USAGE | PRINT_STATS
7435                   | PERFORMANCE | EXCLUDE_FROM_ALL)
7436 }  // namespace test503
7437 
7438 // test504: force massive cache fetch-wback (50% misses, mostly CacheLineZ) {{{1
7439 namespace test504 {
7440 
7441 const int N_THREADS = 2,
7442           HG_CACHELINE_COUNT = 1 << 16,
7443           HG_CACHELINE_SIZE  = 1 << 6,
7444           HG_CACHE_SIZE = HG_CACHELINE_COUNT * HG_CACHELINE_SIZE;
7445 
7446 // int gives us ~4x speed of the byte test
7447 // 4x array size gives us
7448 // total multiplier of 16x over the cachesize
7449 // so we can neglect the cached-at-the-end memory
7450 const int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
7451           ITERATIONS = 30;
7452 int array[ARRAY_SIZE];
7453 
7454 int count = 0;
7455 Mutex count_mu;
7456 
Worker()7457 void Worker() {
7458    count_mu.Lock();
7459    int myId = ++count;
7460    count_mu.Unlock();
7461 
7462    // all threads write to different memory locations,
7463    // so no synchronization mechanisms are needed
7464    int lower_bound = ARRAY_SIZE * (myId-1) / N_THREADS,
7465        upper_bound = ARRAY_SIZE * ( myId ) / N_THREADS;
7466    for (int j = 0; j < ITERATIONS; j++)
7467    for (int i = lower_bound; i < upper_bound;
7468             i += HG_CACHELINE_SIZE / sizeof(array[0])) {
7469       array[i] = i; // each array-write generates a cache miss
7470    }
7471 }
7472 
Run()7473 void Run() {
7474    printf("test504: force massive CacheLineZ fetch-wback\n");
7475    MyThreadArray t(Worker, Worker);
7476    t.Start();
7477    t.Join();
7478 }
7479 
7480 REGISTER_TEST2(Run, 504, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7481 }  // namespace test504
7482 
7483 // test505: force massive cache fetch-wback (60% misses) {{{1
7484 // modification of test504 - more threads, byte accesses and lots of mutexes
7485 // so it produces lots of CacheLineF misses (30-50% of CacheLineZ misses)
7486 namespace test505 {
7487 
7488 const int N_THREADS = 2,
7489           HG_CACHELINE_COUNT = 1 << 16,
7490           HG_CACHELINE_SIZE  = 1 << 6,
7491           HG_CACHE_SIZE = HG_CACHELINE_COUNT * HG_CACHELINE_SIZE;
7492 
7493 const int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
7494           ITERATIONS = 3;
7495 int64_t array[ARRAY_SIZE];
7496 
7497 int count = 0;
7498 Mutex count_mu;
7499 
Worker()7500 void Worker() {
7501    const int N_MUTEXES = 5;
7502    Mutex mu[N_MUTEXES];
7503    count_mu.Lock();
7504    int myId = ++count;
7505    count_mu.Unlock();
7506 
7507    // all threads write to different memory locations,
7508    // so no synchronization mechanisms are needed
7509    int lower_bound = ARRAY_SIZE * (myId-1) / N_THREADS,
7510        upper_bound = ARRAY_SIZE * ( myId ) / N_THREADS;
7511    for (int j = 0; j < ITERATIONS; j++)
7512    for (int mutex_id = 0; mutex_id < N_MUTEXES; mutex_id++) {
7513       Mutex *m = & mu[mutex_id];
7514       m->Lock();
7515       for (int i = lower_bound + mutex_id, cnt = 0;
7516                i < upper_bound;
7517                i += HG_CACHELINE_SIZE / sizeof(array[0]), cnt++) {
7518          array[i] = i; // each array-write generates a cache miss
7519       }
7520       m->Unlock();
7521    }
7522 }
7523 
Run()7524 void Run() {
7525    printf("test505: force massive CacheLineF fetch-wback\n");
7526    MyThreadArray t(Worker, Worker);
7527    t.Start();
7528    t.Join();
7529 }
7530 
7531 REGISTER_TEST2(Run, 505, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7532 }  // namespace test505
7533 
7534 // test506: massive HB's using Barriers {{{1
7535 // HB cache miss is ~40%
7536 // segments consume 10x more memory than SSs
7537 // modification of test39
7538 namespace test506 {
7539 #ifndef NO_BARRIER
7540 // Same as test17 but uses Barrier class (pthread_barrier_t).
7541 int     GLOB = 0;
7542 const int N_threads = 64,
7543           ITERATIONS = 1000;
7544 Barrier *barrier[ITERATIONS];
7545 Mutex   MU;
7546 
Worker()7547 void Worker() {
7548   for (int i = 0; i < ITERATIONS; i++) {
7549      MU.Lock();
7550      GLOB++;
7551      MU.Unlock();
7552      barrier[i]->Block();
7553   }
7554 }
Run()7555 void Run() {
7556   printf("test506: massive HB's using Barriers\n");
7557   for (int i = 0; i < ITERATIONS; i++) {
7558      barrier[i] = new Barrier(N_threads);
7559   }
7560   {
7561     ThreadPool pool(N_threads);
7562     pool.StartWorkers();
7563     for (int i = 0; i < N_threads; i++) {
7564       pool.Add(NewCallback(Worker));
7565     }
7566   } // all folks are joined here.
7567   CHECK(GLOB == N_threads * ITERATIONS);
7568   for (int i = 0; i < ITERATIONS; i++) {
7569      delete barrier[i];
7570   }
7571 }
7572 REGISTER_TEST2(Run, 506, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL);
7573 #endif // NO_BARRIER
7574 }  // namespace test506
7575 
7576 // test507: vgHelgrind_initIterAtFM/stackClear benchmark {{{1
7577 // vgHelgrind_initIterAtFM/stackClear consume ~8.5%/5.5% CPU
7578 namespace test507 {
7579 const int N_THREADS    = 1,
7580           BUFFER_SIZE  = 1,
7581           ITERATIONS   = 1 << 20;
7582 
Foo()7583 void Foo() {
7584   struct T {
7585     char temp;
7586     T() {
7587       ANNOTATE_RWLOCK_CREATE(&temp);
7588     }
7589     ~T() {
7590       ANNOTATE_RWLOCK_DESTROY(&temp);
7591     }
7592   } s[BUFFER_SIZE];
7593   s->temp = '\0';
7594 }
7595 
Worker()7596 void Worker() {
7597   for (int j = 0; j < ITERATIONS; j++) {
7598     Foo();
7599   }
7600 }
7601 
Run()7602 void Run() {
7603   printf("test507: vgHelgrind_initIterAtFM/stackClear benchmark\n");
7604   {
7605     ThreadPool pool(N_THREADS);
7606     pool.StartWorkers();
7607     for (int i = 0; i < N_THREADS; i++) {
7608       pool.Add(NewCallback(Worker));
7609     }
7610   } // all folks are joined here.
7611 }
7612 REGISTER_TEST2(Run, 507, EXCLUDE_FROM_ALL);
7613 }  // namespace test507
7614 
7615 // test508: cmp_WordVecs_for_FM benchmark {{{1
7616 // 50+% of CPU consumption by cmp_WordVecs_for_FM
7617 namespace test508 {
7618 const int N_THREADS    = 1,
7619           BUFFER_SIZE  = 1 << 10,
7620           ITERATIONS   = 1 << 9;
7621 
Foo()7622 void Foo() {
7623   struct T {
7624     char temp;
7625     T() {
7626       ANNOTATE_RWLOCK_CREATE(&temp);
7627     }
7628     ~T() {
7629       ANNOTATE_RWLOCK_DESTROY(&temp);
7630     }
7631   } s[BUFFER_SIZE];
7632   s->temp = '\0';
7633 }
7634 
Worker()7635 void Worker() {
7636   for (int j = 0; j < ITERATIONS; j++) {
7637     Foo();
7638   }
7639 }
7640 
Run()7641 void Run() {
7642   printf("test508: cmp_WordVecs_for_FM benchmark\n");
7643   {
7644     ThreadPool pool(N_THREADS);
7645     pool.StartWorkers();
7646     for (int i = 0; i < N_THREADS; i++) {
7647       pool.Add(NewCallback(Worker));
7648     }
7649   } // all folks are joined here.
7650 }
7651 REGISTER_TEST2(Run, 508, EXCLUDE_FROM_ALL);
7652 }  // namespace test508
7653 
7654 // test509: avl_find_node benchmark {{{1
7655 // 10+% of CPU consumption by avl_find_node
7656 namespace test509 {
7657 const int N_THREADS    = 16,
7658           ITERATIONS   = 1 << 8;
7659 
Worker()7660 void Worker() {
7661   std::vector<Mutex*> mu_list;
7662   for (int i = 0; i < ITERATIONS; i++) {
7663     Mutex * mu = new Mutex();
7664     mu_list.push_back(mu);
7665     mu->Lock();
7666   }
7667   for (int i = ITERATIONS - 1; i >= 0; i--) {
7668     Mutex * mu = mu_list[i];
7669     mu->Unlock();
7670     delete mu;
7671   }
7672 }
7673 
Run()7674 void Run() {
7675   printf("test509: avl_find_node benchmark\n");
7676   {
7677     ThreadPool pool(N_THREADS);
7678     pool.StartWorkers();
7679     for (int i = 0; i < N_THREADS; i++) {
7680       pool.Add(NewCallback(Worker));
7681     }
7682   } // all folks are joined here.
7683 }
7684 REGISTER_TEST2(Run, 509, EXCLUDE_FROM_ALL);
7685 }  // namespace test509
7686 
7687 // test510: SS-recycle test {{{1
7688 // this tests shows the case where only ~1% of SS are recycled
7689 namespace test510 {
7690 const int N_THREADS    = 16,
7691           ITERATIONS   = 1 << 10;
7692 int GLOB = 0;
7693 
Worker()7694 void Worker() {
7695   usleep(100000);
7696   for (int i = 0; i < ITERATIONS; i++) {
7697     ANNOTATE_CONDVAR_SIGNAL((void*)0xDeadBeef);
7698     GLOB++;
7699     usleep(10);
7700   }
7701 }
7702 
Run()7703 void Run() {
7704   //ANNOTATE_BENIGN_RACE(&GLOB, "Test");
7705   printf("test510: SS-recycle test\n");
7706   {
7707     ThreadPool pool(N_THREADS);
7708     pool.StartWorkers();
7709     for (int i = 0; i < N_THREADS; i++) {
7710       pool.Add(NewCallback(Worker));
7711     }
7712   } // all folks are joined here.
7713 }
7714 REGISTER_TEST2(Run, 510, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7715 }  // namespace test510
7716 
7717 // test511: Segment refcounting test ('1' refcounting) {{{1
7718 namespace test511 {
7719 int GLOB = 0;
7720 
Run()7721 void Run () {
7722    for (int i = 0; i < 300; i++) {
7723       ANNOTATE_CONDVAR_SIGNAL(&GLOB);
7724       usleep(1000);
7725       GLOB++;
7726       ANNOTATE_CONDVAR_WAIT(&GLOB);
7727       if (i % 100 == 0)
7728          ANNOTATE_PRINT_MEMORY_USAGE(0);
7729    }
7730 }
7731 REGISTER_TEST2(Run, 511, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7732 }  // namespace test511
7733 
7734 // test512: Segment refcounting test ('S' refcounting) {{{1
7735 namespace test512 {
7736 int GLOB = 0;
7737 sem_t SEM;
7738 
Run()7739 void Run () {
7740    sem_init(&SEM, 0, 0);
7741    for (int i = 0; i < 300; i++) {
7742       sem_post(&SEM);
7743       usleep(1000);
7744       GLOB++;
7745       sem_wait(&SEM);
7746       /*if (i % 100 == 0)
7747          ANNOTATE_PRINT_MEMORY_USAGE(0);*/
7748    }
7749    sem_destroy(&SEM);
7750 }
7751 REGISTER_TEST2(Run, 512, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7752 }  // namespace test512
7753 
7754 // test513: --fast-mode benchmark {{{1
7755 namespace test513 {
7756 
7757 const int N_THREADS = 2,
7758           HG_CACHELINE_SIZE  = 1 << 6,
7759           ARRAY_SIZE = HG_CACHELINE_SIZE * 512,
7760           MUTEX_ID_BITS = 8;
7761 //          MUTEX_ID_MASK = (1 << MUTEX_ID_BITS) - 1;
7762 
7763 // Each thread has its own cacheline and tackles with it intensively
7764 const int ITERATIONS = 1024;
7765 int array[N_THREADS][ARRAY_SIZE];
7766 
7767 int count = 0;
7768 Mutex count_mu;
7769 Mutex mutex_arr[N_THREADS][MUTEX_ID_BITS];
7770 
Worker()7771 void Worker() {
7772    count_mu.Lock();
7773    int myId = count++;
7774    count_mu.Unlock();
7775 
7776    // all threads write to different memory locations
7777    for (int j = 0; j < ITERATIONS; j++) {
7778       int mutex_mask = j & MUTEX_ID_BITS;
7779       for (int m = 0; m < MUTEX_ID_BITS; m++)
7780          if (mutex_mask & (1 << m))
7781             mutex_arr[myId][m].Lock();
7782 
7783       for (int i = 0; i < ARRAY_SIZE; i++) {
7784          array[myId][i] = i;
7785       }
7786 
7787       for (int m = 0; m < MUTEX_ID_BITS; m++)
7788          if (mutex_mask & (1 << m))
7789             mutex_arr[myId][m].Unlock();
7790    }
7791 }
7792 
Run()7793 void Run() {
7794    printf("test513: --fast-mode benchmark\n");
7795    {
7796       ThreadPool pool(N_THREADS);
7797       pool.StartWorkers();
7798       for (int i = 0; i < N_THREADS; i++) {
7799          pool.Add(NewCallback(Worker));
7800       }
7801    } // all folks are joined here.
7802 }
7803 
7804 REGISTER_TEST2(Run, 513, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7805 }  // namespace test513
7806 
7807 // End {{{1
7808 // vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker
7809