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