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.
75template <typename T>
76static 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
131CondVar CV;
132int     COND = 0;
133
134
135typedef void (*void_func_void_t)(void);
136enum 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.
148Mutex printf_mu;
149#define printf(args...) \
150    do{ \
151      printf_mu.Lock();\
152      fprintf(stderr, args);\
153      printf_mu.Unlock(); \
154    }while(0)
155
156long GetTimeInMs() {
157   struct timeval tv;
158   gettimeofday(&tv, NULL);
159   return (tv.tv_sec * 1000L) + (tv.tv_usec / 1000L);
160}
161
162struct Test{
163  void_func_void_t f_;
164  int flags_;
165  Test(void_func_void_t f, int flags)
166    : f_(f)
167    , flags_(flags)
168  {}
169  Test() : f_(0), flags_(0) {}
170  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};
185std::map<int, Test> TheMapOfTests;
186
187#define NOINLINE __attribute__ ((noinline))
188extern "C" void NOINLINE AnnotateSetVerbosity(const char *, int, int) {};
189
190
191struct TestAdder {
192  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
202static bool ArgIsOne(int *arg) { return *arg == 1; };
203static bool ArgIsZero(int *arg) { return *arg == 0; };
204static 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
221inline bool Tsan_PureHappensBefore() {
222  return true;
223}
224
225inline 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
238int 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
282class MyThreadArray {
283 public:
284  static const int kSize = 5;
285  typedef void (*F) (void);
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  }
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
302  void Join() {
303    for(int i = 0; i < kSize; i++) {
304      if(ar_[i]) {
305        ar_[i]->Join();
306      }
307    }
308  }
309
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
322namespace test00 {
323int     GLOB = 0;
324void Run() {
325  printf("test00: negative\n");
326  printf("\tGLOB=%d\n", GLOB);
327}
328REGISTER_TEST(Run, 00)
329}  // namespace test00
330
331
332// test01: TP. Simple race (write vs write). {{{1
333namespace test01 {
334int     GLOB = 0;
335void Worker() {
336  GLOB = 1;
337}
338
339void 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}
347void 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}
356REGISTER_TEST(Run, 1);
357}  // namespace test01
358
359
360// test02: TN. Synchronization via CondVar. {{{1
361namespace test02 {
362int     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)
377Mutex   MU;
378
379void 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
389void 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}
400void Run() {
401  printf("test02: negative\n");
402  Waiter();
403  printf("\tGLOB=%d\n", GLOB);
404}
405REGISTER_TEST(Run, 2);
406}  // namespace test02
407
408
409// test03: TN. Synchronization via LockWhen, signaller gets there first. {{{1
410namespace test03 {
411int     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)
425Mutex   MU;
426
427void 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}
435void 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}
445void Run() {
446  printf("test03: negative\n");
447  Waiter();
448  printf("\tGLOB=%d\n", GLOB);
449}
450REGISTER_TEST2(Run, 3, FEATURE|NEEDS_ANNOTATIONS);
451}  // namespace test03
452
453// test04: TN. Synchronization via PCQ. {{{1
454namespace test04 {
455int     GLOB = 0;
456ProducerConsumerQueue 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
466void Putter() {
467  GLOB = 1;
468  Q.Put(NULL);
469}
470
471void Getter() {
472  Q.Get();
473  GLOB = 2;
474}
475
476void Run() {
477  printf("test04: negative\n");
478  MyThreadArray t(Putter, Getter);
479  t.Start();
480  t.Join();
481  printf("\tGLOB=%d\n", GLOB);
482}
483REGISTER_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.
489namespace test05 {
490int     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)
507Mutex   MU;
508
509void Waker() {
510  GLOB = 1;
511  MU.Lock();
512  COND = 1;
513  CV.Signal();
514  MU.Unlock();
515}
516
517void 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}
529void 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}
537REGISTER_TEST(Run, 5);
538}  // namespace test05
539
540
541// test06: TN. Synchronization via CondVar, but Waker gets there first.  {{{1
542namespace test06 {
543int     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
559Mutex   MU;
560
561void Waker() {
562  GLOB = 1;
563  MU.Lock();
564  COND = 1;
565  CV.Signal();
566  MU.Unlock();
567}
568
569void 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}
583void Run() {
584  printf("test06: negative\n");
585  Waiter();
586  printf("\tGLOB=%d\n", GLOB);
587}
588REGISTER_TEST2(Run, 6, FEATURE|NEEDS_ANNOTATIONS);
589}  // namespace test06
590
591
592// test07: TN. Synchronization via LockWhen(), Signaller is observed first. {{{1
593namespace test07 {
594int     GLOB = 0;
595bool    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
611Mutex   MU;
612void Signaller() {
613  GLOB = 1;
614  MU.Lock();
615  COND = true; // We are done! Tell the Waiter.
616  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
617}
618void 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}
630void Run() {
631  printf("test07: negative\n");
632  Waiter();
633  printf("\tGLOB=%d\n", GLOB);
634}
635REGISTER_TEST2(Run, 7, FEATURE|NEEDS_ANNOTATIONS);
636}  // namespace test07
637
638// test08: TN. Synchronization via thread start/join. {{{1
639namespace test08 {
640int     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)
649void Worker() {
650  GLOB = 2;
651}
652
653void Parent() {
654  MyThread t(Worker);
655  GLOB = 1;
656  t.Start();
657  t.Join();
658  GLOB = 3;
659}
660void Run() {
661  printf("test08: negative\n");
662  Parent();
663  printf("\tGLOB=%d\n", GLOB);
664}
665REGISTER_TEST(Run, 8);
666}  // namespace test08
667
668
669// test09: TP. Simple race (read vs write). {{{1
670namespace test09 {
671int     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.
675void Writer() {
676  usleep(100000);
677  GLOB = 3;
678}
679void Reader() {
680  CHECK(GLOB != -777);
681}
682
683void 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}
693REGISTER_TEST(Run, 9);
694}  // namespace test09
695
696
697// test10: FN. Simple race (write vs read). {{{1
698namespace test10 {
699int     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//
713void Writer() {
714  GLOB = 3;
715}
716void Reader() {
717  usleep(100000);
718  CHECK(GLOB != -777);
719}
720
721void 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}
730REGISTER_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//
746namespace test11 {
747int     GLOB = 0;
748Mutex   MU;
749void Worker() {
750  usleep(200000);
751  CHECK(GLOB != 777);
752
753  MU.Lock();
754  COND++;
755  CV.Signal();
756  MU.Unlock();
757}
758
759void 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
776void 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}
782REGISTER_TEST(Run, 11);
783}  // namespace test11
784
785
786// test12: FP. Synchronization via Mutex, then via PCQ. {{{1
787namespace test12 {
788int     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
802ProducerConsumerQueue Q(INT_MAX);
803Mutex   MU;
804
805void Putter() {
806  MU.Lock();
807  GLOB++;
808  MU.Unlock();
809
810  Q.Put(NULL);
811}
812
813void Getter() {
814  MU.Lock();
815  GLOB++;
816  MU.Unlock();
817
818  Q.Get();
819  GLOB++;
820}
821
822void 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}
830REGISTER_TEST(Run, 12);
831}  // namespace test12
832
833
834// test13: FP. Synchronization via Mutex, then via LockWhen. {{{1
835namespace test13 {
836int     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)
851Mutex   MU;
852
853void 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
864void Waiter() {
865  MU.Lock();
866  GLOB++;
867  MU.Unlock();
868
869  MU.LockWhen(Condition(&ArgIsOne, &COND));
870  MU.Unlock();
871  GLOB++;
872}
873
874void 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}
885REGISTER_TEST2(Run, 13, FEATURE|NEEDS_ANNOTATIONS);
886}  // namespace test13
887
888
889// test14: FP. Synchronization via PCQ, reads, 2 workers. {{{1
890namespace test14 {
891int     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)
903ProducerConsumerQueue Q1(INT_MAX), Q2(INT_MAX);
904
905void Putter1() {
906  CHECK(GLOB != 777);
907  Q1.Put(NULL);
908}
909void Putter2() {
910  CHECK(GLOB != 777);
911  Q2.Put(NULL);
912}
913void Getter() {
914  Q1.Get();
915  Q2.Get();
916  GLOB++;
917}
918void 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}
926REGISTER_TEST(Run, 14);
927}  // namespace test14
928
929
930// test15: TN. Synchronization via LockWhen. One waker and 2 waiters. {{{1
931namespace 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
940int     GLOB = 0;
941Mutex   MU;
942
943void Waker() {
944  GLOB = 2;
945
946  MU.Lock();
947  COND = 1;
948  ANNOTATE_CONDVAR_SIGNAL(&MU);
949  MU.Unlock();
950};
951
952void Waiter() {
953  MU.LockWhen(Condition(&ArgIsOne, &COND));
954  MU.Unlock();
955  CHECK(GLOB != 777);
956}
957
958
959void 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}
967REGISTER_TEST(Run, 15);
968}  // namespace test15
969
970
971// test16: FP. Barrier (emulated by CV), 2 threads. {{{1
972namespace 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//
992int     GLOB = 0;
993Mutex   MU;
994Mutex MU2;
995
996void 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
1010void 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}
1019REGISTER_TEST2(Run, 16, FEATURE|NEEDS_ANNOTATIONS);
1020}  // namespace test16
1021
1022
1023// test17: FP. Barrier (emulated by CV), 3 threads. {{{1
1024namespace test17 {
1025// Same as test16, but with 3 threads.
1026int     GLOB = 0;
1027Mutex   MU;
1028Mutex MU2;
1029
1030void 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
1044void 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}
1053REGISTER_TEST2(Run, 17, FEATURE|NEEDS_ANNOTATIONS);
1054}  // namespace test17
1055
1056
1057// test18: TN. Synchronization via Await(), signaller gets there first. {{{1
1058namespace test18 {
1059int     GLOB = 0;
1060Mutex   MU;
1061// Same as test03, but uses Mutex::Await() instead of Mutex::LockWhen().
1062
1063void 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}
1071void 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}
1083void Run() {
1084  printf("test18: negative\n");
1085  Waiter();
1086  printf("\tGLOB=%d\n", GLOB);
1087}
1088REGISTER_TEST2(Run, 18, FEATURE|NEEDS_ANNOTATIONS);
1089}  // namespace test18
1090
1091// test19: TN. Synchronization via AwaitWithTimeout(). {{{1
1092namespace test19 {
1093int     GLOB = 0;
1094// Same as test18, but with AwaitWithTimeout. Do not timeout.
1095Mutex   MU;
1096void 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}
1104void 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}
1116void Run() {
1117  printf("test19: negative\n");
1118  Waiter();
1119  printf("\tGLOB=%d\n", GLOB);
1120}
1121REGISTER_TEST2(Run, 19, FEATURE|NEEDS_ANNOTATIONS);
1122}  // namespace test19
1123
1124// test20: TP. Incorrect synchronization via AwaitWhen(), timeout. {{{1
1125namespace test20 {
1126int     GLOB = 0;
1127Mutex   MU;
1128// True race. We timeout in AwaitWhen.
1129void Waker() {
1130  GLOB = 1;
1131  usleep(100 * 1000);
1132}
1133void 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}
1145void 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}
1152REGISTER_TEST2(Run, 20, FEATURE|NEEDS_ANNOTATIONS);
1153}  // namespace test20
1154
1155// test21: TP. Incorrect synchronization via LockWhenWithTimeout(). {{{1
1156namespace test21 {
1157int     GLOB = 0;
1158// True race. We timeout in LockWhenWithTimeout().
1159Mutex   MU;
1160void Waker() {
1161  GLOB = 1;
1162  usleep(100 * 1000);
1163}
1164void 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}
1175void 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}
1182REGISTER_TEST2(Run, 21, FEATURE|NEEDS_ANNOTATIONS);
1183}  // namespace test21
1184
1185// test22: TP. Incorrect synchronization via CondVar::WaitWithTimeout(). {{{1
1186namespace test22 {
1187int     GLOB = 0;
1188Mutex   MU;
1189// True race. We timeout in CondVar::WaitWithTimeout().
1190void Waker() {
1191  GLOB = 1;
1192  usleep(100 * 1000);
1193}
1194void 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}
1211void 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}
1218REGISTER_TEST(Run, 22);
1219}  // namespace test22
1220
1221// test23: TN. TryLock, ReaderLock, ReaderTryLock. {{{1
1222namespace test23 {
1223// Correct synchronization with TryLock, Lock, ReaderTryLock, ReaderLock.
1224int     GLOB = 0;
1225Mutex   MU;
1226void 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
1239void 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
1252void 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
1261void Worker_Lock() {
1262  for (int i = 0; i < 20; i++) {
1263    MU.Lock();
1264    GLOB++;
1265    MU.Unlock();
1266    usleep(1000);
1267  }
1268}
1269
1270void 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}
1281REGISTER_TEST(Run, 23);
1282}  // namespace test23
1283
1284// test24: TN. Synchronization via ReaderLockWhen(). {{{1
1285namespace test24 {
1286int     GLOB = 0;
1287Mutex   MU;
1288// Same as test03, but uses ReaderLockWhen().
1289
1290void 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}
1298void 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}
1308void Run() {
1309  printf("test24: negative\n");
1310  Waiter();
1311  printf("\tGLOB=%d\n", GLOB);
1312}
1313REGISTER_TEST2(Run, 24, FEATURE|NEEDS_ANNOTATIONS);
1314}  // namespace test24
1315
1316// test25: TN. Synchronization via ReaderLockWhenWithTimeout(). {{{1
1317namespace test25 {
1318int     GLOB = 0;
1319Mutex   MU;
1320// Same as test24, but uses ReaderLockWhenWithTimeout().
1321// We do not timeout.
1322
1323void 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}
1331void 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}
1341void Run() {
1342  printf("test25: negative\n");
1343  Waiter();
1344  printf("\tGLOB=%d\n", GLOB);
1345}
1346REGISTER_TEST2(Run, 25, FEATURE|NEEDS_ANNOTATIONS);
1347}  // namespace test25
1348
1349// test26: TP. Incorrect synchronization via ReaderLockWhenWithTimeout(). {{{1
1350namespace test26 {
1351int     GLOB = 0;
1352Mutex   MU;
1353// Same as test25, but we timeout and incorrectly assume happens-before.
1354
1355void Waker() {
1356  GLOB = 1;
1357  usleep(10000);
1358}
1359void 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}
1369void 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}
1376REGISTER_TEST2(Run, 26, FEATURE|NEEDS_ANNOTATIONS);
1377}  // namespace test26
1378
1379
1380// test27: TN. Simple synchronization via SpinLock. {{{1
1381namespace test27 {
1382#ifndef NO_SPINLOCK
1383int     GLOB = 0;
1384SpinLock MU;
1385void Worker() {
1386  MU.Lock();
1387  GLOB++;
1388  MU.Unlock();
1389  usleep(10000);
1390}
1391
1392void 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}
1399REGISTER_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
1405namespace 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)
1415ProducerConsumerQueue Q(INT_MAX);
1416int     GLOB = 0;
1417Mutex   MU;
1418
1419void 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
1431void Getter() {
1432  Q.Get();
1433  Q.Get();
1434  usleep(100000);
1435  CHECK(GLOB == 2);
1436}
1437
1438void 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}
1445REGISTER_TEST(Run, 28);
1446}  // namespace test28
1447
1448
1449// test29: TN. Synchronization via Mutex, then PCQ. 4 threads. {{{1
1450namespace test29 {
1451// Similar to test28, but has two Getters and two PCQs.
1452ProducerConsumerQueue *Q1, *Q2;
1453Mutex   MU;
1454int     GLOB = 0;
1455
1456void 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
1470void Putter1() { Putter(Q1); }
1471void Putter2() { Putter(Q2); }
1472
1473void 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
1481void 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}
1492REGISTER_TEST(Run, 29);
1493}  // namespace test29
1494
1495
1496// test30: TN. Synchronization via 'safe' race. Writer vs multiple Readers. {{{1
1497namespace 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
1518const int N = 48;
1519static int GLOB[N];
1520volatile int BOUNDARY = 0;
1521
1522void 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
1534void 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
1547void 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}
1556REGISTER_TEST2(Run, 30, FEATURE|NEEDS_ANNOTATIONS);
1557}  // namespace test30
1558
1559
1560// test31: TN. Synchronization via 'safe' race. Writer vs Writer. {{{1
1561namespace 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
1571const int N = 48;
1572static int GLOB[N];
1573volatile int BOUNDARY = 0;
1574
1575void 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
1587void 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
1602void 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}
1611REGISTER_TEST2(Run, 31, FEATURE|NEEDS_ANNOTATIONS);
1612}  // namespace test31
1613
1614
1615// test32: FP. Synchronization via thread create/join. W/R. {{{1
1616namespace 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//
1637int     GLOB = 0;
1638Mutex   MU;
1639
1640void Writer() {
1641  MU.Lock();
1642  GLOB = 1;
1643  MU.Unlock();
1644}
1645
1646void Reader() {
1647  usleep(480000);
1648  MU.Lock();
1649  CHECK(GLOB != 777);
1650  MU.Unlock();
1651}
1652
1653void 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
1665void 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
1672REGISTER_TEST(Run, 32);
1673}  // namespace test32
1674
1675
1676// test33: STAB. Stress test for the number of thread sets (TSETs). {{{1
1677namespace test33 {
1678int     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).
1682const int N_iter = 48;
1683const int Nlog  = 15;
1684const int N     = 1 << Nlog;
1685static int ARR[N];
1686Mutex   MU;
1687
1688void 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
1702void 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}
1726REGISTER_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
1731namespace test34 {
1732// Similar to test33, but for lock sets.
1733int     GLOB = 0;
1734const int N_iter = 48;
1735const int Nlog = 10;
1736const int N    = 1 << Nlog;
1737static int ARR[N];
1738static Mutex *MUs[Nlog];
1739
1740void 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
1749void 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}
1765REGISTER_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
1770namespace 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.
1776int **ARR;
1777const int N_mu   = 25000;
1778const int N_free = 48000;
1779
1780void Worker() {
1781  for (int i = 0; i < N_free; i++)
1782    CHECK(777 == *ARR[i]);
1783}
1784
1785void 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}
1813REGISTER_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
1818namespace 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()
1834ProducerConsumerQueue Q(INT_MAX);
1835int     GLOB = 0;
1836Mutex   MU, MU1;
1837
1838void 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
1852void Getter() {
1853  Q.Get();
1854  Q.Get();
1855  usleep(100000);
1856  MU1.Lock();
1857  GLOB++;
1858  MU1.Unlock();
1859}
1860
1861void 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}
1868REGISTER_TEST(Run, 36);
1869}  // namespace test36
1870
1871
1872// test37: TN. Simple synchronization (write vs read). {{{1
1873namespace test37 {
1874int     GLOB = 0;
1875Mutex   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
1885void Writer() {
1886  MU.Lock();
1887  GLOB = 3;
1888  MU.Unlock();
1889}
1890void Reader() {
1891  usleep(100000);
1892  MU.Lock();
1893  CHECK(GLOB != -777);
1894  MU.Unlock();
1895}
1896
1897void Run() {
1898  printf("test37: negative\n");
1899  MyThreadArray t(Writer, Reader);
1900  t.Start();
1901  t.Join();
1902  printf("\tGLOB=%d\n", GLOB);
1903}
1904REGISTER_TEST(Run, 37);
1905}  // namespace test37
1906
1907
1908// test38: TN. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1
1909namespace 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
1931ProducerConsumerQueue *Q1, *Q2;
1932int     GLOB = 0;
1933Mutex   MU, MU1, MU2;
1934
1935void 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
1951void Putter1() { Putter(Q1); }
1952void Putter2() { Putter(Q2); }
1953
1954void 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
1966void 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}
1977REGISTER_TEST(Run, 38);
1978}  // namespace test38
1979
1980// test39: FP. Barrier. {{{1
1981namespace test39 {
1982#ifndef NO_BARRIER
1983// Same as test17 but uses Barrier class (pthread_barrier_t).
1984int     GLOB = 0;
1985const int N_threads = 3;
1986Barrier barrier(N_threads);
1987Mutex   MU;
1988
1989void Worker() {
1990  MU.Lock();
1991  GLOB++;
1992  MU.Unlock();
1993  barrier.Block();
1994  CHECK(GLOB == N_threads);
1995}
1996void 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}
2009REGISTER_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
2015namespace 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
2037ProducerConsumerQueue *Q1, *Q2;
2038int     GLOB = 0;
2039Mutex   MU, MU1, MU2;
2040
2041void 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
2058void Putter1() { Putter(Q1); }
2059void Putter2() { Putter(Q2); }
2060
2061void 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
2072void 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}
2084REGISTER_TEST(Run, 40);
2085}  // namespace test40
2086
2087// test41: TN. Test for race that appears when loading a dynamic symbol. {{{1
2088namespace test41 {
2089void Worker() {
2090  ANNOTATE_NO_OP(NULL); // An empty function, loaded from dll.
2091}
2092void Run() {
2093  printf("test41: negative\n");
2094  MyThreadArray t(Worker, Worker, Worker);
2095  t.Start();
2096  t.Join();
2097}
2098REGISTER_TEST2(Run, 41, FEATURE|NEEDS_ANNOTATIONS);
2099}  // namespace test41
2100
2101
2102// test42: TN. Using the same cond var several times. {{{1
2103namespace test42 {
2104int GLOB = 0;
2105int COND = 0;
2106int N_threads = 3;
2107Mutex   MU;
2108
2109void 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
2127void 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
2144void 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}
2152REGISTER_TEST2(Run, 42, FEATURE|NEEDS_ANNOTATIONS);
2153}  // namespace test42
2154
2155
2156
2157// test43: TN. {{{1
2158namespace test43 {
2159//
2160// Putter:            Getter:
2161// 1. write
2162// 2. Q.Put() --\     .
2163// 3. read       \--> a. Q.Get()
2164//                    b. read
2165int     GLOB = 0;
2166ProducerConsumerQueue Q(INT_MAX);
2167void Putter() {
2168  GLOB = 1;
2169  Q.Put(NULL);
2170  CHECK(GLOB == 1);
2171}
2172void Getter() {
2173  Q.Get();
2174  usleep(100000);
2175  CHECK(GLOB == 1);
2176}
2177void Run() {
2178  printf("test43: negative\n");
2179  MyThreadArray t(Putter, Getter);
2180  t.Start();
2181  t.Join();
2182  printf("\tGLOB=%d\n", GLOB);
2183}
2184REGISTER_TEST(Run, 43)
2185}  // namespace test43
2186
2187
2188// test44: FP. {{{1
2189namespace 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();
2200int     GLOB = 0;
2201Mutex   MU;
2202ProducerConsumerQueue Q(INT_MAX);
2203void Putter() {
2204  CHECK(GLOB == 0);
2205  Q.Put(NULL);
2206  MU.Lock();
2207  GLOB = 1;
2208  MU.Unlock();
2209}
2210void Getter() {
2211  Q.Get();
2212  usleep(100000);
2213  MU.Lock();
2214  GLOB = 1;
2215  MU.Unlock();
2216}
2217void 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}
2225REGISTER_TEST(Run, 44)
2226}  // namespace test44
2227
2228
2229// test45: TN. {{{1
2230namespace 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();
2241int     GLOB = 0;
2242Mutex   MU;
2243ProducerConsumerQueue Q(INT_MAX);
2244void Putter() {
2245  CHECK(GLOB == 0);
2246  Q.Put(NULL);
2247  MU.Lock();
2248  GLOB++;
2249  MU.Unlock();
2250}
2251void Getter() {
2252  Q.Get();
2253  usleep(100000);
2254  MU.Lock();
2255  CHECK(GLOB <= 1);
2256  MU.Unlock();
2257}
2258void Run() {
2259  printf("test45: negative\n");
2260  MyThreadArray t(Putter, Getter);
2261  t.Start();
2262  t.Join();
2263  printf("\tGLOB=%d\n", GLOB);
2264}
2265REGISTER_TEST(Run, 45)
2266}  // namespace test45
2267
2268
2269// test46: FN. {{{1
2270namespace 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();
2280int     GLOB = 0;
2281Mutex   MU;
2282void First() {
2283  GLOB++;
2284  MU.Lock();
2285  GLOB++;
2286  MU.Unlock();
2287}
2288void 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}
2301void Run() {
2302  ANNOTATE_TRACE_MEMORY(&GLOB);
2303  MyThreadArray t(First, Second);
2304  t.Start();
2305  t.Join();
2306}
2307REGISTER_TEST(Run, 46)
2308}  // namespace test46
2309
2310
2311// test47: TP. Not detected by pure happens-before detectors. {{{1
2312namespace 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
2323int     GLOB = 0;
2324Mutex   MU;
2325void First() {
2326  GLOB=1;
2327  MU.Lock();
2328  MU.Unlock();
2329}
2330void Second() {
2331  usleep(480000);
2332  MU.Lock();
2333  MU.Unlock();
2334  GLOB++;
2335}
2336void 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}
2346REGISTER_TEST(Run, 47)
2347}  // namespace test47
2348
2349
2350// test48: FN. Simple race (single write vs multiple reads). {{{1
2351namespace test48 {
2352int     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//
2367void Writer() {
2368  GLOB = 3;
2369}
2370void Reader() {
2371  usleep(100000);
2372  CHECK(GLOB != -777);
2373}
2374
2375void 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}
2384REGISTER_TEST(Run, 48)
2385}  // namespace test48
2386
2387
2388// test49: FN. Simple race (single write vs multiple reads). {{{1
2389namespace test49 {
2390int     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//
2407void Writer() {
2408  GLOB = 3;
2409}
2410void Reader() {
2411  usleep(100000);
2412  CHECK(GLOB != -777);
2413  CHECK(GLOB != -777);
2414  CHECK(GLOB != -777);
2415  CHECK(GLOB != -777);
2416}
2417
2418void 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}
2427REGISTER_TEST(Run, 49);
2428}  // namespace test49
2429
2430
2431// test50: TP. Synchronization via CondVar. {{{1
2432namespace test50 {
2433int     GLOB = 0;
2434Mutex   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
2452void 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
2468void 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}
2482void 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}
2489REGISTER_TEST2(Run, 50, FEATURE|NEEDS_ANNOTATIONS);
2490}  // namespace test50
2491
2492
2493// test51: TP. Synchronization via CondVar: problem with several signals. {{{1
2494namespace test51 {
2495int     GLOB = 0;
2496int     COND = 0;
2497Mutex   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
2522void 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
2543void 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}
2557void 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}
2564REGISTER_TEST(Run, 51);
2565}  // namespace test51
2566
2567
2568// test52: TP. Synchronization via CondVar: problem with several signals. {{{1
2569namespace test52 {
2570int     GLOB = 0;
2571int     COND = 0;
2572Mutex   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
2595void 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
2614void 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}
2628void 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}
2635REGISTER_TEST(Run, 52);
2636}  // namespace test52
2637
2638
2639// test53: FP. Synchronization via implicit semaphore. {{{1
2640namespace 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
2662int     GLOB = 0;
2663bool    FLAG = false;
2664Mutex   MU1, MU2;
2665
2666void Initializer() {
2667  MU1.Lock();
2668  GLOB = 1000;
2669  FLAG = true;
2670  MU1.Unlock();
2671  usleep(100000); // just in case
2672}
2673
2674void 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
2689void 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}
2699REGISTER_TEST(Run, 53)
2700}  // namespace test53
2701
2702
2703// test54: TN. Synchronization via implicit semaphore. Annotated {{{1
2704namespace test54 {
2705// Same as test53, but annotated.
2706int     GLOB = 0;
2707bool    FLAG = false;
2708Mutex   MU1, MU2;
2709
2710void 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
2719void 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
2735void 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}
2742REGISTER_TEST2(Run, 54, FEATURE|NEEDS_ANNOTATIONS)
2743}  // namespace test54
2744
2745
2746// test55: FP. Synchronization with TryLock. Not easy for race detectors {{{1
2747namespace 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).
2753int     GLOB = 0;
2754Mutex   MU;
2755
2756void Worker_Lock() {
2757  GLOB = 1;
2758  MU.Lock();
2759}
2760
2761void 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
2774void 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}
2781REGISTER_TEST2(Run, 55, FEATURE|EXCLUDE_FROM_ALL);
2782}  // namespace test55
2783
2784
2785
2786// test56: TP. Use of ANNOTATE_BENIGN_RACE. {{{1
2787namespace test56 {
2788// For whatever reason the user wants to treat
2789// a race on GLOB as a benign race.
2790int     GLOB = 0;
2791int     GLOB2 = 0;
2792
2793void Worker() {
2794  GLOB++;
2795}
2796
2797void 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}
2806REGISTER_TEST2(Run, 56, FEATURE|NEEDS_ANNOTATIONS)
2807}  // namespace test56
2808
2809
2810// test57: TN: Correct use of atomics. {{{1
2811namespace test57 {
2812int     GLOB = 0;
2813void Writer() {
2814  for (int i = 0; i < 10; i++) {
2815    AtomicIncrement(&GLOB, 1);
2816    usleep(1000);
2817  }
2818}
2819void Reader() {
2820  while (GLOB < 20) usleep(1000);
2821}
2822void 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}
2830REGISTER_TEST(Run, 57)
2831}  // namespace test57
2832
2833
2834// test58: TN. User defined synchronization. {{{1
2835namespace test58 {
2836int     GLOB1 = 1;
2837int     GLOB2 = 2;
2838int     FLAG1 = 0;
2839int     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
2846void Worker2() {
2847  FLAG1=GLOB2;
2848
2849  while(!FLAG2)
2850    ;
2851  GLOB2=FLAG2;
2852}
2853
2854void Worker1() {
2855  FLAG2=GLOB1;
2856
2857  while(!FLAG1)
2858    ;
2859  GLOB1=FLAG1;
2860}
2861
2862void 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}
2870REGISTER_TEST2(Run, 58, FEATURE|EXCLUDE_FROM_ALL)
2871}  // namespace test58
2872
2873
2874
2875// test59: TN. User defined synchronization. Annotated {{{1
2876namespace test59 {
2877int     COND1 = 0;
2878int     COND2 = 0;
2879int     GLOB1 = 1;
2880int     GLOB2 = 2;
2881int     FLAG1 = 0;
2882int     FLAG2 = 0;
2883// same as test 58 but annotated
2884
2885void Worker2() {
2886  FLAG1=GLOB2;
2887  ANNOTATE_CONDVAR_SIGNAL(&COND2);
2888  while(!FLAG2) usleep(1);
2889  ANNOTATE_CONDVAR_WAIT(&COND1);
2890  GLOB2=FLAG2;
2891}
2892
2893void Worker1() {
2894  FLAG2=GLOB1;
2895  ANNOTATE_CONDVAR_SIGNAL(&COND1);
2896  while(!FLAG1) usleep(1);
2897  ANNOTATE_CONDVAR_WAIT(&COND2);
2898  GLOB1=FLAG1;
2899}
2900
2901void 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}
2911REGISTER_TEST2(Run, 59, FEATURE|NEEDS_ANNOTATIONS)
2912}  // namespace test59
2913
2914
2915// test60: TN. Correct synchronization using signal-wait {{{1
2916namespace test60 {
2917int     COND1 = 0;
2918int     COND2 = 0;
2919int     GLOB1 = 1;
2920int     GLOB2 = 2;
2921int     FLAG2 = 0;
2922int     FLAG1 = 0;
2923Mutex   MU;
2924// same as test 59 but synchronized with signal-wait.
2925
2926void 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
2943void 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
2960void 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}
2968REGISTER_TEST2(Run, 60, FEATURE|NEEDS_ANNOTATIONS)
2969}  // namespace test60
2970
2971
2972// test61: TN. Synchronization via Mutex as in happens-before, annotated. {{{1
2973namespace test61 {
2974Mutex MU;
2975int     GLOB = 0;
2976int     *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
2982void 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
2992void 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
3007void Run() {
3008  printf("test61: negative\n");
3009  MyThreadArray t(Putter, Getter);
3010  t.Start();
3011  t.Join();
3012  printf("\tGLOB=%d\n", GLOB);
3013}
3014REGISTER_TEST2(Run, 61, FEATURE|NEEDS_ANNOTATIONS)
3015}  // namespace test61
3016
3017
3018// test62: STAB. Create as many segments as possible. {{{1
3019namespace 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.
3022ProducerConsumerQueue Q(INT_MAX);
3023const int N = 1 << 22;
3024
3025void 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
3034void Getter() {
3035  for (int i = 0; i < N; i++)
3036    Q.Get();
3037}
3038
3039void Run() {
3040  printf("test62:\n");
3041  MyThreadArray t(Putter, Getter);
3042  t.Start();
3043  t.Join();
3044}
3045REGISTER_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
3050namespace 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.
3053const int N = 1 << 24;
3054int C = 0;
3055
3056void 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
3065void Getter() {
3066}
3067
3068void Run() {
3069  printf("test63:\n");
3070  MyThreadArray t(Putter, Getter);
3071  t.Start();
3072  t.Join();
3073}
3074REGISTER_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
3079namespace 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
3090int     GLOB = 0;
3091ProducerConsumerQueue Q(INT_MAX);
3092
3093void T1() {
3094  CHECK(GLOB == 0);
3095}
3096
3097void T2() {
3098  usleep(100000);
3099  CHECK(GLOB == 0);
3100  Q.Put(NULL);
3101}
3102
3103void T3() {
3104  Q.Get();
3105  GLOB = 1;
3106}
3107
3108
3109void 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}
3118REGISTER_TEST(Run, 64)
3119}  // namespace test64
3120
3121
3122// test65: TP. T2 happens-before T3, but T1 is independent. Writes in T1/T2. {{{1
3123namespace 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
3139int     GLOB = 0;
3140Mutex   MU;
3141ProducerConsumerQueue Q(INT_MAX);
3142
3143void T1() {
3144  MU.Lock();
3145  GLOB++;
3146  MU.Unlock();
3147}
3148
3149void T2() {
3150  usleep(100000);
3151  MU.Lock();
3152  GLOB++;
3153  MU.Unlock();
3154  Q.Put(NULL);
3155}
3156
3157void T3() {
3158  Q.Get();
3159  GLOB = 1;
3160}
3161
3162
3163void 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}
3173REGISTER_TEST(Run, 65)
3174}  // namespace test65
3175
3176
3177// test66: TN. Two separate pairs of signaller/waiter using the same CV. {{{1
3178namespace test66 {
3179int     GLOB1 = 0;
3180int     GLOB2 = 0;
3181int     C1 = 0;
3182int     C2 = 0;
3183Mutex   MU;
3184
3185void Signaller1() {
3186  GLOB1 = 1;
3187  MU.Lock();
3188  C1 = 1;
3189  CV.Signal();
3190  MU.Unlock();
3191}
3192
3193void Signaller2() {
3194  GLOB2 = 1;
3195  usleep(100000);
3196  MU.Lock();
3197  C2 = 1;
3198  CV.Signal();
3199  MU.Unlock();
3200}
3201
3202void Waiter1() {
3203  MU.Lock();
3204  while (C1 != 1) CV.Wait(&MU);
3205  ANNOTATE_CONDVAR_WAIT(&CV);
3206  MU.Unlock();
3207  GLOB1 = 2;
3208}
3209
3210void Waiter2() {
3211  MU.Lock();
3212  while (C2 != 1) CV.Wait(&MU);
3213  ANNOTATE_CONDVAR_WAIT(&CV);
3214  MU.Unlock();
3215  GLOB2 = 2;
3216}
3217
3218void 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}
3225REGISTER_TEST2(Run, 66, FEATURE|NEEDS_ANNOTATIONS)
3226}  // namespace test66
3227
3228
3229// test67: FN. Race between Signaller1 and Waiter2 {{{1
3230namespace 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.
3236int     GLOB = 0;
3237int     C1 = 0;
3238int     C2 = 0;
3239Mutex   MU;
3240
3241void Signaller1() {
3242  GLOB = 1;
3243  MU.Lock();
3244  C1 = 1;
3245  CV.Signal();
3246  MU.Unlock();
3247}
3248
3249void Signaller2() {
3250  usleep(100000);
3251  MU.Lock();
3252  C2 = 1;
3253  CV.Signal();
3254  MU.Unlock();
3255}
3256
3257void Waiter1() {
3258  MU.Lock();
3259  while (C1 != 1) CV.Wait(&MU);
3260  ANNOTATE_CONDVAR_WAIT(&CV);
3261  MU.Unlock();
3262}
3263
3264void Waiter2() {
3265  MU.Lock();
3266  while (C2 != 1) CV.Wait(&MU);
3267  ANNOTATE_CONDVAR_WAIT(&CV);
3268  MU.Unlock();
3269  GLOB = 2;
3270}
3271
3272void 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}
3281REGISTER_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
3286namespace 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.
3292int     GLOB = 0;
3293int     COND = 0;
3294const int N_writers = 3;
3295Mutex MU, MU1;
3296
3297void 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
3310void 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
3324void 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}
3333REGISTER_TEST(Run, 68)
3334}  // namespace test68
3335
3336
3337// test69:  {{{1
3338namespace 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:
3344int     GLOB = 0;
3345int     COND = 0;
3346const int N_writers = 3;
3347int     FAKE_MU = 0;
3348Mutex MU, MU1;
3349
3350void 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
3363void 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
3379void 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}
3386REGISTER_TEST(Run, 69)
3387}  // namespace test69
3388
3389// test70: STAB. Check that TRACE_MEMORY works. {{{1
3390namespace test70 {
3391int     GLOB = 0;
3392void Run() {
3393  printf("test70: negative\n");
3394  ANNOTATE_TRACE_MEMORY(&GLOB);
3395  GLOB = 1;
3396  printf("\tGLOB=%d\n", GLOB);
3397}
3398REGISTER_TEST(Run, 70)
3399}  // namespace test70
3400
3401
3402
3403// test71: TN. strlen, index. {{{1
3404namespace 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
3417char    *str;
3418void 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}
3428void WorkerY() {
3429  str[5] = 'Y';
3430  str[6] = 'Y';
3431  str[7] = '\0';
3432}
3433
3434void 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}
3451REGISTER_TEST(Run, 71)
3452}  // namespace test71
3453
3454
3455// test72: STAB. Stress test for the number of segment sets (SSETs). {{{1
3456namespace 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.
3461int     GLOB = 0;
3462const int N_iter = 30;
3463const int Nlog  = 16;
3464const int N     = 1 << Nlog;
3465static int64_t ARR1[N];
3466static int64_t ARR2[N];
3467Barrier *barriers[N_iter];
3468Mutex   MU;
3469
3470void 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
3506void 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}
3531REGISTER_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
3537namespace test73 {
3538#ifndef NO_BARRIER
3539// Variation of test72.
3540// We perform accesses of different sizes to the same location.
3541int     GLOB = 0;
3542const int N_iter = 2;
3543const int Nlog  = 16;
3544const int N     = 1 << Nlog;
3545union uint64_union {
3546  uint64_t u64[1];
3547  uint32_t u32[2];
3548  uint16_t u16[4];
3549  uint8_t  u8 [8];
3550};
3551static uint64_union ARR1[N];
3552union uint32_union {
3553  uint32_t u32[1];
3554  uint16_t u16[2];
3555  uint8_t  u8 [4];
3556};
3557static uint32_union ARR2[N];
3558Barrier *barriers[N_iter];
3559Mutex   MU;
3560
3561void 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
3598void 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}
3623REGISTER_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
3629namespace    test74 {
3630const int N = 100000;
3631Mutex   MU;
3632void Run() {
3633  printf("test74: perf\n");
3634  for (int i = 0; i < N; i++ ) {
3635    MU.Lock();
3636    MU.Unlock();
3637  }
3638}
3639REGISTER_TEST(Run, 74)
3640}  // namespace test74
3641
3642
3643// test75: TN. Test for sem_post, sem_wait, sem_trywait. {{{1
3644namespace test75 {
3645int     GLOB = 0;
3646sem_t   sem[2];
3647
3648void Poster() {
3649  GLOB = 1;
3650  sem_post(&sem[0]);
3651  sem_post(&sem[1]);
3652}
3653
3654void Waiter() {
3655  sem_wait(&sem[0]);
3656  CHECK(GLOB==1);
3657}
3658void TryWaiter() {
3659  usleep(500000);
3660  sem_trywait(&sem[1]);
3661  CHECK(GLOB==1);
3662}
3663
3664void 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}
3687REGISTER_TEST(Run, 75)
3688}  // namespace test75
3689
3690// RefCountedClass {{{1
3691struct RefCountedClass {
3692 public:
3693  RefCountedClass() {
3694    annotate_unref_ = false;
3695    ref_ = 0;
3696    data_ = 0;
3697  }
3698
3699  ~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
3708  void AccessData() {
3709    this->mu_.Lock();
3710    this->data_++;
3711    this->mu_.Unlock();
3712  }
3713
3714  void Ref() {
3715    MU.Lock();
3716    CHECK(ref_ >= 0);
3717    ref_++;
3718    MU.Unlock();
3719  }
3720
3721  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
3738  static void Annotate_MU() {
3739    ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
3740  }
3741  void AnnotateUnref() {
3742    annotate_unref_ = true;
3743  }
3744  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
3758Mutex RefCountedClass::MU;
3759
3760// test76: FP. Ref counting, no annotations. {{{1
3761namespace test76 {
3762#ifndef NO_BARRIER
3763int     GLOB = 0;
3764Barrier barrier(4);
3765RefCountedClass *object = NULL;
3766void Worker() {
3767  object->Ref();
3768  barrier.Block();
3769  object->AccessData();
3770  object->Unref();
3771}
3772void 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}
3780REGISTER_TEST2(Run, 76, FEATURE)
3781#endif // NO_BARRIER
3782}  // namespace test76
3783
3784
3785
3786// test77: TN. Ref counting, MU is annotated. {{{1
3787namespace test77 {
3788#ifndef NO_BARRIER
3789// same as test76, but RefCountedClass::MU is annotated.
3790int     GLOB = 0;
3791Barrier barrier(4);
3792RefCountedClass *object = NULL;
3793void Worker() {
3794  object->Ref();
3795  barrier.Block();
3796  object->AccessData();
3797  object->Unref();
3798}
3799void 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}
3807REGISTER_TEST(Run, 77)
3808#endif // NO_BARRIER
3809}  // namespace test77
3810
3811
3812
3813// test78: TN. Ref counting, Unref is annotated. {{{1
3814namespace test78 {
3815#ifndef NO_BARRIER
3816// same as test76, but RefCountedClass::Unref is annotated.
3817int     GLOB = 0;
3818Barrier barrier(4);
3819RefCountedClass *object = NULL;
3820void Worker() {
3821  object->Ref();
3822  barrier.Block();
3823  object->AccessData();
3824  object->Unref();
3825}
3826void 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}
3834REGISTER_TEST(Run, 78)
3835#endif // NO_BARRIER
3836}  // namespace test78
3837
3838
3839
3840// test79 TN. Swap. {{{1
3841namespace test79 {
3842#if 0
3843typedef __gnu_cxx::hash_map<int, int> map_t;
3844#else
3845typedef std::map<int, int> map_t;
3846#endif
3847map_t   MAP;
3848Mutex   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
3854void 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
3863void Worker2() {
3864  MU.Lock();
3865  MAP[1]++;  // Just update MAP under MU.
3866  MU.Unlock();
3867}
3868
3869void Worker3() { Worker1(); }
3870void Worker4() { Worker2(); }
3871
3872void 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}
3879REGISTER_TEST(Run, 79)
3880}  // namespace test79
3881
3882
3883// AtomicRefCountedClass. {{{1
3884// Same as RefCountedClass, but using atomic ops instead of mutex.
3885struct AtomicRefCountedClass {
3886 public:
3887  AtomicRefCountedClass() {
3888    annotate_unref_ = false;
3889    ref_ = 0;
3890    data_ = 0;
3891  }
3892
3893  ~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
3901  void AccessData() {
3902    this->mu_.Lock();
3903    this->data_++;
3904    this->mu_.Unlock();
3905  }
3906
3907  void Ref() {
3908    AtomicIncrement(&ref_, 1);
3909  }
3910
3911  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
3924  void AnnotateUnref() {
3925    annotate_unref_ = true;
3926  }
3927  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
3940namespace test80 {
3941#ifndef NO_BARRIER
3942int     GLOB = 0;
3943Barrier barrier(4);
3944AtomicRefCountedClass *object = NULL;
3945void Worker() {
3946  object->Ref();
3947  barrier.Block();
3948  object->AccessData();
3949  object->Unref(); // All the tricky stuff is here.
3950}
3951void 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}
3959REGISTER_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
3965namespace test81 {
3966#ifndef NO_BARRIER
3967// same as test80, but Unref is annotated.
3968int     GLOB = 0;
3969Barrier barrier(4);
3970AtomicRefCountedClass *object = NULL;
3971void Worker() {
3972  object->Ref();
3973  barrier.Block();
3974  object->AccessData();
3975  object->Unref(); // All the tricky stuff is here.
3976}
3977void 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}
3985REGISTER_TEST2(Run, 81, FEATURE|EXCLUDE_FROM_ALL)
3986#endif // NO_BARRIER
3987}  // namespace test81
3988
3989
3990// test82: Object published w/o synchronization. {{{1
3991namespace 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
4011class FOO {
4012 public:
4013  FOO() {
4014    idx_ = rand() % 1024;
4015    arr_[idx_] = 77777;
4016  //   __asm__ __volatile__("" : : : "memory"); // this fixes!
4017  }
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
4026const int N = 100000;
4027static volatile FOO *foo[N];
4028Mutex   MU;
4029
4030void Writer() {
4031  for (int i = 0; i < N; i++) {
4032    foo[i] = new FOO;
4033    usleep(100);
4034  }
4035}
4036
4037void 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
4053void Run() {
4054  printf("test82: positive\n");
4055  MyThreadArray t(Writer, Reader);
4056  t.Start();
4057  t.Join();
4058}
4059REGISTER_TEST2(Run, 82, FEATURE|EXCLUDE_FROM_ALL)
4060}  // namespace test82
4061
4062
4063// test83: Object published w/o synchronization (simple version){{{1
4064namespace test83 {
4065// A simplified version of test83 (example of a wrong code).
4066// This test, though incorrect, will almost never fail.
4067volatile static int *ptr = NULL;
4068Mutex   MU;
4069
4070void Writer() {
4071  usleep(100);
4072  ptr = new int(777);
4073}
4074
4075void Reader() {
4076  while(!ptr) {
4077    MU.Lock(); // Not a synchronization!
4078    MU.Unlock();
4079  }
4080  CHECK(*ptr == 777);
4081}
4082
4083void Run() {
4084//  printf("test83: positive\n");
4085  MyThreadArray t(Writer, Reader);
4086  t.Start();
4087  t.Join();
4088}
4089REGISTER_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
4094namespace 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.
4099static int s_x = 0;
4100/* s_dummy[] ensures that s_x and s_y are not in the same cache line. */
4101static char s_dummy[512] = {0};
4102static int s_y;
4103
4104void thread_func_1()
4105{
4106  s_y = 1;
4107  AtomicIncrement(&s_x, 1);
4108}
4109
4110void thread_func_2()
4111{
4112  while (AtomicIncrement(&s_x, 0) == 0)
4113    ;
4114  printf("y = %d\n", s_y);
4115}
4116
4117
4118void 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}
4127REGISTER_TEST(Run, 84)
4128}  // namespace test84
4129
4130
4131// test85: Test for RunningOnValgrind(). {{{1
4132namespace  test85 {
4133int     GLOB = 0;
4134void Run() {
4135  printf("test85: RunningOnValgrind() = %d\n", RunningOnValgrind());
4136}
4137REGISTER_TEST(Run, 85)
4138}  // namespace test85
4139
4140
4141// test86: Test for race inside DTOR: racey write to vptr. Benign. {{{1
4142namespace 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
4169bool flag_stopped = false;
4170Mutex mu;
4171
4172ProducerConsumerQueue Q(INT_MAX);  // Used to pass A* between threads.
4173
4174struct A {
4175  A()  { printf("A::A()\n"); }
4176  virtual ~A() { printf("A::~A()\n"); }
4177  virtual void f() { }
4178
4179  uintptr_t padding[15];
4180} __attribute__ ((aligned (64)));
4181
4182struct B: A {
4183  B()  { printf("B::B()\n"); }
4184  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  }
4192  virtual void f() { }
4193};
4194
4195void 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
4209void 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
4221void Run() {
4222  printf("test86: positive, race inside DTOR\n");
4223  MyThreadArray t(Waiter, Worker);
4224  t.Start();
4225  t.Join();
4226}
4227REGISTER_TEST(Run, 86)
4228}  // namespace test86
4229
4230
4231// test87: Test for race inside DTOR: racey write to vptr. Harmful.{{{1
4232namespace 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//
4242bool flag_stopped = false;
4243Mutex mu;
4244
4245ProducerConsumerQueue Q(INT_MAX);  // Used to pass A* between threads.
4246
4247struct A {
4248  A()  { printf("A::A()\n"); }
4249  virtual ~A() { printf("A::~A()\n"); }
4250  virtual void f() = 0; // pure virtual.
4251};
4252
4253struct B: A {
4254  B()  { printf("B::B()\n"); }
4255  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
4266struct C: B {
4267  C()  { printf("C::C()\n"); }
4268  virtual ~C() { printf("C::~C()\n"); }
4269  virtual void f() { }
4270};
4271
4272void Waiter() {
4273  A *a = new C;
4274  Q.Put(a);
4275  delete a;
4276}
4277
4278void 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
4288void Run() {
4289  printf("test87: positive, race inside DTOR\n");
4290  MyThreadArray t(Waiter, Worker);
4291  t.Start();
4292  t.Join();
4293}
4294REGISTER_TEST2(Run, 87, FEATURE|EXCLUDE_FROM_ALL)
4295}  // namespace test87
4296
4297
4298// test88: Test for ANNOTATE_IGNORE_WRITES_*{{{1
4299namespace test88 {
4300// a recey write annotated with ANNOTATE_IGNORE_WRITES_BEGIN/END.
4301int     GLOB = 0;
4302void Worker() {
4303  ANNOTATE_IGNORE_WRITES_BEGIN();
4304  GLOB = 1;
4305  ANNOTATE_IGNORE_WRITES_END();
4306}
4307void 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}
4315REGISTER_TEST(Run, 88)
4316}  // namespace test88
4317
4318
4319// test89: Test for debug info. {{{1
4320namespace 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.
4324struct STRUCT {
4325  int a, b, c;
4326};
4327
4328struct A {
4329  int a;
4330  A() {
4331    ANNOTATE_TRACE_MEMORY(&a);
4332    a = 1;
4333  }
4334  virtual ~A() {
4335    a = 4;
4336  }
4337};
4338
4339struct B : A {
4340  B()  { CHECK(a == 1); }
4341  virtual ~B() { CHECK(a == 3); }
4342};
4343struct C : B {
4344  C()  { a = 2; }
4345  virtual ~C() { a = 3; }
4346};
4347
4348int            GLOBAL = 0;
4349int           *STACK  = 0;
4350STRUCT         GLOB_STRUCT;
4351STRUCT        *STACK_STRUCT;
4352STRUCT        *HEAP_STRUCT;
4353
4354void Worker() {
4355  GLOBAL = 1;
4356  *STACK = 1;
4357  GLOB_STRUCT.b   = 1;
4358  STACK_STRUCT->b = 1;
4359  HEAP_STRUCT->b  = 1;
4360}
4361
4362void 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}
4382REGISTER_TEST2(Run, 89, FEATURE|EXCLUDE_FROM_ALL)
4383}  // namespace test89
4384
4385
4386// test90: FP. Test for a safely-published pointer (read-only). {{{1
4387namespace 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
4399int     *GLOB = 0;
4400Mutex   MU;
4401
4402void 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
4412void 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
4425void 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}
4433REGISTER_TEST(Run, 90)
4434}  // namespace test90
4435
4436
4437// test91: FP. Test for a safely-published pointer (read-write). {{{1
4438namespace 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
4446int     *GLOB = 0;
4447Mutex   MU, MU1, MU2;
4448
4449void 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
4458void 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
4474void 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}
4482REGISTER_TEST(Run, 91)
4483}  // namespace test91
4484
4485
4486// test92: TN. Test for a safely-published pointer (read-write), annotated. {{{1
4487namespace 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
4505struct ObjType {
4506  int arr[10];
4507};
4508
4509ObjType *GLOB = 0;
4510Mutex   MU, MU1, MU2;
4511
4512void 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
4523void 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
4538void Accessor0() { Accessor(0); }
4539void Accessor5() { Accessor(5); }
4540void Accessor9() { Accessor(9); }
4541
4542void 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}
4549REGISTER_TEST(Run, 92)
4550}  // namespace test92
4551
4552
4553// test93: TP. Test for incorrect usage of ANNOTATE_PUBLISH_MEMORY_RANGE. {{{1
4554namespace test93 {
4555int     GLOB = 0;
4556
4557void Reader() {
4558  CHECK(GLOB == 0);
4559}
4560
4561void 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
4567void 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}
4574REGISTER_TEST2(Run, 93, FEATURE|EXCLUDE_FROM_ALL)
4575}  // namespace test93
4576
4577
4578// test94: TP. Check do_cv_signal/fake segment logic {{{1
4579namespace test94 {
4580int     GLOB;
4581
4582int COND  = 0;
4583int COND2 = 0;
4584Mutex MU, MU2;
4585CondVar CV, CV2;
4586
4587void 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}
4597void 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}
4606void Thr3() {
4607  MU.Lock();
4608  while(COND != 1)
4609    CV.Wait(&MU);
4610  MU.Unlock();
4611}
4612void 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}
4619void 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}
4628REGISTER_TEST(Run, 94);
4629}  // namespace test94
4630
4631// test95: TP. Check do_cv_signal/fake segment logic {{{1
4632namespace test95 {
4633int     GLOB = 0;
4634
4635int COND  = 0;
4636int COND2 = 0;
4637Mutex MU, MU2;
4638CondVar CV, CV2;
4639
4640void 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}
4651void Thr2() {
4652  usleep(10000);  // Make sure the waiter blocks.
4653
4654  MU2.Lock();
4655  COND2 = 1;
4656  CV2.Signal();
4657  MU2.Unlock();
4658}
4659void Thr3() {
4660  MU.Lock();
4661  while(COND != 1)
4662    CV.Wait(&MU);
4663  MU.Unlock();
4664}
4665void 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}
4672void 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}
4681REGISTER_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
4688namespace test96 {
4689int     GLOB = 0;
4690
4691Mutex A, B, C;
4692
4693void Thread1() {
4694  MutexLock a(&A);
4695  MutexLock b(&B);
4696  GLOB++;
4697}
4698
4699void Thread2() {
4700  MutexLock b(&B);
4701  MutexLock c(&C);
4702  GLOB++;
4703}
4704
4705void Thread3() {
4706  MutexLock a(&A);
4707  MutexLock c(&C);
4708  GLOB++;
4709}
4710
4711void 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}
4720REGISTER_TEST(Run, 96);
4721}  // namespace test96
4722
4723// test97: This test shows false negative with --fast-mode=yes {{{1
4724namespace test97 {
4725const int HG_CACHELINE_SIZE = 64;
4726
4727Mutex MU;
4728
4729const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4730int array[ARRAY_SIZE];
4731int * 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
4737void Reader() {
4738  usleep(500000);
4739  CHECK(777 == *GLOB);
4740}
4741
4742void 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
4753REGISTER_TEST2(Run, 97, FEATURE)
4754}  // namespace test97
4755
4756// test98: Synchronization via read/write (or send/recv). {{{1
4757namespace 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//
4768int     GLOB = 0;
4769int fd_out = -1;
4770int fd_in  = -1;
4771
4772void 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
4779void 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
4787void 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}
4815REGISTER_TEST(Run, 98)
4816}  // namespace test98
4817
4818
4819// test99: TP. Unit test for a bug in LockWhen*. {{{1
4820namespace test99 {
4821
4822
4823bool GLOB = false;
4824Mutex mu;
4825
4826static 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
4835static void Thread2() {
4836  for (int i = 0; i < 100; i++) {
4837    mu.Lock();
4838    mu.Unlock();
4839    usleep(10000);
4840  }
4841}
4842
4843void Run() {
4844  printf("test99: regression test for LockWhen*\n");
4845  MyThreadArray t(Thread1, Thread2);
4846  t.Start();
4847  t.Join();
4848}
4849REGISTER_TEST(Run, 99);
4850}  // namespace test99
4851
4852
4853// test100: Test for initialization bit. {{{1
4854namespace test100 {
4855int     G1 = 0;
4856int     G2 = 0;
4857int     G3 = 0;
4858int     G4 = 0;
4859
4860void Creator() {
4861  G1 = 1; CHECK(G1);
4862  G2 = 1;
4863  G3 = 1; CHECK(G3);
4864  G4 = 1;
4865}
4866
4867void Worker1() {
4868  usleep(100000);
4869  CHECK(G1);
4870  CHECK(G2);
4871  G3 = 3;
4872  G4 = 3;
4873}
4874
4875void Worker2() {
4876
4877}
4878
4879
4880void 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}
4890REGISTER_TEST2(Run, 100, FEATURE|EXCLUDE_FROM_ALL)
4891}  // namespace test100
4892
4893
4894// test101: TN. Two signals and two waits. {{{1
4895namespace test101 {
4896Mutex MU;
4897CondVar CV;
4898int     GLOB = 0;
4899
4900int C1 = 0, C2 = 0;
4901
4902void 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
4920void 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
4937void Run() {
4938  printf("test101: negative\n");
4939  MyThreadArray t(Waiter, Signaller);
4940  t.Start();
4941  t.Join();
4942  printf("\tGLOB=%d\n", GLOB);
4943}
4944REGISTER_TEST(Run, 101)
4945}  // namespace test101
4946
4947// test102: --fast-mode=yes vs. --initialization-bit=yes {{{1
4948namespace test102 {
4949const int HG_CACHELINE_SIZE = 64;
4950
4951Mutex MU;
4952
4953const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4954int array[ARRAY_SIZE + 1];
4955int * 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
4961void Reader() {
4962  usleep(200000);
4963  CHECK(777 == GLOB[0]);
4964  usleep(400000);
4965  CHECK(777 == GLOB[1]);
4966}
4967
4968void 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
4982REGISTER_TEST2(Run, 102, FEATURE)
4983}  // namespace test102
4984
4985// test103: Access different memory locations with different LockSets {{{1
4986namespace test103 {
4987const int N_MUTEXES = 6;
4988const int LOCKSET_INTERSECTION_SIZE = 3;
4989
4990int data[1 << LOCKSET_INTERSECTION_SIZE] = {0};
4991Mutex MU[N_MUTEXES];
4992
4993inline int LS_to_idx (int ls) {
4994  return (ls >> (N_MUTEXES - LOCKSET_INTERSECTION_SIZE))
4995      & ((1 << LOCKSET_INTERSECTION_SIZE) - 1);
4996}
4997
4998void 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
5014void 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}
5020REGISTER_TEST2(Run, 103, FEATURE)
5021}  // namespace test103
5022
5023// test104: TP. Simple race (write vs write). Heap mem. {{{1
5024namespace test104 {
5025int     *GLOB = NULL;
5026void Worker() {
5027  *GLOB = 1;
5028}
5029
5030void Parent() {
5031  MyThread t(Worker);
5032  t.Start();
5033  usleep(100000);
5034  *GLOB = 2;
5035  t.Join();
5036}
5037void 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}
5047REGISTER_TEST(Run, 104);
5048}  // namespace test104
5049
5050
5051// test105: Checks how stack grows. {{{1
5052namespace test105 {
5053int     GLOB = 0;
5054
5055void 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
5063void 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
5072void 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}
5080REGISTER_TEST(Run, 105)
5081}  // namespace test105
5082
5083
5084// test106: TN. pthread_once. {{{1
5085namespace test106 {
5086int     *GLOB = NULL;
5087static pthread_once_t once = PTHREAD_ONCE_INIT;
5088void Init() {
5089  GLOB = new int;
5090  ANNOTATE_TRACE_MEMORY(GLOB);
5091  *GLOB = 777;
5092}
5093
5094void Worker0() {
5095  pthread_once(&once, Init);
5096}
5097void Worker1() {
5098  usleep(100000);
5099  pthread_once(&once, Init);
5100  CHECK(*GLOB == 777);
5101}
5102
5103
5104void 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}
5111REGISTER_TEST2(Run, 106, FEATURE)
5112}  // namespace test106
5113
5114
5115// test107: Test for ANNOTATE_EXPECT_RACE {{{1
5116namespace test107 {
5117int     GLOB = 0;
5118void 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}
5123REGISTER_TEST2(Run, 107, FEATURE|EXCLUDE_FROM_ALL)
5124}  // namespace test107
5125
5126
5127// test108: TN. initialization of static object. {{{1
5128namespace 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.
5137class Foo {
5138 public:
5139  Foo() {
5140    ANNOTATE_TRACE_MEMORY(&a_);
5141    a_ = 42;
5142  }
5143  void Check() const { CHECK(a_ == 42); }
5144 private:
5145  int a_;
5146};
5147
5148const Foo *GetFoo() {
5149  static const Foo *foo = new Foo();
5150  return foo;
5151}
5152void Worker0() {
5153  GetFoo();
5154}
5155
5156void Worker() {
5157  usleep(200000);
5158  const Foo *foo = GetFoo();
5159  foo->Check();
5160}
5161
5162
5163void Run() {
5164  printf("test108: negative, initialization of static object\n");
5165  MyThreadArray t(Worker0, Worker, Worker);
5166  t.Start();
5167  t.Join();
5168}
5169REGISTER_TEST2(Run, 108, FEATURE)
5170}  // namespace test108
5171
5172
5173// test109: TN. Checking happens before between parent and child threads. {{{1
5174namespace test109 {
5175// Check that the detector correctly connects
5176//   pthread_create with the new thread
5177// and
5178//   thread exit with pthread_join
5179const int N = 32;
5180static int GLOB[N];
5181
5182void 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
5189void 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}
5211REGISTER_TEST(Run, 109)
5212}  // namespace test109
5213
5214
5215// test110: TP. Simple races with stack, global and heap objects. {{{1
5216namespace test110 {
5217int        GLOB = 0;
5218static int STATIC;
5219
5220int       *STACK = 0;
5221
5222int       *MALLOC;
5223int       *CALLOC;
5224int       *REALLOC;
5225int       *VALLOC;
5226int       *PVALLOC;
5227int       *MEMALIGN;
5228union pi_pv_union { int* pi; void* pv; } POSIX_MEMALIGN;
5229int       *MMAP;
5230
5231int       *NEW;
5232int       *NEW_ARR;
5233
5234void 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}
5252void 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}
5317REGISTER_TEST(Run, 110)
5318}  // namespace test110
5319
5320
5321// test111: TN. Unit test for a bug related to stack handling. {{{1
5322namespace test111 {
5323char     *GLOB = 0;
5324bool COND = false;
5325Mutex mu;
5326const int N = 3000;
5327
5328void write_to_p(char *p, int val) {
5329  for (int i = 0; i < N; i++)
5330    p[i] = val;
5331}
5332
5333static bool ArgIsTrue(bool *arg) {
5334//  printf("ArgIsTrue: %d tid=%d\n", *arg, (int)pthread_self());
5335  return *arg == true;
5336}
5337
5338void f1() {
5339  char some_stack[N];
5340  write_to_p(some_stack, 1);
5341  mu.LockWhen(Condition(&ArgIsTrue, &COND));
5342  mu.Unlock();
5343}
5344
5345void 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
5352void f0() { f2(); }
5353
5354void Worker1() {
5355  f0();
5356  f1();
5357  f2();
5358}
5359
5360void Worker2() {
5361  usleep(100000);
5362  mu.Lock();
5363  COND = true;
5364  mu.Unlock();
5365}
5366
5367void 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}
5375REGISTER_TEST2(Run, 111, FEATURE)
5376}  // namespace test111
5377
5378// test112: STAB. Test for ANNOTATE_PUBLISH_MEMORY_RANGE{{{1
5379namespace test112 {
5380char     *GLOB = 0;
5381const int N = 64 * 5;
5382Mutex mu;
5383bool ready = false; // under mu
5384int beg, end; // under mu
5385
5386Mutex mu1;
5387
5388void 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
5408void 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
5430void 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}
5454REGISTER_TEST2(Run, 112, STABILITY)
5455}  // namespace test112
5456
5457
5458// test113: PERF. A lot of lock/unlock calls. Many locks {{{1
5459namespace    test113 {
5460const int kNumIter = 100000;
5461const int kNumLocks = 7;
5462Mutex   MU[kNumLocks];
5463void 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}
5474REGISTER_TEST(Run, 113)
5475}  // namespace test113
5476
5477
5478// test114: STAB. Recursive lock. {{{1
5479namespace    test114 {
5480int Bar() {
5481  static int bar = 1;
5482  return bar;
5483}
5484int Foo() {
5485  static int foo = Bar();
5486  return foo;
5487}
5488void Worker() {
5489  static int x = Foo();
5490  CHECK(x == 1);
5491}
5492void Run() {
5493  printf("test114: stab\n");
5494  MyThreadArray t(Worker, Worker);
5495  t.Start();
5496  t.Join();
5497}
5498REGISTER_TEST(Run, 114)
5499}  // namespace test114
5500
5501
5502// test115: TN. sem_open. {{{1
5503namespace    test115 {
5504int tid = 0;
5505Mutex mu;
5506const char *kSemName = "drt-test-sem";
5507
5508int GLOB = 0;
5509
5510sem_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
5519void 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
5540void 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}
5557REGISTER_TEST(Run, 115)
5558}  // namespace test115
5559
5560
5561// test116: TN. some operations with string<> objects. {{{1
5562namespace test116 {
5563
5564void 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
5591void Run() {
5592  printf("test116: negative (strings)\n");
5593  MyThreadArray t(Worker, Worker, Worker);
5594  t.Start();
5595  t.Join();
5596}
5597REGISTER_TEST2(Run, 116, FEATURE|EXCLUDE_FROM_ALL)
5598}  // namespace test116
5599
5600// test117: TN. Many calls to function-scope static init. {{{1
5601namespace test117 {
5602const int N = 50;
5603
5604int Foo() {
5605  usleep(20000);
5606  return 1;
5607}
5608
5609void Worker(void *a) {
5610  static int foo = Foo();
5611  CHECK(foo == 1);
5612}
5613
5614void 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}
5628REGISTER_TEST(Run, 117)
5629}  // namespace test117
5630
5631
5632
5633// test118 PERF: One signal, multiple waits. {{{1
5634namespace   test118 {
5635int     GLOB = 0;
5636const int kNumIter = 2000000;
5637void Signaller() {
5638  usleep(50000);
5639  ANNOTATE_CONDVAR_SIGNAL(&GLOB);
5640}
5641void Waiter() {
5642  for (int i = 0; i < kNumIter; i++) {
5643    ANNOTATE_CONDVAR_WAIT(&GLOB);
5644    if (i == kNumIter / 2)
5645      usleep(100000);
5646  }
5647}
5648void 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}
5655REGISTER_TEST(Run, 118)
5656}  // namespace test118
5657
5658
5659// test119: TP. Testing that malloc does not introduce any HB arc. {{{1
5660namespace test119 {
5661int     GLOB = 0;
5662void Worker1() {
5663  GLOB = 1;
5664  free(malloc(123));
5665}
5666void Worker2() {
5667  usleep(100000);
5668  free(malloc(345));
5669  GLOB = 2;
5670}
5671void 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}
5681REGISTER_TEST(Run, 119)
5682}  // namespace test119
5683
5684
5685// test120: TP. Thread1: write then read. Thread2: read. {{{1
5686namespace test120 {
5687int     GLOB = 0;
5688
5689void Thread1() {
5690  GLOB = 1;           // write
5691  CHECK(GLOB);        // read
5692}
5693
5694void Thread2() {
5695  usleep(100000);
5696  CHECK(GLOB >= 0);   // read
5697}
5698
5699void 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}
5709REGISTER_TEST(Run, 120)
5710}  // namespace test120
5711
5712
5713// test121: TP. Example of double-checked-locking  {{{1
5714namespace test121 {
5715struct Foo {
5716  uintptr_t a, b[15];
5717} __attribute__ ((aligned (64)));
5718
5719static Mutex mu;
5720static Foo  *foo;
5721
5722void 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
5735void UseMe() {
5736  InitMe();
5737  CHECK(foo && foo->a == 42);
5738}
5739
5740void Worker1() { UseMe(); }
5741void Worker2() { UseMe(); }
5742void Worker3() { UseMe(); }
5743
5744
5745void 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}
5753REGISTER_TEST(Run, 121)
5754}  // namespace test121
5755
5756// test122 TP: Simple test with RWLock {{{1
5757namespace  test122 {
5758int     VAR1 = 0;
5759int     VAR2 = 0;
5760RWLock mu;
5761
5762void WriteWhileHoldingReaderLock(int *p) {
5763  usleep(100000);
5764  ReaderLockScoped lock(&mu);  // Reader lock for writing. -- bug.
5765  (*p)++;
5766}
5767
5768void CorrectWrite(int *p) {
5769  WriterLockScoped lock(&mu);
5770  (*p)++;
5771}
5772
5773void Thread1() { WriteWhileHoldingReaderLock(&VAR1); }
5774void Thread2() { CorrectWrite(&VAR1); }
5775void Thread3() { CorrectWrite(&VAR2); }
5776void Thread4() { WriteWhileHoldingReaderLock(&VAR2); }
5777
5778
5779void 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}
5793REGISTER_TEST(Run, 122)
5794}  // namespace test122
5795
5796
5797// test123 TP: accesses of different sizes. {{{1
5798namespace test123 {
5799
5800union uint_union {
5801  uint64_t u64[1];
5802  uint32_t u32[2];
5803  uint16_t u16[4];
5804  uint8_t  u8[8];
5805};
5806
5807uint_union MEM[8];
5808
5809// Q. Hey dude, why so many functions?
5810// A. I need different stack traces for different accesses.
5811
5812void Wr64_0() { MEM[0].u64[0] = 1; }
5813void Wr64_1() { MEM[1].u64[0] = 1; }
5814void Wr64_2() { MEM[2].u64[0] = 1; }
5815void Wr64_3() { MEM[3].u64[0] = 1; }
5816void Wr64_4() { MEM[4].u64[0] = 1; }
5817void Wr64_5() { MEM[5].u64[0] = 1; }
5818void Wr64_6() { MEM[6].u64[0] = 1; }
5819void Wr64_7() { MEM[7].u64[0] = 1; }
5820
5821void Wr32_0() { MEM[0].u32[0] = 1; }
5822void Wr32_1() { MEM[1].u32[1] = 1; }
5823void Wr32_2() { MEM[2].u32[0] = 1; }
5824void Wr32_3() { MEM[3].u32[1] = 1; }
5825void Wr32_4() { MEM[4].u32[0] = 1; }
5826void Wr32_5() { MEM[5].u32[1] = 1; }
5827void Wr32_6() { MEM[6].u32[0] = 1; }
5828void Wr32_7() { MEM[7].u32[1] = 1; }
5829
5830void Wr16_0() { MEM[0].u16[0] = 1; }
5831void Wr16_1() { MEM[1].u16[1] = 1; }
5832void Wr16_2() { MEM[2].u16[2] = 1; }
5833void Wr16_3() { MEM[3].u16[3] = 1; }
5834void Wr16_4() { MEM[4].u16[0] = 1; }
5835void Wr16_5() { MEM[5].u16[1] = 1; }
5836void Wr16_6() { MEM[6].u16[2] = 1; }
5837void Wr16_7() { MEM[7].u16[3] = 1; }
5838
5839void Wr8_0() { MEM[0].u8[0] = 1; }
5840void Wr8_1() { MEM[1].u8[1] = 1; }
5841void Wr8_2() { MEM[2].u8[2] = 1; }
5842void Wr8_3() { MEM[3].u8[3] = 1; }
5843void Wr8_4() { MEM[4].u8[4] = 1; }
5844void Wr8_5() { MEM[5].u8[5] = 1; }
5845void Wr8_6() { MEM[6].u8[6] = 1; }
5846void Wr8_7() { MEM[7].u8[7] = 1; }
5847
5848void 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
5859void 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
5870void 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
5881void 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
5892void W00() { WriteAll64(); }
5893void W01() { WriteAll64(); }
5894void W02() { WriteAll64(); }
5895
5896void W10() { WriteAll32(); }
5897void W11() { WriteAll32(); }
5898void W12() { WriteAll32(); }
5899
5900void W20() { WriteAll16(); }
5901void W21() { WriteAll16(); }
5902void W22() { WriteAll16(); }
5903
5904void W30() { WriteAll8(); }
5905void W31() { WriteAll8(); }
5906void W32() { WriteAll8(); }
5907
5908typedef void (*F)(void);
5909
5910void 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
5925void 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}
5935REGISTER_TEST2(Run, 123, FEATURE|EXCLUDE_FROM_ALL)
5936}  // namespace test123
5937
5938
5939// test124: What happens if we delete an unlocked lock? {{{1
5940namespace test124 {
5941// This test does not worg with pthreads (you can't call
5942// pthread_mutex_destroy on a locked lock).
5943int     GLOB = 0;
5944const int N = 1000;
5945void 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
5955void 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}
5962REGISTER_TEST2(Run, 124, FEATURE|EXCLUDE_FROM_ALL)
5963}  // namespace test124
5964
5965
5966// test125 TN: Backwards lock (annotated). {{{1
5967namespace 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
5978const int n_threads = 3;
5979RWLock   mu;
5980int     GLOB[n_threads];
5981
5982int adder_num; // updated atomically.
5983
5984void Adder() {
5985  int my_num = AtomicIncrement(&adder_num, 1);
5986
5987  ReaderLockScoped lock(&mu);
5988  GLOB[my_num]++;
5989}
5990
5991void 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
6002void 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}
6023REGISTER_TEST(Run, 125)
6024}  // namespace test125
6025
6026// test126 TN: test for BlockingCounter {{{1
6027namespace  test126 {
6028BlockingCounter *blocking_counter;
6029int     GLOB = 0;
6030void Worker() {
6031  CHECK(blocking_counter);
6032  CHECK(GLOB == 0);
6033  blocking_counter->DecrementCount();
6034}
6035void 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}
6045REGISTER_TEST(Run, 126)
6046}  // namespace test126
6047
6048
6049// test127. Bad code: unlocking a mutex locked by another thread. {{{1
6050namespace test127 {
6051Mutex mu;
6052void Thread1() {
6053  mu.Lock();
6054}
6055void Thread2() {
6056  usleep(100000);
6057  mu.Unlock();
6058}
6059void Run() {
6060  printf("test127: unlocking a mutex locked by another thread.\n");
6061  MyThreadArray t(Thread1, Thread2);
6062  t.Start();
6063  t.Join();
6064}
6065REGISTER_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.
6070namespace test128 {
6071Mutex mu;
6072int GLOB = 0;
6073void Worker() {
6074  usleep(100000);
6075  mu.Lock();
6076  GLOB++;
6077  mu.Unlock();
6078}
6079void ThisFunctionShouldBeSuppressed() {
6080  GLOB++;
6081}
6082void Run() {
6083  printf("test128: Suppressed code in concurrent accesses.\n");
6084  MyThreadArray t(Worker, ThisFunctionShouldBeSuppressed);
6085  t.Start();
6086  t.Join();
6087}
6088REGISTER_TEST2(Run, 128, FEATURE | EXCLUDE_FROM_ALL)
6089}  // namespace test128
6090
6091// test129: TN. Synchronization via ReaderLockWhen(). {{{1
6092namespace test129 {
6093int     GLOB = 0;
6094Mutex   MU;
6095bool WeirdCondition(int* param) {
6096  *param = GLOB;  // a write into Waiter's memory
6097  return GLOB > 0;
6098}
6099void Waiter() {
6100  int param = 0;
6101  MU.ReaderLockWhen(Condition(WeirdCondition, &param));
6102  MU.ReaderUnlock();
6103  CHECK(GLOB > 0);
6104  CHECK(param > 0);
6105}
6106void Waker() {
6107  usleep(100000);  // Make sure the waiter blocks.
6108  MU.Lock();
6109  GLOB++;
6110  MU.Unlock();     // calls ANNOTATE_CONDVAR_SIGNAL;
6111}
6112void 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}
6120REGISTER_TEST2(Run, 129, FEATURE);
6121}  // namespace test129
6122
6123// test130: TN. Per-thread. {{{1
6124namespace 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
6141static __thread int per_thread_global[10] = {0};
6142
6143void RealWorker() {  // Touch per_thread_global.
6144  per_thread_global[1]++;
6145  errno++;
6146}
6147
6148void Worker() {  // Spawn few threads that touch per_thread_global.
6149  MyThreadArray t(RealWorker, RealWorker);
6150  t.Start();
6151  t.Join();
6152}
6153void Worker0() { sleep(0); Worker(); }
6154void Worker1() { sleep(1); Worker(); }
6155void Worker2() { sleep(2); Worker(); }
6156void Worker3() { sleep(3); Worker(); }
6157
6158void 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}
6165REGISTER_TEST(Run, 130)
6166#endif // NO_TLS
6167}  // namespace test130
6168
6169
6170// test131: TN. Stack. {{{1
6171namespace test131 {
6172// Same as test130, but for stack.
6173
6174void RealWorker() {  // Touch stack.
6175  int stack_var = 0;
6176  stack_var++;
6177}
6178
6179void Worker() {  // Spawn few threads that touch stack.
6180  MyThreadArray t(RealWorker, RealWorker);
6181  t.Start();
6182  t.Join();
6183}
6184void Worker0() { sleep(0); Worker(); }
6185void Worker1() { sleep(1); Worker(); }
6186void Worker2() { sleep(2); Worker(); }
6187void Worker3() { sleep(3); Worker(); }
6188
6189void Run() {
6190  printf("test131: stack\n");
6191  MyThreadArray t(Worker0, Worker1, Worker2, Worker3);
6192  t.Start();
6193  t.Join();
6194}
6195REGISTER_TEST(Run, 131)
6196}  // namespace test131
6197
6198
6199// test132: TP. Simple race (write vs write). Works in fast-mode. {{{1
6200namespace test132 {
6201int     GLOB = 0;
6202void Worker() { GLOB = 1; }
6203
6204void 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
6215void Run() {
6216  Run1();
6217}
6218REGISTER_TEST(Run, 132);
6219}  // namespace test132
6220
6221
6222// test133: TP. Simple race (write vs write). Works in fast mode. {{{1
6223namespace test133 {
6224// Same as test132, but everything is run from a separate thread spawned from
6225// the main thread.
6226int     GLOB = 0;
6227void Worker() { GLOB = 1; }
6228
6229void 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}
6239void Run() {
6240  MyThread t(Run1);
6241  t.Start();
6242  t.Join();
6243}
6244REGISTER_TEST(Run, 133);
6245}  // namespace test133
6246
6247
6248// test134 TN. Swap. Variant of test79. {{{1
6249namespace test134 {
6250#if 0
6251typedef __gnu_cxx::hash_map<int, int> map_t;
6252#else
6253typedef std::map<int, int> map_t;
6254#endif
6255map_t   map;
6256Mutex   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.
6268void 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
6278void Worker() {
6279  MutexLock lock(&mu);
6280  ANNOTATE_HAPPENS_AFTER(&map);
6281  map[1]++;
6282  ANNOTATE_HAPPENS_BEFORE(&map);
6283}
6284
6285void 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}
6293REGISTER_TEST(Run, 134)
6294}  // namespace test134
6295
6296// test135 TN. Swap. Variant of test79. {{{1
6297namespace test135 {
6298
6299void 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
6309void Worker() {
6310  MyThreadArray t(SubWorker, SubWorker, SubWorker, SubWorker);
6311  t.Start();
6312  t.Join();
6313}
6314
6315void Run() {
6316  printf("test135: negative (mmap)\n");
6317  MyThreadArray t(Worker, Worker, Worker, Worker);
6318  t.Start();
6319  t.Join();
6320}
6321REGISTER_TEST(Run, 135)
6322}  // namespace test135
6323
6324// test136. Unlock twice. {{{1
6325namespace test136 {
6326void 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
6343REGISTER_TEST(Run, 136)
6344}  // namespace test136
6345
6346// test137 TP. Races on stack variables. {{{1
6347namespace test137 {
6348int GLOB = 0;
6349ProducerConsumerQueue q(10);
6350
6351void 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
6362void 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
6372REGISTER_TEST2(Run, 137, FEATURE | EXCLUDE_FROM_ALL)
6373}  // namespace test137
6374
6375// test138 FN. Two closures hit the same thread in ThreadPool. {{{1
6376namespace test138 {
6377int GLOB = 0;
6378
6379void Worker() {
6380  usleep(100000);
6381  GLOB++;
6382}
6383
6384void 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
6400REGISTER_TEST2(Run, 138, FEATURE)
6401}  // namespace test138
6402
6403// test139: FN. A true race hidden by reference counting annotation. {{{1
6404namespace test139 {
6405int GLOB = 0;
6406RefCountedClass *obj;
6407
6408void Worker1() {
6409  GLOB++;  // First access.
6410  obj->Unref();
6411}
6412
6413void Worker2() {
6414  usleep(100000);
6415  obj->Unref();
6416  GLOB++;  // Second access.
6417}
6418
6419void 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
6432REGISTER_TEST2(Run, 139, FEATURE)
6433}  // namespace test139
6434
6435// test140 TN. Swap. Variant of test79 and test134. {{{1
6436namespace test140 {
6437#if 0
6438typedef __gnu_cxx::hash_map<int, int> Container;
6439#else
6440typedef std::map<int,int>             Container;
6441#endif
6442Mutex mu;
6443static 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.
6460void 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
6476void 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
6489void Run() {
6490  printf("test140: negative (swap) %p\n", &container);
6491  MyThreadArray t(Worker, Worker, Swapper, Worker, Worker);
6492  t.Start();
6493  t.Join();
6494}
6495REGISTER_TEST(Run, 140)
6496}  // namespace test140
6497
6498// test141 FP. unlink/fopen, rmdir/opendir. {{{1
6499namespace test141 {
6500int GLOB1 = 0,
6501    GLOB2 = 0;
6502char *dir_name = NULL,
6503     *filename = NULL;
6504
6505void 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
6514void 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
6524void 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
6533void 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
6543void 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}
6568REGISTER_TEST(Run, 141)
6569}  // namespace test141
6570
6571
6572// Simple FIFO queue annotated with PCQ annotations. {{{1
6573class FifoMessageQueue {
6574 public:
6575  FifoMessageQueue() { ANNOTATE_PCQ_CREATE(this); }
6576  ~FifoMessageQueue() { ANNOTATE_PCQ_DESTROY(this); }
6577  // Send a message. 'message' should be positive.
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.
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
6601namespace 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
6606const int N = 1000;
6607int array[N+1];
6608
6609FifoMessageQueue q;
6610
6611void Putter() {
6612  for (int i = 1; i <= N; i++) {
6613    array[i] = i*i;
6614    q.Put(i);
6615    usleep(1000);
6616  }
6617}
6618
6619void 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
6633void Run() {
6634  printf("test142: tests PCQ annotations\n");
6635  MyThreadArray t(Putter, Getter, Getter);
6636  t.Start();
6637  t.Join();
6638}
6639REGISTER_TEST(Run, 142)
6640}  // namespace test142
6641
6642
6643// test143: TP. Check PCQ_* annotations. {{{1
6644namespace 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.
6651int     GLOB = 0;
6652
6653FifoMessageQueue q;
6654
6655void Putter() {
6656  GLOB = 1;
6657  q.Put(1);
6658}
6659
6660void Getter() {
6661  usleep(10000);
6662  q.Get();
6663  CHECK(GLOB == 1);  // Race here
6664}
6665
6666void 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}
6676REGISTER_TEST(Run, 143);
6677}  // namespace test143
6678
6679
6680
6681
6682// test300: {{{1
6683namespace test300 {
6684int     GLOB = 0;
6685void Run() {
6686}
6687REGISTER_TEST2(Run, 300, RACE_DEMO)
6688}  // namespace test300
6689
6690// test301: Simple race.  {{{1
6691namespace test301 {
6692Mutex mu1;  // This Mutex guards var.
6693Mutex mu2;  // This Mutex is not related to var.
6694int   var;  // GUARDED_BY(mu1)
6695
6696void Thread1() {  // Runs in thread named 'test-thread-1'.
6697  MutexLock lock(&mu1);  // Correct Mutex.
6698  var = 1;
6699}
6700
6701void Thread2() {  // Runs in thread named 'test-thread-2'.
6702  MutexLock lock(&mu2);  // Wrong Mutex.
6703  var = 2;
6704}
6705
6706void 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}
6716REGISTER_TEST2(Run, 301, RACE_DEMO)
6717}  // namespace test301
6718
6719// test302: Complex race which happens at least twice.  {{{1
6720namespace test302 {
6721// In this test we have many different accesses to GLOB and only one access
6722// is not synchronized properly.
6723int     GLOB = 0;
6724
6725Mutex MU1;
6726Mutex MU2;
6727void 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
6753void 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}
6760REGISTER_TEST2(Run, 302, RACE_DEMO)
6761}  // namespace test302
6762
6763
6764// test303: Need to trace the memory to understand the report. {{{1
6765namespace test303 {
6766int     GLOB = 0;
6767
6768Mutex MU;
6769void Worker1() { CHECK(GLOB >= 0); }
6770void Worker2() { MU.Lock(); GLOB=1;  MU.Unlock();}
6771
6772void 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}
6779REGISTER_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
6785namespace test304 {
6786string *STR;
6787Mutex   MU;
6788
6789void Worker1() {
6790  sleep(0);
6791  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6792  MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
6793}
6794void Worker2() {
6795  sleep(1);
6796  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6797  CHECK(STR->length() >= 4); // Unprotected!
6798}
6799void Worker3() {
6800  sleep(2);
6801  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6802  MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
6803}
6804void Worker4() {
6805  sleep(3);
6806  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6807  MU.Lock(); *STR += " + a very very long string"; MU.Unlock();
6808}
6809
6810void 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}
6820REGISTER_TEST2(Run, 304, RACE_DEMO)
6821}  // namespace test304
6822
6823
6824
6825// test305: A bit more tricky: two locks used inconsistenly. {{{1
6826namespace test305 {
6827int     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.
6838Mutex MU1;
6839Mutex MU2;
6840void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
6841void Worker2() { MU1.Lock();             GLOB=2;               MU1.Unlock(); }
6842void Worker3() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
6843void Worker4() {             MU2.Lock(); GLOB=4; MU2.Unlock();               }
6844
6845void 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}
6855REGISTER_TEST2(Run, 305, RACE_DEMO)
6856}  // namespace test305
6857
6858// test306: Two locks are used to protect a var.  {{{1
6859namespace test306 {
6860int     GLOB = 0;
6861// Thread1 and Thread2 access the var under two locks.
6862// Thread3 uses no locks.
6863
6864Mutex MU1;
6865Mutex MU2;
6866void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
6867void Worker2() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
6868void Worker3() {                         GLOB=4;               }
6869
6870void 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}
6879REGISTER_TEST2(Run, 306, RACE_DEMO)
6880}  // namespace test306
6881
6882// test307: Simple race, code with control flow  {{{1
6883namespace test307 {
6884int     *GLOB = 0;
6885volatile /*to fake the compiler*/ bool some_condition = true;
6886
6887
6888void SomeFunc() { }
6889
6890int 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
6905void Worker1() { FunctionWithControlFlow(); }
6906void Worker2() { Worker1(); }
6907void Worker3() { Worker2(); }
6908void Worker4() { Worker3(); }
6909
6910void 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}
6918REGISTER_TEST2(Run, 307, RACE_DEMO)
6919}  // namespace test307
6920
6921// test308: Example of double-checked-locking  {{{1
6922namespace test308 {
6923struct Foo {
6924  int a;
6925};
6926
6927static int   is_inited = 0;
6928static Mutex lock;
6929static Foo  *foo;
6930
6931void 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
6943void UseMe() {
6944  InitMe();
6945  CHECK(foo && foo->a == 42);
6946}
6947
6948void Worker1() { UseMe(); }
6949void Worker2() { UseMe(); }
6950void Worker3() { UseMe(); }
6951
6952
6953void 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}
6960REGISTER_TEST2(Run, 308, RACE_DEMO)
6961}  // namespace test308
6962
6963// test309: Simple race on an STL object.  {{{1
6964namespace test309 {
6965string  GLOB;
6966
6967void Worker1() {
6968  GLOB="Thread1";
6969}
6970void Worker2() {
6971  usleep(100000);
6972  GLOB="Booooooooooo";
6973}
6974
6975void 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}
6982REGISTER_TEST2(Run, 309, RACE_DEMO)
6983}  // namespace test309
6984
6985// test310: One more simple race.  {{{1
6986namespace test310 {
6987int     *PTR = NULL;  // GUARDED_BY(mu1)
6988
6989Mutex mu1;  // Protects PTR.
6990Mutex mu2;  // Unrelated to PTR.
6991Mutex mu3;  // Unrelated to PTR.
6992
6993void Writer1() {
6994  MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
6995  MutexLock lock1(&mu1);  // Protect PTR.
6996  *PTR = 1;
6997}
6998
6999void 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
7009void 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.
7015void DoWrite1() { Writer1();  }
7016void Thread1()  { DoWrite1(); }
7017
7018void DoWrite2() { Writer2();  }
7019void Thread2()  { DoWrite2(); }
7020
7021void DoRead()  { Reader();  }
7022void Thread3() { DoRead();  }
7023
7024void 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}
7041REGISTER_TEST2(Run, 310, RACE_DEMO)
7042}  // namespace test310
7043
7044// test311: Yet another simple race.  {{{1
7045namespace test311 {
7046int     *PTR = NULL;  // GUARDED_BY(mu1)
7047
7048Mutex mu1;  // Protects PTR.
7049Mutex mu2;  // Unrelated to PTR.
7050Mutex mu3;  // Unrelated to PTR.
7051
7052void GoodWriter1() {
7053  MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
7054  MutexLock lock1(&mu1);  // Protect PTR.
7055  *PTR = 1;
7056}
7057
7058void GoodWriter2() {
7059  MutexLock lock2(&mu2);  // This lock is unrelated to PTR.
7060  MutexLock lock1(&mu1);  // Protect PTR.
7061  *PTR = 2;
7062}
7063
7064void GoodReader() {
7065  MutexLock lock1(&mu1);  // Protect PTR.
7066  CHECK(*PTR >= 0);
7067}
7068
7069void BuggyWriter() {
7070  MutexLock lock2(&mu2);  // Wrong mutex!
7071  *PTR = 3;
7072}
7073
7074// Some functions to make the stack trace non-trivial.
7075void DoWrite1() { GoodWriter1();  }
7076void Thread1()  { DoWrite1(); }
7077
7078void DoWrite2() { GoodWriter2();  }
7079void Thread2()  { DoWrite2(); }
7080
7081void DoGoodRead()  { GoodReader();  }
7082void Thread3()     { DoGoodRead();  }
7083
7084void DoBadWrite()  { BuggyWriter(); }
7085void Thread4()     { DoBadWrite(); }
7086
7087void 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}
7109REGISTER_TEST2(Run, 311, RACE_DEMO)
7110}  // namespace test311
7111
7112// test312: A test with a very deep stack. {{{1
7113namespace test312 {
7114int     GLOB = 0;
7115void RaceyWrite() { GLOB++; }
7116void Func1() { RaceyWrite(); }
7117void Func2() { Func1(); }
7118void Func3() { Func2(); }
7119void Func4() { Func3(); }
7120void Func5() { Func4(); }
7121void Func6() { Func5(); }
7122void Func7() { Func6(); }
7123void Func8() { Func7(); }
7124void Func9() { Func8(); }
7125void Func10() { Func9(); }
7126void Func11() { Func10(); }
7127void Func12() { Func11(); }
7128void Func13() { Func12(); }
7129void Func14() { Func13(); }
7130void Func15() { Func14(); }
7131void Func16() { Func15(); }
7132void Func17() { Func16(); }
7133void Func18() { Func17(); }
7134void Func19() { Func18(); }
7135void Worker() { Func19(); }
7136void Run() {
7137  printf("test312: simple race with deep stack.\n");
7138  MyThreadArray t(Worker, Worker, Worker);
7139  t.Start();
7140  t.Join();
7141}
7142REGISTER_TEST2(Run, 312, RACE_DEMO)
7143}  // namespace test312
7144
7145// test313 TP: test for thread graph output {{{1
7146namespace  test313 {
7147BlockingCounter *blocking_counter;
7148int     GLOB = 0;
7149
7150// Worker(N) will do 2^N increments of GLOB, each increment in a separate thread
7151void 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}
7162void Run() {
7163  printf("test313: positive\n");
7164  Worker(4);
7165  printf("\tGLOB=%d\n", GLOB);
7166}
7167REGISTER_TEST2(Run, 313, RACE_DEMO)
7168}  // namespace test313
7169
7170
7171
7172// test400: Demo of a simple false positive. {{{1
7173namespace test400 {
7174static Mutex mu;
7175static vector<int> *vec; // GUARDED_BY(mu);
7176
7177void InitAllBeforeStartingThreads() {
7178  vec = new vector<int>;
7179  vec->push_back(1);
7180  vec->push_back(2);
7181}
7182
7183void Thread1() {
7184  MutexLock lock(&mu);
7185  vec->pop_back();
7186}
7187
7188void Thread2() {
7189  MutexLock lock(&mu);
7190  vec->pop_back();
7191}
7192
7193//---- Sub-optimal code ---------
7194size_t NumberOfElementsLeft() {
7195  MutexLock lock(&mu);
7196  return vec->size();
7197}
7198
7199void 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
7216bool NoElementsLeft(vector<int> *v) {
7217  return v->empty();
7218}
7219
7220void 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
7230void Run() {
7231  MyThreadArray t(Thread1, Thread2);
7232  InitAllBeforeStartingThreads();
7233  t.Start();
7234  WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly();
7235//  WaitForAllThreadsToFinish_Good();
7236  t.Join();
7237}
7238REGISTER_TEST2(Run, 400, RACE_DEMO)
7239}  // namespace test400
7240
7241// test401: Demo of false positive caused by reference counting. {{{1
7242namespace 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
7247static vector<int> *vec;
7248static int ref_count;
7249
7250void 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.
7257int DecRef() {
7258  return AtomicIncrement(&ref_count, -1);
7259}
7260
7261// Correct and friendly to race detectors.
7262int 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
7271void 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
7281void Run() {
7282  MyThreadArray t(ThreadWorker, ThreadWorker, ThreadWorker);
7283  InitAllBeforeStartingThreads(3 /*number of threads*/);
7284  t.Start();
7285  t.Join();
7286  CHECK(vec == 0);
7287}
7288REGISTER_TEST2(Run, 401, RACE_DEMO)
7289}  // namespace test401
7290
7291// test501: Manually call PRINT_* annotations {{{1
7292namespace test501 {
7293int  COUNTER = 0;
7294int     GLOB = 0;
7295Mutex muCounter, muGlob[65];
7296
7297void 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
7311void Worker_1() {
7312   MyThreadArray ta (Worker, Worker, Worker, Worker);
7313   ta.Start();
7314   usleep(500000);
7315   ta.Join ();
7316}
7317
7318void Worker_2() {
7319   MyThreadArray ta (Worker_1, Worker_1, Worker_1, Worker_1);
7320   ta.Start();
7321   usleep(300000);
7322   ta.Join ();
7323}
7324
7325void 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
7336REGISTER_TEST2(Run, 501, FEATURE | EXCLUDE_FROM_ALL)
7337}  // namespace test501
7338
7339// test502: produce lots of segments without cross-thread relations {{{1
7340namespace 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
7351Mutex MU;
7352int     GLOB = 0;
7353
7354void TP() {
7355   for (int i = 0; i < 750000; i++) {
7356      MU.Lock();
7357      GLOB++;
7358      MU.Unlock();
7359   }
7360}
7361
7362void 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
7370REGISTER_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%
7376namespace test503 {
7377
7378//  |- |  |  |  |  |
7379//  | \|  |  |  |  |
7380//  |  |- |  |  |  |
7381//  |  | \|  |  |  |
7382//  |  |  |- |  |  |
7383//  |  |  | \|  |  |
7384//  |  |  |  |- |  |
7385//  |  |  |  | \|  |
7386//  |  |  |  |  |- |
7387//  |  |  |  |  | \|
7388//  |  |  |  |  |  |----
7389//->|  |  |  |  |  |
7390//  |- |  |  |  |  |
7391//  | \|  |  |  |  |
7392//     ...
7393
7394const int N_threads = 32;
7395const int ARRAY_SIZE = 128;
7396int       GLOB[ARRAY_SIZE];
7397ProducerConsumerQueue *Q[N_threads];
7398int GLOB_limit = 100000;
7399int count = -1;
7400
7401void 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
7420void 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
7438REGISTER_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
7443namespace test504 {
7444
7445const 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
7454const int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
7455          ITERATIONS = 30;
7456int array[ARRAY_SIZE];
7457
7458int count = 0;
7459Mutex count_mu;
7460
7461void 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
7477void Run() {
7478   printf("test504: force massive CacheLineZ fetch-wback\n");
7479   MyThreadArray t(Worker, Worker);
7480   t.Start();
7481   t.Join();
7482}
7483
7484REGISTER_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)
7490namespace test505 {
7491
7492const 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
7497const int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
7498          ITERATIONS = 3;
7499int64_t array[ARRAY_SIZE];
7500
7501int count = 0;
7502Mutex count_mu;
7503
7504void 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
7528void Run() {
7529   printf("test505: force massive CacheLineF fetch-wback\n");
7530   MyThreadArray t(Worker, Worker);
7531   t.Start();
7532   t.Join();
7533}
7534
7535REGISTER_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
7542namespace test506 {
7543#ifndef NO_BARRIER
7544// Same as test17 but uses Barrier class (pthread_barrier_t).
7545int     GLOB = 0;
7546const int N_threads = 64,
7547          ITERATIONS = 1000;
7548Barrier *barrier[ITERATIONS];
7549Mutex   MU;
7550
7551void Worker() {
7552  for (int i = 0; i < ITERATIONS; i++) {
7553     MU.Lock();
7554     GLOB++;
7555     MU.Unlock();
7556     barrier[i]->Block();
7557  }
7558}
7559void 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}
7576REGISTER_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
7582namespace test507 {
7583const int N_THREADS    = 1,
7584          BUFFER_SIZE  = 1,
7585          ITERATIONS   = 1 << 20;
7586
7587void 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
7600void Worker() {
7601  for (int j = 0; j < ITERATIONS; j++) {
7602    Foo();
7603  }
7604}
7605
7606void 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}
7616REGISTER_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
7621namespace test508 {
7622const int N_THREADS    = 1,
7623          BUFFER_SIZE  = 1 << 10,
7624          ITERATIONS   = 1 << 9;
7625
7626void 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
7639void Worker() {
7640  for (int j = 0; j < ITERATIONS; j++) {
7641    Foo();
7642  }
7643}
7644
7645void 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}
7655REGISTER_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
7660namespace test509 {
7661const int N_THREADS    = 16,
7662          ITERATIONS   = 1 << 8;
7663
7664void 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
7678void 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}
7688REGISTER_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
7693namespace test510 {
7694const int N_THREADS    = 16,
7695          ITERATIONS   = 1 << 10;
7696int GLOB = 0;
7697
7698void 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
7707void 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}
7718REGISTER_TEST2(Run, 510, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7719}  // namespace test510
7720
7721// test511: Segment refcounting test ('1' refcounting) {{{1
7722namespace test511 {
7723int GLOB = 0;
7724
7725void 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}
7735REGISTER_TEST2(Run, 511, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7736}  // namespace test511
7737
7738// test512: Segment refcounting test ('S' refcounting) {{{1
7739namespace test512 {
7740int GLOB = 0;
7741sem_t SEM;
7742
7743void 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}
7755REGISTER_TEST2(Run, 512, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7756}  // namespace test512
7757
7758// test513: --fast-mode benchmark {{{1
7759namespace test513 {
7760
7761const 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
7768const int ITERATIONS = 1024;
7769int array[N_THREADS][ARRAY_SIZE];
7770
7771int count = 0;
7772Mutex count_mu;
7773Mutex mutex_arr[N_THREADS][MUTEX_ID_BITS];
7774
7775void 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
7797void 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
7808REGISTER_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