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