tsan_unittest.cpp revision 3cb0598774b588523738c9b38690e9ee197a87ad
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 <algorithm>
77#include <cstring>      // strlen(), index(), rindex()
78#include <ctime>
79#include <sys/time.h>
80#include <sys/types.h>
81#include <sys/stat.h>
82#include <fcntl.h>
83#include <sys/mman.h>  // mmap
84#include <errno.h>
85#include <stdlib.h>
86#include <dirent.h>
87
88#ifndef OS_MACOSX
89#include <malloc.h>
90#endif
91
92// The tests are
93// - Stability tests (marked STAB)
94// - Performance tests (marked PERF)
95// - Feature tests
96//   - TN (true negative) : no race exists and the tool is silent.
97//   - TP (true positive) : a race exists and reported.
98//   - FN (false negative): a race exists but not reported.
99//   - FP (false positive): no race exists but the tool reports it.
100//
101// The feature tests are marked according to the behavior of helgrind 3.3.0.
102//
103// TP and FP tests are annotated with ANNOTATE_EXPECT_RACE,
104// so, no error reports should be seen when running under helgrind.
105//
106// When some of the FP cases are fixed in helgrind we'll need
107// to update this test.
108//
109// Each test resides in its own namespace.
110// Namespaces are named test01, test02, ...
111// Please, *DO NOT* change the logic of existing tests nor rename them.
112// Create a new test instead.
113//
114// Some tests use sleep()/usleep().
115// This is not a synchronization, but a simple way to trigger
116// some specific behaviour of the race detector's scheduler.
117
118// Globals and utilities used by several tests. {{{1
119CondVar CV;
120int     COND = 0;
121
122
123typedef void (*void_func_void_t)(void);
124enum TEST_FLAG {
125  FEATURE           = 1 << 0,
126  STABILITY         = 1 << 1,
127  PERFORMANCE       = 1 << 2,
128  EXCLUDE_FROM_ALL  = 1 << 3,
129  NEEDS_ANNOTATIONS = 1 << 4,
130  RACE_DEMO         = 1 << 5,
131  MEMORY_USAGE      = 1 << 6,
132  PRINT_STATS       = 1 << 7
133};
134
135// Put everything into stderr.
136Mutex printf_mu;
137#define printf(args...) \
138    do{ \
139      printf_mu.Lock();\
140      fprintf(stderr, args);\
141      printf_mu.Unlock(); \
142    }while(0)
143
144long GetTimeInMs() {
145   struct timeval tv;
146   gettimeofday(&tv, NULL);
147   return (tv.tv_sec * 1000L) + (tv.tv_usec / 1000L);
148}
149
150struct Test{
151  void_func_void_t f_;
152  int flags_;
153  Test(void_func_void_t f, int flags)
154    : f_(f)
155    , flags_(flags)
156  {}
157  Test() : f_(0), flags_(0) {}
158  void Run() {
159     ANNOTATE_RESET_STATS();
160     if (flags_ & PERFORMANCE) {
161        long start = GetTimeInMs();
162        f_();
163        long end = GetTimeInMs();
164        printf ("Time: %4ldms\n", end-start);
165     } else
166        f_();
167     if (flags_ & PRINT_STATS)
168        ANNOTATE_PRINT_STATS();
169     if (flags_ & MEMORY_USAGE)
170        ANNOTATE_PRINT_MEMORY_USAGE(0);
171  }
172};
173std::map<int, Test> TheMapOfTests;
174
175#define NOINLINE __attribute__ ((noinline))
176extern "C" void NOINLINE AnnotateSetVerbosity(const char *, int, int) {};
177
178
179struct TestAdder {
180  TestAdder(void_func_void_t f, int id, int flags = FEATURE) {
181    // AnnotateSetVerbosity(__FILE__, __LINE__, 0);
182    CHECK(TheMapOfTests.count(id) == 0);
183    TheMapOfTests[id] = Test(f, flags);
184  }
185};
186
187#define REGISTER_TEST(f, id)         TestAdder add_test_##id (f, id);
188#define REGISTER_TEST2(f, id, flags) TestAdder add_test_##id (f, id, flags);
189
190static bool ArgIsOne(int *arg) { return *arg == 1; };
191static bool ArgIsZero(int *arg) { return *arg == 0; };
192static bool ArgIsTrue(bool *arg) { return *arg == true; };
193
194// Call ANNOTATE_EXPECT_RACE only if 'machine' env variable is defined.
195// Useful to test against several different machines.
196// Supported machines so far:
197//   MSM_HYBRID1             -- aka MSMProp1
198//   MSM_HYBRID1_INIT_STATE  -- aka MSMProp1 with --initialization-state=yes
199//   MSM_THREAD_SANITIZER    -- ThreadSanitizer's state machine
200#define ANNOTATE_EXPECT_RACE_FOR_MACHINE(mem, descr, machine) \
201    while(getenv(machine)) {\
202      ANNOTATE_EXPECT_RACE(mem, descr); \
203      break;\
204    }\
205
206#define ANNOTATE_EXPECT_RACE_FOR_TSAN(mem, descr) \
207    ANNOTATE_EXPECT_RACE_FOR_MACHINE(mem, descr, "MSM_THREAD_SANITIZER")
208
209inline bool Tsan_PureHappensBefore() {
210  return true;
211}
212
213inline bool Tsan_FastMode()           {
214  return getenv("TSAN_FAST_MODE") != NULL;
215}
216
217// Initialize *(mem) to 0 if Tsan_FastMode.
218#define FAST_MODE_INIT(mem) do { if (Tsan_FastMode()) { *(mem) = 0; } } while(0)
219
220#ifndef MAIN_INIT_ACTION
221#define MAIN_INIT_ACTION
222#endif
223
224
225
226int main(int argc, char** argv) { // {{{1
227  MAIN_INIT_ACTION;
228  printf("FLAGS [phb=%i, fm=%i]\n", Tsan_PureHappensBefore(), Tsan_FastMode());
229  if (argc == 2 && !strcmp(argv[1], "benchmark")) {
230     for (std::map<int,Test>::iterator it = TheMapOfTests.begin();
231         it != TheMapOfTests.end(); ++it) {
232       if(!(it->second.flags_ & PERFORMANCE)) continue;
233       it->second.Run();
234     }
235  } else if (argc == 2 && !strcmp(argv[1], "demo")) {
236     for (std::map<int,Test>::iterator it = TheMapOfTests.begin();
237         it != TheMapOfTests.end();  ++it) {
238       if(!(it->second.flags_ & RACE_DEMO)) continue;
239       it->second.Run();
240     }
241  } else if (argc > 1) {
242    // the tests are listed in command line flags
243    for (int i = 1; i < argc; i++) {
244      int f_num = atoi(argv[i]);
245      CHECK(TheMapOfTests.count(f_num));
246      TheMapOfTests[f_num].Run();
247    }
248  } else {
249    bool run_tests_with_annotations = false;
250    if (getenv("DRT_ALLOW_ANNOTATIONS")) {
251      run_tests_with_annotations = true;
252    }
253    for (std::map<int,Test>::iterator it = TheMapOfTests.begin();
254        it != TheMapOfTests.end();
255        ++it) {
256      if(it->second.flags_ & EXCLUDE_FROM_ALL) continue;
257      if(it->second.flags_ & RACE_DEMO) continue;
258      if((it->second.flags_ & NEEDS_ANNOTATIONS)
259         && run_tests_with_annotations == false) continue;
260      it->second.Run();
261    }
262  }
263}
264
265#ifdef THREAD_WRAPPERS_PTHREAD_H
266#endif
267
268
269// An array of threads. Create/start/join all elements at once. {{{1
270class MyThreadArray {
271 public:
272  static const int kSize = 5;
273  typedef void (*F) (void);
274  MyThreadArray(F f1, F f2 = NULL, F f3 = NULL, F f4 = NULL, F f5 = NULL) {
275    ar_[0] = new MyThread(f1);
276    ar_[1] = f2 ? new MyThread(f2) : NULL;
277    ar_[2] = f3 ? new MyThread(f3) : NULL;
278    ar_[3] = f4 ? new MyThread(f4) : NULL;
279    ar_[4] = f5 ? new MyThread(f5) : NULL;
280  }
281  void Start() {
282    for(int i = 0; i < kSize; i++) {
283      if(ar_[i]) {
284        ar_[i]->Start();
285        usleep(10);
286      }
287    }
288  }
289
290  void Join() {
291    for(int i = 0; i < kSize; i++) {
292      if(ar_[i]) {
293        ar_[i]->Join();
294      }
295    }
296  }
297
298  ~MyThreadArray() {
299    for(int i = 0; i < kSize; i++) {
300      delete ar_[i];
301    }
302  }
303 private:
304  MyThread *ar_[kSize];
305};
306
307
308
309// test00: {{{1
310namespace test00 {
311int     GLOB = 0;
312void Run() {
313  printf("test00: negative\n");
314  printf("\tGLOB=%d\n", GLOB);
315}
316REGISTER_TEST(Run, 00)
317}  // namespace test00
318
319
320// test01: TP. Simple race (write vs write). {{{1
321namespace test01 {
322int     GLOB = 0;
323void Worker() {
324  GLOB = 1;
325}
326
327void Parent() {
328  MyThread t(Worker);
329  t.Start();
330  GLOB = 2;
331  t.Join();
332}
333void Run() {
334  FAST_MODE_INIT(&GLOB);
335  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test01. TP.");
336  ANNOTATE_TRACE_MEMORY(&GLOB);
337  printf("test01: positive\n");
338  Parent();
339  const int tmp = GLOB;
340  printf("\tGLOB=%d\n", tmp);
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_CONDVAR_SIGNAL(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_CONDVAR_WAIT(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_CONDVAR_SIGNAL(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_CONDVAR_WAIT(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#if 0
3820typedef __gnu_cxx::hash_map<int, int> map_t;
3821#else
3822typedef std::map<int, int> map_t;
3823#endif
3824map_t   MAP;
3825Mutex   MU;
3826
3827// Here we use swap to pass MAP between threads.
3828// The synchronization is correct, but w/o ANNOTATE_MUTEX_IS_USED_AS_CONDVAR
3829// Helgrind will complain.
3830
3831void Worker1() {
3832  map_t tmp;
3833  MU.Lock();
3834  // We swap the new empty map 'tmp' with 'MAP'.
3835  MAP.swap(tmp);
3836  MU.Unlock();
3837  // tmp (which is the old version of MAP) is destroyed here.
3838}
3839
3840void Worker2() {
3841  MU.Lock();
3842  MAP[1]++;  // Just update MAP under MU.
3843  MU.Unlock();
3844}
3845
3846void Worker3() { Worker1(); }
3847void Worker4() { Worker2(); }
3848
3849void Run() {
3850  ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
3851  printf("test79: negative\n");
3852  MyThreadArray t(Worker1, Worker2, Worker3, Worker4);
3853  t.Start();
3854  t.Join();
3855}
3856REGISTER_TEST(Run, 79)
3857}  // namespace test79
3858
3859
3860// AtomicRefCountedClass. {{{1
3861// Same as RefCountedClass, but using atomic ops instead of mutex.
3862struct AtomicRefCountedClass {
3863 public:
3864  AtomicRefCountedClass() {
3865    annotate_unref_ = false;
3866    ref_ = 0;
3867    data_ = 0;
3868  }
3869
3870  ~AtomicRefCountedClass() {
3871    CHECK(ref_ == 0);     // race may be reported here
3872    int data_val = data_; // and here
3873    data_ = 0;
3874    ref_ = -1;
3875    printf("\tRefCountedClass::data_ = %d\n", data_val);
3876  }
3877
3878  void AccessData() {
3879    this->mu_.Lock();
3880    this->data_++;
3881    this->mu_.Unlock();
3882  }
3883
3884  void Ref() {
3885    AtomicIncrement(&ref_, 1);
3886  }
3887
3888  void Unref() {
3889    // DISCLAIMER: I am not sure I've implemented this correctly
3890    // (might require some memory barrier, etc).
3891    // But this implementation of reference counting is enough for
3892    // the purpose of Helgrind demonstration.
3893    AtomicIncrement(&ref_, -1);
3894    if (annotate_unref_) { ANNOTATE_CONDVAR_SIGNAL(this); }
3895    if (ref_ == 0) {
3896      if (annotate_unref_) { ANNOTATE_CONDVAR_WAIT(this); }
3897      delete this;
3898    }
3899  }
3900
3901  void AnnotateUnref() {
3902    annotate_unref_ = true;
3903  }
3904  void Annotate_Race() {
3905    ANNOTATE_BENIGN_RACE(&this->data_, "needs annotation");
3906  }
3907 private:
3908  bool annotate_unref_;
3909
3910  Mutex mu_;
3911  int data_; // under mu_
3912
3913  int ref_;  // used in atomic ops.
3914};
3915
3916// test80: FP. Ref counting with atomics, no annotations. {{{1
3917namespace test80 {
3918#ifndef NO_BARRIER
3919int     GLOB = 0;
3920Barrier barrier(4);
3921AtomicRefCountedClass *object = NULL;
3922void Worker() {
3923  object->Ref();
3924  barrier.Block();
3925  object->AccessData();
3926  object->Unref(); // All the tricky stuff is here.
3927}
3928void Run() {
3929  printf("test80: false positive (ref counting)\n");
3930  object = new AtomicRefCountedClass;
3931  object->Annotate_Race();
3932  MyThreadArray t(Worker, Worker, Worker, Worker);
3933  t.Start();
3934  t.Join();
3935}
3936REGISTER_TEST2(Run, 80, FEATURE|EXCLUDE_FROM_ALL)
3937#endif // NO_BARRIER
3938}  // namespace test80
3939
3940
3941// test81: TN. Ref counting with atomics, Unref is annotated. {{{1
3942namespace test81 {
3943#ifndef NO_BARRIER
3944// same as test80, but Unref is annotated.
3945int     GLOB = 0;
3946Barrier barrier(4);
3947AtomicRefCountedClass *object = NULL;
3948void Worker() {
3949  object->Ref();
3950  barrier.Block();
3951  object->AccessData();
3952  object->Unref(); // All the tricky stuff is here.
3953}
3954void Run() {
3955  printf("test81: negative (annotated ref counting)\n");
3956  object = new AtomicRefCountedClass;
3957  object->AnnotateUnref();
3958  MyThreadArray t(Worker, Worker, Worker, Worker);
3959  t.Start();
3960  t.Join();
3961}
3962REGISTER_TEST2(Run, 81, FEATURE|EXCLUDE_FROM_ALL)
3963#endif // NO_BARRIER
3964}  // namespace test81
3965
3966
3967// test82: Object published w/o synchronization. {{{1
3968namespace test82 {
3969
3970// Writer creates a new object and makes the pointer visible to the Reader.
3971// Reader waits until the object pointer is non-null and reads the object.
3972//
3973// On Core 2 Duo this test will sometimes (quite rarely) fail in
3974// the CHECK below, at least if compiled with -O2.
3975//
3976// The sequence of events::
3977// Thread1:                  Thread2:
3978//   a. arr_[...] = ...
3979//   b. foo[i]    = ...
3980//                           A. ... = foo[i]; // non NULL
3981//                           B. ... = arr_[...];
3982//
3983//  Since there is no proper synchronization, during the even (B)
3984//  Thread2 may not see the result of the event (a).
3985//  On x86 and x86_64 this happens due to compiler reordering instructions.
3986//  On other arcitectures it may also happen due to cashe inconsistency.
3987
3988class FOO {
3989 public:
3990  FOO() {
3991    idx_ = rand() % 1024;
3992    arr_[idx_] = 77777;
3993  //   __asm__ __volatile__("" : : : "memory"); // this fixes!
3994  }
3995  static void check(volatile FOO *foo) {
3996    CHECK(foo->arr_[foo->idx_] == 77777);
3997  }
3998 private:
3999  int idx_;
4000  int arr_[1024];
4001};
4002
4003const int N = 100000;
4004static volatile FOO *foo[N];
4005Mutex   MU;
4006
4007void Writer() {
4008  for (int i = 0; i < N; i++) {
4009    foo[i] = new FOO;
4010    usleep(100);
4011  }
4012}
4013
4014void Reader() {
4015  for (int i = 0; i < N; i++) {
4016    while (!foo[i]) {
4017      MU.Lock();   // this is NOT a synchronization,
4018      MU.Unlock(); // it just helps foo[i] to become visible in Reader.
4019    }
4020    if ((i % 100) == 0) {
4021      printf("rd %d\n", i);
4022    }
4023    // At this point Reader() sees the new value of foo[i]
4024    // but in very rare cases will not see the new value of foo[i]->arr_.
4025    // Thus this CHECK will sometimes fail.
4026    FOO::check(foo[i]);
4027  }
4028}
4029
4030void Run() {
4031  printf("test82: positive\n");
4032  MyThreadArray t(Writer, Reader);
4033  t.Start();
4034  t.Join();
4035}
4036REGISTER_TEST2(Run, 82, FEATURE|EXCLUDE_FROM_ALL)
4037}  // namespace test82
4038
4039
4040// test83: Object published w/o synchronization (simple version){{{1
4041namespace test83 {
4042// A simplified version of test83 (example of a wrong code).
4043// This test, though incorrect, will almost never fail.
4044volatile static int *ptr = NULL;
4045Mutex   MU;
4046
4047void Writer() {
4048  usleep(100);
4049  ptr = new int(777);
4050}
4051
4052void Reader() {
4053  while(!ptr) {
4054    MU.Lock(); // Not a synchronization!
4055    MU.Unlock();
4056  }
4057  CHECK(*ptr == 777);
4058}
4059
4060void Run() {
4061//  printf("test83: positive\n");
4062  MyThreadArray t(Writer, Reader);
4063  t.Start();
4064  t.Join();
4065}
4066REGISTER_TEST2(Run, 83, FEATURE|EXCLUDE_FROM_ALL)
4067}  // namespace test83
4068
4069
4070// test84: TP. True race (regression test for a bug related to atomics){{{1
4071namespace test84 {
4072// Helgrind should not create HB arcs for the bus lock even when
4073// --pure-happens-before=yes is used.
4074// Bug found in by Bart Van Assche, the test is taken from
4075// valgrind file drd/tests/atomic_var.c.
4076static int s_x = 0;
4077/* s_dummy[] ensures that s_x and s_y are not in the same cache line. */
4078static char s_dummy[512] = {0};
4079static int s_y;
4080
4081void thread_func_1()
4082{
4083  s_y = 1;
4084  AtomicIncrement(&s_x, 1);
4085}
4086
4087void thread_func_2()
4088{
4089  while (AtomicIncrement(&s_x, 0) == 0)
4090    ;
4091  printf("y = %d\n", s_y);
4092}
4093
4094
4095void Run() {
4096  CHECK(s_dummy[0] == 0);  // Avoid compiler warning about 's_dummy unused'.
4097  printf("test84: positive\n");
4098  FAST_MODE_INIT(&s_y);
4099  ANNOTATE_EXPECT_RACE_FOR_TSAN(&s_y, "test84: TP. true race.");
4100  MyThreadArray t(thread_func_1, thread_func_2);
4101  t.Start();
4102  t.Join();
4103}
4104REGISTER_TEST(Run, 84)
4105}  // namespace test84
4106
4107
4108// test85: Test for RunningOnValgrind(). {{{1
4109namespace  test85 {
4110int     GLOB = 0;
4111void Run() {
4112  printf("test85: RunningOnValgrind() = %d\n", RunningOnValgrind());
4113}
4114REGISTER_TEST(Run, 85)
4115}  // namespace test85
4116
4117
4118// test86: Test for race inside DTOR: racey write to vptr. Benign. {{{1
4119namespace test86 {
4120// This test shows a racey access to vptr (the pointer to vtbl).
4121// We have class A and class B derived from A.
4122// Both classes have a virtual function f() and a virtual DTOR.
4123// We create an object 'A *a = new B'
4124// and pass this object from Thread1 to Thread2.
4125// Thread2 calls a->f(). This call reads a->vtpr.
4126// Thread1 deletes the object. B::~B waits untill the object can be destroyed
4127// (flag_stopped == true) but at the very beginning of B::~B
4128// a->vptr is written to.
4129// So, we have a race on a->vptr.
4130// On this particular test this race is benign, but test87 shows
4131// how such race could harm.
4132//
4133//
4134//
4135// Threa1:                                            Thread2:
4136// 1. A a* = new B;
4137// 2. Q.Put(a); ------------\                         .
4138//                           \-------------------->   a. a = Q.Get();
4139//                                                    b. a->f();
4140//                                       /---------   c. flag_stopped = true;
4141// 3. delete a;                         /
4142//    waits untill flag_stopped <------/
4143//    inside the dtor
4144//
4145
4146bool flag_stopped = false;
4147Mutex mu;
4148
4149ProducerConsumerQueue Q(INT_MAX);  // Used to pass A* between threads.
4150
4151struct A {
4152  A()  { printf("A::A()\n"); }
4153  virtual ~A() { printf("A::~A()\n"); }
4154  virtual void f() { }
4155
4156  uintptr_t padding[15];
4157} __attribute__ ((aligned (64)));
4158
4159struct B: A {
4160  B()  { printf("B::B()\n"); }
4161  virtual ~B() {
4162    // The race is here.    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
4163    printf("B::~B()\n");
4164    // wait until flag_stopped is true.
4165    mu.LockWhen(Condition(&ArgIsTrue, &flag_stopped));
4166    mu.Unlock();
4167    printf("B::~B() done\n");
4168  }
4169  virtual void f() { }
4170};
4171
4172void Waiter() {
4173  A *a = new B;
4174  if (!Tsan_FastMode())
4175    ANNOTATE_EXPECT_RACE(a, "test86: expected race on a->vptr");
4176  printf("Waiter: B created\n");
4177  Q.Put(a);
4178  usleep(100000); // so that Worker calls a->f() first.
4179  printf("Waiter: deleting B\n");
4180  delete a;
4181  printf("Waiter: B deleted\n");
4182  usleep(100000);
4183  printf("Waiter: done\n");
4184}
4185
4186void Worker() {
4187  A *a = reinterpret_cast<A*>(Q.Get());
4188  printf("Worker: got A\n");
4189  a->f();
4190
4191  mu.Lock();
4192  flag_stopped = true;
4193  mu.Unlock();
4194  usleep(200000);
4195  printf("Worker: done\n");
4196}
4197
4198void Run() {
4199  printf("test86: positive, race inside DTOR\n");
4200  MyThreadArray t(Waiter, Worker);
4201  t.Start();
4202  t.Join();
4203}
4204REGISTER_TEST(Run, 86)
4205}  // namespace test86
4206
4207
4208// test87: Test for race inside DTOR: racey write to vptr. Harmful.{{{1
4209namespace test87 {
4210// A variation of test86 where the race is harmful.
4211// Here we have class C derived from B.
4212// We create an object 'A *a = new C' in Thread1 and pass it to Thread2.
4213// Thread2 calls a->f().
4214// Thread1 calls 'delete a'.
4215// It first calls C::~C, then B::~B where it rewrites the vptr to point
4216// to B::vtbl. This is a problem because Thread2 might not have called a->f()
4217// and now it will call B::f instead of C::f.
4218//
4219bool flag_stopped = false;
4220Mutex mu;
4221
4222ProducerConsumerQueue Q(INT_MAX);  // Used to pass A* between threads.
4223
4224struct A {
4225  A()  { printf("A::A()\n"); }
4226  virtual ~A() { printf("A::~A()\n"); }
4227  virtual void f() = 0; // pure virtual.
4228};
4229
4230struct B: A {
4231  B()  { printf("B::B()\n"); }
4232  virtual ~B() {
4233    // The race is here.    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
4234    printf("B::~B()\n");
4235    // wait until flag_stopped is true.
4236    mu.LockWhen(Condition(&ArgIsTrue, &flag_stopped));
4237    mu.Unlock();
4238    printf("B::~B() done\n");
4239  }
4240  virtual void f() = 0; // pure virtual.
4241};
4242
4243struct C: B {
4244  C()  { printf("C::C()\n"); }
4245  virtual ~C() { printf("C::~C()\n"); }
4246  virtual void f() { }
4247};
4248
4249void Waiter() {
4250  A *a = new C;
4251  Q.Put(a);
4252  delete a;
4253}
4254
4255void Worker() {
4256  A *a = reinterpret_cast<A*>(Q.Get());
4257  a->f();
4258
4259  mu.Lock();
4260  flag_stopped = true;
4261  ANNOTATE_CONDVAR_SIGNAL(&mu);
4262  mu.Unlock();
4263}
4264
4265void Run() {
4266  printf("test87: positive, race inside DTOR\n");
4267  MyThreadArray t(Waiter, Worker);
4268  t.Start();
4269  t.Join();
4270}
4271REGISTER_TEST2(Run, 87, FEATURE|EXCLUDE_FROM_ALL)
4272}  // namespace test87
4273
4274
4275// test88: Test for ANNOTATE_IGNORE_WRITES_*{{{1
4276namespace test88 {
4277// a recey write annotated with ANNOTATE_IGNORE_WRITES_BEGIN/END.
4278int     GLOB = 0;
4279void Worker() {
4280  ANNOTATE_IGNORE_WRITES_BEGIN();
4281  GLOB = 1;
4282  ANNOTATE_IGNORE_WRITES_END();
4283}
4284void Run() {
4285  printf("test88: negative, test for ANNOTATE_IGNORE_WRITES_*\n");
4286  MyThread t(Worker);
4287  t.Start();
4288  GLOB = 1;
4289  t.Join();
4290  printf("\tGLOB=%d\n", GLOB);
4291}
4292REGISTER_TEST(Run, 88)
4293}  // namespace test88
4294
4295
4296// test89: Test for debug info. {{{1
4297namespace test89 {
4298// Simlpe races with different objects (stack, heap globals; scalars, structs).
4299// Also, if run with --trace-level=2 this test will show a sequence of
4300// CTOR and DTOR calls.
4301struct STRUCT {
4302  int a, b, c;
4303};
4304
4305struct A {
4306  int a;
4307  A() {
4308    ANNOTATE_TRACE_MEMORY(&a);
4309    a = 1;
4310  }
4311  virtual ~A() {
4312    a = 4;
4313  }
4314};
4315
4316struct B : A {
4317  B()  { CHECK(a == 1); }
4318  virtual ~B() { CHECK(a == 3); }
4319};
4320struct C : B {
4321  C()  { a = 2; }
4322  virtual ~C() { a = 3; }
4323};
4324
4325int            GLOBAL = 0;
4326int           *STACK  = 0;
4327STRUCT         GLOB_STRUCT;
4328STRUCT        *STACK_STRUCT;
4329STRUCT        *HEAP_STRUCT;
4330
4331void Worker() {
4332  GLOBAL = 1;
4333  *STACK = 1;
4334  GLOB_STRUCT.b   = 1;
4335  STACK_STRUCT->b = 1;
4336  HEAP_STRUCT->b  = 1;
4337}
4338
4339void Run() {
4340  int stack_var = 0;
4341  STACK = &stack_var;
4342
4343  STRUCT stack_struct;
4344  STACK_STRUCT = &stack_struct;
4345
4346  HEAP_STRUCT = new STRUCT;
4347
4348  printf("test89: negative\n");
4349  MyThreadArray t(Worker, Worker);
4350  t.Start();
4351  t.Join();
4352
4353  delete HEAP_STRUCT;
4354
4355  A *a = new C;
4356  printf("Using 'a->a':  %d\n", a->a);
4357  delete a;
4358}
4359REGISTER_TEST2(Run, 89, FEATURE|EXCLUDE_FROM_ALL)
4360}  // namespace test89
4361
4362
4363// test90: FP. Test for a safely-published pointer (read-only). {{{1
4364namespace test90 {
4365// The Publisher creates an object and safely publishes it under a mutex.
4366// Readers access the object read-only.
4367// See also test91.
4368//
4369// Without annotations Helgrind will issue a false positive in Reader().
4370//
4371// Choices for annotations:
4372//   -- ANNOTATE_CONDVAR_SIGNAL/ANNOTATE_CONDVAR_WAIT
4373//   -- ANNOTATE_MUTEX_IS_USED_AS_CONDVAR
4374//   -- ANNOTATE_PUBLISH_MEMORY_RANGE.
4375
4376int     *GLOB = 0;
4377Mutex   MU;
4378
4379void Publisher() {
4380  MU.Lock();
4381  GLOB = (int*)memalign(64, sizeof(int));
4382  *GLOB = 777;
4383  if (!Tsan_PureHappensBefore() && !Tsan_FastMode())
4384    ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test90. FP. This is a false positve");
4385  MU.Unlock();
4386  usleep(200000);
4387}
4388
4389void Reader() {
4390  usleep(10000);
4391  while (true) {
4392    MU.Lock();
4393    int *p = GLOB;
4394    MU.Unlock();
4395    if (p) {
4396      CHECK(*p == 777);  // Race is reported here.
4397      break;
4398    }
4399  }
4400}
4401
4402void Run() {
4403  printf("test90: false positive (safely published pointer).\n");
4404  MyThreadArray t(Publisher, Reader, Reader, Reader);
4405  t.Start();
4406  t.Join();
4407  printf("\t*GLOB=%d\n", *GLOB);
4408  free(GLOB);
4409}
4410REGISTER_TEST(Run, 90)
4411}  // namespace test90
4412
4413
4414// test91: FP. Test for a safely-published pointer (read-write). {{{1
4415namespace test91 {
4416// Similar to test90.
4417// The Publisher creates an object and safely publishes it under a mutex MU1.
4418// Accessors get the object under MU1 and access it (read/write) under MU2.
4419//
4420// Without annotations Helgrind will issue a false positive in Accessor().
4421//
4422
4423int     *GLOB = 0;
4424Mutex   MU, MU1, MU2;
4425
4426void Publisher() {
4427  MU1.Lock();
4428  GLOB = (int*)memalign(64, sizeof(int));
4429  *GLOB = 777;
4430  if (!Tsan_PureHappensBefore() && !Tsan_FastMode())
4431    ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test91. FP. This is a false positve");
4432  MU1.Unlock();
4433}
4434
4435void Accessor() {
4436  usleep(10000);
4437  while (true) {
4438    MU1.Lock();
4439    int *p = GLOB;
4440    MU1.Unlock();
4441    if (p) {
4442      MU2.Lock();
4443      (*p)++;  // Race is reported here.
4444      CHECK(*p >  777);
4445      MU2.Unlock();
4446      break;
4447    }
4448  }
4449}
4450
4451void Run() {
4452  printf("test91: false positive (safely published pointer, read/write).\n");
4453  MyThreadArray t(Publisher, Accessor, Accessor, Accessor);
4454  t.Start();
4455  t.Join();
4456  printf("\t*GLOB=%d\n", *GLOB);
4457  free(GLOB);
4458}
4459REGISTER_TEST(Run, 91)
4460}  // namespace test91
4461
4462
4463// test92: TN. Test for a safely-published pointer (read-write), annotated. {{{1
4464namespace test92 {
4465// Similar to test91, but annotated with ANNOTATE_PUBLISH_MEMORY_RANGE.
4466//
4467//
4468// Publisher:                                       Accessors:
4469//
4470// 1. MU1.Lock()
4471// 2. Create GLOB.
4472// 3. ANNOTATE_PUBLISH_...(GLOB) -------\            .
4473// 4. MU1.Unlock()                       \           .
4474//                                        \          a. MU1.Lock()
4475//                                         \         b. Get GLOB
4476//                                          \        c. MU1.Lock()
4477//                                           \-->    d. Access GLOB
4478//
4479//  A happens-before arc is created between ANNOTATE_PUBLISH_MEMORY_RANGE and
4480//  accesses to GLOB.
4481
4482struct ObjType {
4483  int arr[10];
4484};
4485
4486ObjType *GLOB = 0;
4487Mutex   MU, MU1, MU2;
4488
4489void Publisher() {
4490  MU1.Lock();
4491  GLOB = new ObjType;
4492  for (int i = 0; i < 10; i++) {
4493    GLOB->arr[i] = 777;
4494  }
4495  // This annotation should go right before the object is published.
4496  ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB, sizeof(*GLOB));
4497  MU1.Unlock();
4498}
4499
4500void Accessor(int index) {
4501  while (true) {
4502    MU1.Lock();
4503    ObjType *p = GLOB;
4504    MU1.Unlock();
4505    if (p) {
4506      MU2.Lock();
4507      p->arr[index]++;  // W/o the annotations the race will be reported here.
4508      CHECK(p->arr[index] ==  778);
4509      MU2.Unlock();
4510      break;
4511    }
4512  }
4513}
4514
4515void Accessor0() { Accessor(0); }
4516void Accessor5() { Accessor(5); }
4517void Accessor9() { Accessor(9); }
4518
4519void Run() {
4520  printf("test92: safely published pointer, read/write, annotated.\n");
4521  MyThreadArray t(Publisher, Accessor0, Accessor5, Accessor9);
4522  t.Start();
4523  t.Join();
4524  printf("\t*GLOB=%d\n", GLOB->arr[0]);
4525}
4526REGISTER_TEST(Run, 92)
4527}  // namespace test92
4528
4529
4530// test93: TP. Test for incorrect usage of ANNOTATE_PUBLISH_MEMORY_RANGE. {{{1
4531namespace test93 {
4532int     GLOB = 0;
4533
4534void Reader() {
4535  CHECK(GLOB == 0);
4536}
4537
4538void Publisher() {
4539  usleep(10000);
4540  // Incorrect, used after the memory has been accessed in another thread.
4541  ANNOTATE_PUBLISH_MEMORY_RANGE(&GLOB, sizeof(GLOB));
4542}
4543
4544void Run() {
4545  printf("test93: positive, misuse of ANNOTATE_PUBLISH_MEMORY_RANGE\n");
4546  MyThreadArray t(Reader, Publisher);
4547  t.Start();
4548  t.Join();
4549  printf("\tGLOB=%d\n", GLOB);
4550}
4551REGISTER_TEST2(Run, 93, FEATURE|EXCLUDE_FROM_ALL)
4552}  // namespace test93
4553
4554
4555// test94: TP. Check do_cv_signal/fake segment logic {{{1
4556namespace test94 {
4557int     GLOB;
4558
4559int COND  = 0;
4560int COND2 = 0;
4561Mutex MU, MU2;
4562CondVar CV, CV2;
4563
4564void Thr1() {
4565  usleep(10000);  // Make sure the waiter blocks.
4566
4567  GLOB = 1; // WRITE
4568
4569  MU.Lock();
4570  COND = 1;
4571  CV.Signal();
4572  MU.Unlock();
4573}
4574void Thr2() {
4575  usleep(1000*1000); // Make sure CV2.Signal() "happens after" CV.Signal()
4576  usleep(10000);  // Make sure the waiter blocks.
4577
4578  MU2.Lock();
4579  COND2 = 1;
4580  CV2.Signal();
4581  MU2.Unlock();
4582}
4583void Thr3() {
4584  MU.Lock();
4585  while(COND != 1)
4586    CV.Wait(&MU);
4587  MU.Unlock();
4588}
4589void Thr4() {
4590  MU2.Lock();
4591  while(COND2 != 1)
4592    CV2.Wait(&MU2);
4593  MU2.Unlock();
4594  GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait !
4595}
4596void Run() {
4597  FAST_MODE_INIT(&GLOB);
4598  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test94: TP.");
4599  printf("test94: TP. Check do_cv_signal/fake segment logic\n");
4600  MyThreadArray mta(Thr1, Thr2, Thr3, Thr4);
4601  mta.Start();
4602  mta.Join();
4603  printf("\tGLOB=%d\n", GLOB);
4604}
4605REGISTER_TEST(Run, 94);
4606}  // namespace test94
4607
4608// test95: TP. Check do_cv_signal/fake segment logic {{{1
4609namespace test95 {
4610int     GLOB = 0;
4611
4612int COND  = 0;
4613int COND2 = 0;
4614Mutex MU, MU2;
4615CondVar CV, CV2;
4616
4617void Thr1() {
4618  usleep(1000*1000); // Make sure CV2.Signal() "happens before" CV.Signal()
4619  usleep(10000);  // Make sure the waiter blocks.
4620
4621  GLOB = 1; // WRITE
4622
4623  MU.Lock();
4624  COND = 1;
4625  CV.Signal();
4626  MU.Unlock();
4627}
4628void Thr2() {
4629  usleep(10000);  // Make sure the waiter blocks.
4630
4631  MU2.Lock();
4632  COND2 = 1;
4633  CV2.Signal();
4634  MU2.Unlock();
4635}
4636void Thr3() {
4637  MU.Lock();
4638  while(COND != 1)
4639    CV.Wait(&MU);
4640  MU.Unlock();
4641}
4642void Thr4() {
4643  MU2.Lock();
4644  while(COND2 != 1)
4645    CV2.Wait(&MU2);
4646  MU2.Unlock();
4647  GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait !
4648}
4649void Run() {
4650  FAST_MODE_INIT(&GLOB);
4651  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test95: TP.");
4652  printf("test95: TP. Check do_cv_signal/fake segment logic\n");
4653  MyThreadArray mta(Thr1, Thr2, Thr3, Thr4);
4654  mta.Start();
4655  mta.Join();
4656  printf("\tGLOB=%d\n", GLOB);
4657}
4658REGISTER_TEST(Run, 95);
4659}  // namespace test95
4660
4661// test96: TN. tricky LockSet behaviour {{{1
4662// 3 threads access the same memory with three different
4663// locksets: {A, B}, {B, C}, {C, A}.
4664// These locksets have empty intersection
4665namespace test96 {
4666int     GLOB = 0;
4667
4668Mutex A, B, C;
4669
4670void Thread1() {
4671  MutexLock a(&A);
4672  MutexLock b(&B);
4673  GLOB++;
4674}
4675
4676void Thread2() {
4677  MutexLock b(&B);
4678  MutexLock c(&C);
4679  GLOB++;
4680}
4681
4682void Thread3() {
4683  MutexLock a(&A);
4684  MutexLock c(&C);
4685  GLOB++;
4686}
4687
4688void Run() {
4689  printf("test96: FP. tricky LockSet behaviour\n");
4690  ANNOTATE_TRACE_MEMORY(&GLOB);
4691  MyThreadArray mta(Thread1, Thread2, Thread3);
4692  mta.Start();
4693  mta.Join();
4694  CHECK(GLOB == 3);
4695  printf("\tGLOB=%d\n", GLOB);
4696}
4697REGISTER_TEST(Run, 96);
4698}  // namespace test96
4699
4700// test97: This test shows false negative with --fast-mode=yes {{{1
4701namespace test97 {
4702const int HG_CACHELINE_SIZE = 64;
4703
4704Mutex MU;
4705
4706const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4707int array[ARRAY_SIZE];
4708int * GLOB = &array[ARRAY_SIZE/2];
4709/*
4710  We use sizeof(array) == 4 * HG_CACHELINE_SIZE to be sure that GLOB points
4711  to a memory inside a CacheLineZ which is inside array's memory range
4712 */
4713
4714void Reader() {
4715  usleep(500000);
4716  CHECK(777 == *GLOB);
4717}
4718
4719void Run() {
4720  MyThreadArray t(Reader);
4721  if (!Tsan_FastMode())
4722    ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test97: TP. FN with --fast-mode=yes");
4723  printf("test97: This test shows false negative with --fast-mode=yes\n");
4724
4725  t.Start();
4726  *GLOB = 777;
4727  t.Join();
4728}
4729
4730REGISTER_TEST2(Run, 97, FEATURE)
4731}  // namespace test97
4732
4733// test98: Synchronization via read/write (or send/recv). {{{1
4734namespace test98 {
4735// The synchronization here is done by a pair of read/write calls
4736// that create a happens-before arc. Same may be done with send/recv.
4737// Such synchronization is quite unusual in real programs
4738// (why would one synchronizae via a file or socket?), but
4739// quite possible in unittests where one threads runs for producer
4740// and one for consumer.
4741//
4742// A race detector has to create a happens-before arcs for
4743// {read,send}->{write,recv} even if the file descriptors are different.
4744//
4745int     GLOB = 0;
4746int fd_out = -1;
4747int fd_in  = -1;
4748
4749void Writer() {
4750  usleep(1000);
4751  GLOB = 1;
4752  const char *str = "Hey there!\n";
4753  write(fd_out, str, strlen(str) + 1);
4754}
4755
4756void Reader() {
4757  char buff[100];
4758  while (read(fd_in, buff, 100) == 0)
4759    sleep(1);
4760  printf("read: %s\n", buff);
4761  GLOB = 2;
4762}
4763
4764void Run() {
4765  printf("test98: negative, synchronization via I/O\n");
4766  char in_name[100];
4767  char out_name[100];
4768  // we open two files, on for reading and one for writing,
4769  // but the files are actually the same (symlinked).
4770  sprintf(in_name,  "/tmp/racecheck_unittest_in.%d", getpid());
4771  sprintf(out_name, "/tmp/racecheck_unittest_out.%d", getpid());
4772  fd_out = creat(out_name, O_WRONLY | S_IRWXU);
4773  symlink(out_name, in_name);
4774  fd_in  = open(in_name, 0, O_RDONLY);
4775  CHECK(fd_out >= 0);
4776  CHECK(fd_in  >= 0);
4777  MyThreadArray t(Writer, Reader);
4778  t.Start();
4779  t.Join();
4780  printf("\tGLOB=%d\n", GLOB);
4781  // cleanup
4782  close(fd_in);
4783  close(fd_out);
4784  unlink(in_name);
4785  unlink(out_name);
4786}
4787REGISTER_TEST(Run, 98)
4788}  // namespace test98
4789
4790
4791// test99: TP. Unit test for a bug in LockWhen*. {{{1
4792namespace test99 {
4793
4794
4795bool GLOB = false;
4796Mutex mu;
4797
4798static void Thread1() {
4799  for (int i = 0; i < 100; i++) {
4800    mu.LockWhenWithTimeout(Condition(&ArgIsTrue, &GLOB), 5);
4801    GLOB = false;
4802    mu.Unlock();
4803    usleep(10000);
4804  }
4805}
4806
4807static void Thread2() {
4808  for (int i = 0; i < 100; i++) {
4809    mu.Lock();
4810    mu.Unlock();
4811    usleep(10000);
4812  }
4813}
4814
4815void Run() {
4816  printf("test99: regression test for LockWhen*\n");
4817  MyThreadArray t(Thread1, Thread2);
4818  t.Start();
4819  t.Join();
4820}
4821REGISTER_TEST(Run, 99);
4822}  // namespace test99
4823
4824
4825// test100: Test for initialization bit. {{{1
4826namespace test100 {
4827int     G1 = 0;
4828int     G2 = 0;
4829int     G3 = 0;
4830int     G4 = 0;
4831
4832void Creator() {
4833  G1 = 1; CHECK(G1);
4834  G2 = 1;
4835  G3 = 1; CHECK(G3);
4836  G4 = 1;
4837}
4838
4839void Worker1() {
4840  usleep(100000);
4841  CHECK(G1);
4842  CHECK(G2);
4843  G3 = 3;
4844  G4 = 3;
4845}
4846
4847void Worker2() {
4848
4849}
4850
4851
4852void Run() {
4853  printf("test100: test for initialization bit. \n");
4854  MyThreadArray t(Creator, Worker1, Worker2);
4855  ANNOTATE_TRACE_MEMORY(&G1);
4856  ANNOTATE_TRACE_MEMORY(&G2);
4857  ANNOTATE_TRACE_MEMORY(&G3);
4858  ANNOTATE_TRACE_MEMORY(&G4);
4859  t.Start();
4860  t.Join();
4861}
4862REGISTER_TEST2(Run, 100, FEATURE|EXCLUDE_FROM_ALL)
4863}  // namespace test100
4864
4865
4866// test101: TN. Two signals and two waits. {{{1
4867namespace test101 {
4868Mutex MU;
4869CondVar CV;
4870int     GLOB = 0;
4871
4872int C1 = 0, C2 = 0;
4873
4874void Signaller() {
4875  usleep(100000);
4876  MU.Lock();
4877  C1 = 1;
4878  CV.Signal();
4879  printf("signal\n");
4880  MU.Unlock();
4881
4882  GLOB = 1;
4883
4884  usleep(500000);
4885  MU.Lock();
4886  C2 = 1;
4887  CV.Signal();
4888  printf("signal\n");
4889  MU.Unlock();
4890}
4891
4892void Waiter() {
4893  MU.Lock();
4894  while(!C1)
4895    CV.Wait(&MU);
4896  printf("wait\n");
4897  MU.Unlock();
4898
4899  MU.Lock();
4900  while(!C2)
4901    CV.Wait(&MU);
4902  printf("wait\n");
4903  MU.Unlock();
4904
4905  GLOB = 2;
4906
4907}
4908
4909void Run() {
4910  printf("test101: negative\n");
4911  MyThreadArray t(Waiter, Signaller);
4912  t.Start();
4913  t.Join();
4914  printf("\tGLOB=%d\n", GLOB);
4915}
4916REGISTER_TEST(Run, 101)
4917}  // namespace test101
4918
4919// test102: --fast-mode=yes vs. --initialization-bit=yes {{{1
4920namespace test102 {
4921const int HG_CACHELINE_SIZE = 64;
4922
4923Mutex MU;
4924
4925const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4926int array[ARRAY_SIZE + 1];
4927int * GLOB = &array[ARRAY_SIZE/2];
4928/*
4929  We use sizeof(array) == 4 * HG_CACHELINE_SIZE to be sure that GLOB points
4930  to a memory inside a CacheLineZ which is inside array's memory range
4931*/
4932
4933void Reader() {
4934  usleep(200000);
4935  CHECK(777 == GLOB[0]);
4936  usleep(400000);
4937  CHECK(777 == GLOB[1]);
4938}
4939
4940void Run() {
4941  MyThreadArray t(Reader);
4942  if (!Tsan_FastMode())
4943    ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB+0, "test102: TP. FN with --fast-mode=yes");
4944  ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB+1, "test102: TP");
4945  printf("test102: --fast-mode=yes vs. --initialization-bit=yes\n");
4946
4947  t.Start();
4948  GLOB[0] = 777;
4949  usleep(400000);
4950  GLOB[1] = 777;
4951  t.Join();
4952}
4953
4954REGISTER_TEST2(Run, 102, FEATURE)
4955}  // namespace test102
4956
4957// test103: Access different memory locations with different LockSets {{{1
4958namespace test103 {
4959const int N_MUTEXES = 6;
4960const int LOCKSET_INTERSECTION_SIZE = 3;
4961
4962int data[1 << LOCKSET_INTERSECTION_SIZE] = {0};
4963Mutex MU[N_MUTEXES];
4964
4965inline int LS_to_idx (int ls) {
4966  return (ls >> (N_MUTEXES - LOCKSET_INTERSECTION_SIZE))
4967      & ((1 << LOCKSET_INTERSECTION_SIZE) - 1);
4968}
4969
4970void Worker() {
4971  for (int ls = 0; ls < (1 << N_MUTEXES); ls++) {
4972    if (LS_to_idx(ls) == 0)
4973      continue;
4974    for (int m = 0; m < N_MUTEXES; m++)
4975      if (ls & (1 << m))
4976        MU[m].Lock();
4977
4978    data[LS_to_idx(ls)]++;
4979
4980    for (int m = N_MUTEXES - 1; m >= 0; m--)
4981      if (ls & (1 << m))
4982        MU[m].Unlock();
4983  }
4984}
4985
4986void Run() {
4987  printf("test103: Access different memory locations with different LockSets\n");
4988  MyThreadArray t(Worker, Worker, Worker, Worker);
4989  t.Start();
4990  t.Join();
4991}
4992REGISTER_TEST2(Run, 103, FEATURE)
4993}  // namespace test103
4994
4995// test104: TP. Simple race (write vs write). Heap mem. {{{1
4996namespace test104 {
4997int     *GLOB = NULL;
4998void Worker() {
4999  *GLOB = 1;
5000}
5001
5002void Parent() {
5003  MyThread t(Worker);
5004  t.Start();
5005  usleep(100000);
5006  *GLOB = 2;
5007  t.Join();
5008}
5009void Run() {
5010  GLOB = (int*)memalign(64, sizeof(int));
5011  *GLOB = 0;
5012  ANNOTATE_EXPECT_RACE(GLOB, "test104. TP.");
5013  ANNOTATE_TRACE_MEMORY(GLOB);
5014  printf("test104: positive\n");
5015  Parent();
5016  printf("\tGLOB=%d\n", *GLOB);
5017  free(GLOB);
5018}
5019REGISTER_TEST(Run, 104);
5020}  // namespace test104
5021
5022
5023// test105: Checks how stack grows. {{{1
5024namespace test105 {
5025int     GLOB = 0;
5026
5027void F1() {
5028  int ar[32];
5029//  ANNOTATE_TRACE_MEMORY(&ar[0]);
5030//  ANNOTATE_TRACE_MEMORY(&ar[31]);
5031  ar[0] = 1;
5032  ar[31] = 1;
5033}
5034
5035void Worker() {
5036  int ar[32];
5037//  ANNOTATE_TRACE_MEMORY(&ar[0]);
5038//  ANNOTATE_TRACE_MEMORY(&ar[31]);
5039  ar[0] = 1;
5040  ar[31] = 1;
5041  F1();
5042}
5043
5044void Run() {
5045  printf("test105: negative\n");
5046  Worker();
5047  MyThread t(Worker);
5048  t.Start();
5049  t.Join();
5050  printf("\tGLOB=%d\n", GLOB);
5051}
5052REGISTER_TEST(Run, 105)
5053}  // namespace test105
5054
5055
5056// test106: TN. pthread_once. {{{1
5057namespace test106 {
5058int     *GLOB = NULL;
5059static pthread_once_t once = PTHREAD_ONCE_INIT;
5060void Init() {
5061  GLOB = new int;
5062  ANNOTATE_TRACE_MEMORY(GLOB);
5063  *GLOB = 777;
5064}
5065
5066void Worker0() {
5067  pthread_once(&once, Init);
5068}
5069void Worker1() {
5070  usleep(100000);
5071  pthread_once(&once, Init);
5072  CHECK(*GLOB == 777);
5073}
5074
5075
5076void Run() {
5077  printf("test106: negative\n");
5078  MyThreadArray t(Worker0, Worker1, Worker1, Worker1);
5079  t.Start();
5080  t.Join();
5081  printf("\tGLOB=%d\n", *GLOB);
5082}
5083REGISTER_TEST2(Run, 106, FEATURE)
5084}  // namespace test106
5085
5086
5087// test107: Test for ANNOTATE_EXPECT_RACE {{{1
5088namespace test107 {
5089int     GLOB = 0;
5090void Run() {
5091  printf("test107: negative\n");
5092  ANNOTATE_EXPECT_RACE(&GLOB, "No race in fact. Just checking the tool.");
5093  printf("\tGLOB=%d\n", GLOB);
5094}
5095REGISTER_TEST2(Run, 107, FEATURE|EXCLUDE_FROM_ALL)
5096}  // namespace test107
5097
5098
5099// test108: TN. initialization of static object. {{{1
5100namespace test108 {
5101// Here we have a function-level static object.
5102// Starting from gcc 4 this is therad safe,
5103// but is is not thread safe with many other compilers.
5104//
5105// Helgrind supports this kind of initialization by
5106// intercepting __cxa_guard_acquire/__cxa_guard_release
5107// and ignoring all accesses between them.
5108// Helgrind also intercepts pthread_once in the same manner.
5109class Foo {
5110 public:
5111  Foo() {
5112    ANNOTATE_TRACE_MEMORY(&a_);
5113    a_ = 42;
5114  }
5115  void Check() const { CHECK(a_ == 42); }
5116 private:
5117  int a_;
5118};
5119
5120const Foo *GetFoo() {
5121  static const Foo *foo = new Foo();
5122  return foo;
5123}
5124void Worker0() {
5125  GetFoo();
5126}
5127
5128void Worker() {
5129  usleep(200000);
5130  const Foo *foo = GetFoo();
5131  foo->Check();
5132}
5133
5134
5135void Run() {
5136  printf("test108: negative, initialization of static object\n");
5137  MyThreadArray t(Worker0, Worker, Worker);
5138  t.Start();
5139  t.Join();
5140}
5141REGISTER_TEST2(Run, 108, FEATURE)
5142}  // namespace test108
5143
5144
5145// test109: TN. Checking happens before between parent and child threads. {{{1
5146namespace test109 {
5147// Check that the detector correctly connects
5148//   pthread_create with the new thread
5149// and
5150//   thread exit with pthread_join
5151const int N = 32;
5152static int GLOB[N];
5153
5154void Worker(void *a) {
5155  usleep(10000);
5156//  printf("--Worker : %ld %p\n", (int*)a - GLOB, (void*)pthread_self());
5157  int *arg = (int*)a;
5158  (*arg)++;
5159}
5160
5161void Run() {
5162  printf("test109: negative\n");
5163  MyThread *t[N];
5164  for (int i  = 0; i < N; i++) {
5165    t[i] = new MyThread(Worker, &GLOB[i]);
5166  }
5167  for (int i  = 0; i < N; i++) {
5168    ANNOTATE_TRACE_MEMORY(&GLOB[i]);
5169    GLOB[i] = 1;
5170    t[i]->Start();
5171//    printf("--Started: %p\n", (void*)t[i]->tid());
5172  }
5173  for (int i  = 0; i < N; i++) {
5174//    printf("--Joining: %p\n", (void*)t[i]->tid());
5175    t[i]->Join();
5176//    printf("--Joined : %p\n", (void*)t[i]->tid());
5177    GLOB[i]++;
5178  }
5179  for (int i  = 0; i < N; i++) delete t[i];
5180
5181  printf("\tGLOB=%d\n", GLOB[13]);
5182}
5183REGISTER_TEST(Run, 109)
5184}  // namespace test109
5185
5186
5187// test110: TP. Simple races with stack, global and heap objects. {{{1
5188namespace test110 {
5189int        GLOB = 0;
5190static int STATIC;
5191
5192int       *STACK = 0;
5193
5194int       *MALLOC;
5195int       *CALLOC;
5196int       *REALLOC;
5197int       *VALLOC;
5198int       *PVALLOC;
5199int       *MEMALIGN;
5200int       *POSIX_MEMALIGN;
5201int       *MMAP;
5202
5203int       *NEW;
5204int       *NEW_ARR;
5205
5206void Worker() {
5207  GLOB++;
5208  STATIC++;
5209
5210  (*STACK)++;
5211
5212  (*MALLOC)++;
5213  (*CALLOC)++;
5214  (*REALLOC)++;
5215  (*VALLOC)++;
5216  (*PVALLOC)++;
5217  (*MEMALIGN)++;
5218  (*POSIX_MEMALIGN)++;
5219  (*MMAP)++;
5220
5221  (*NEW)++;
5222  (*NEW_ARR)++;
5223}
5224void Run() {
5225  int x = 0;
5226  STACK = &x;
5227
5228  MALLOC = (int*)malloc(sizeof(int));
5229  CALLOC = (int*)calloc(1, sizeof(int));
5230  REALLOC = (int*)realloc(NULL, sizeof(int));
5231  VALLOC = (int*)valloc(sizeof(int));
5232  PVALLOC = (int*)valloc(sizeof(int));  // TODO: pvalloc breaks helgrind.
5233  MEMALIGN = (int*)memalign(64, sizeof(int));
5234  CHECK(0 == posix_memalign((void**)&POSIX_MEMALIGN, 64, sizeof(int)));
5235  MMAP = (int*)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
5236                    MAP_PRIVATE | MAP_ANON, -1, 0);
5237
5238  NEW     = new int;
5239  NEW_ARR = new int[10];
5240
5241
5242  FAST_MODE_INIT(STACK);
5243  ANNOTATE_EXPECT_RACE(STACK, "real race on stack object");
5244  FAST_MODE_INIT(&GLOB);
5245  ANNOTATE_EXPECT_RACE(&GLOB, "real race on global object");
5246  FAST_MODE_INIT(&STATIC);
5247  ANNOTATE_EXPECT_RACE(&STATIC, "real race on a static global object");
5248  FAST_MODE_INIT(MALLOC);
5249  ANNOTATE_EXPECT_RACE(MALLOC, "real race on a malloc-ed object");
5250  FAST_MODE_INIT(CALLOC);
5251  ANNOTATE_EXPECT_RACE(CALLOC, "real race on a calloc-ed object");
5252  FAST_MODE_INIT(REALLOC);
5253  ANNOTATE_EXPECT_RACE(REALLOC, "real race on a realloc-ed object");
5254  FAST_MODE_INIT(VALLOC);
5255  ANNOTATE_EXPECT_RACE(VALLOC, "real race on a valloc-ed object");
5256  FAST_MODE_INIT(PVALLOC);
5257  ANNOTATE_EXPECT_RACE(PVALLOC, "real race on a pvalloc-ed object");
5258  FAST_MODE_INIT(MEMALIGN);
5259  ANNOTATE_EXPECT_RACE(MEMALIGN, "real race on a memalign-ed object");
5260  FAST_MODE_INIT(POSIX_MEMALIGN);
5261  ANNOTATE_EXPECT_RACE(POSIX_MEMALIGN, "real race on a posix_memalign-ed object");
5262  FAST_MODE_INIT(MMAP);
5263  ANNOTATE_EXPECT_RACE(MMAP, "real race on a mmap-ed object");
5264
5265  FAST_MODE_INIT(NEW);
5266  ANNOTATE_EXPECT_RACE(NEW, "real race on a new-ed object");
5267  FAST_MODE_INIT(NEW_ARR);
5268  ANNOTATE_EXPECT_RACE(NEW_ARR, "real race on a new[]-ed object");
5269
5270  MyThreadArray t(Worker, Worker, Worker);
5271  t.Start();
5272  t.Join();
5273  printf("test110: positive (race on a stack object)\n");
5274  printf("\tSTACK=%d\n", *STACK);
5275  CHECK(GLOB <= 3);
5276  CHECK(STATIC <= 3);
5277
5278  free(MALLOC);
5279  free(CALLOC);
5280  free(REALLOC);
5281  free(VALLOC);
5282  free(PVALLOC);
5283  free(MEMALIGN);
5284  free(POSIX_MEMALIGN);
5285  munmap(MMAP, sizeof(int));
5286  delete NEW;
5287  delete [] NEW_ARR;
5288}
5289REGISTER_TEST(Run, 110)
5290}  // namespace test110
5291
5292
5293// test111: TN. Unit test for a bug related to stack handling. {{{1
5294namespace test111 {
5295char     *GLOB = 0;
5296bool COND = false;
5297Mutex mu;
5298const int N = 3000;
5299
5300void write_to_p(char *p, int val) {
5301  for (int i = 0; i < N; i++)
5302    p[i] = val;
5303}
5304
5305static bool ArgIsTrue(bool *arg) {
5306//  printf("ArgIsTrue: %d tid=%d\n", *arg, (int)pthread_self());
5307  return *arg == true;
5308}
5309
5310void f1() {
5311  char some_stack[N];
5312  write_to_p(some_stack, 1);
5313  mu.LockWhen(Condition(&ArgIsTrue, &COND));
5314  mu.Unlock();
5315}
5316
5317void f2() {
5318  char some_stack[N];
5319  char some_more_stack[N];
5320  write_to_p(some_stack, 2);
5321  write_to_p(some_more_stack, 2);
5322}
5323
5324void f0() { f2(); }
5325
5326void Worker1() {
5327  f0();
5328  f1();
5329  f2();
5330}
5331
5332void Worker2() {
5333  usleep(100000);
5334  mu.Lock();
5335  COND = true;
5336  mu.Unlock();
5337}
5338
5339void Run() {
5340  printf("test111: regression test\n");
5341  MyThreadArray t(Worker1, Worker1, Worker2);
5342//  AnnotateSetVerbosity(__FILE__, __LINE__, 3);
5343  t.Start();
5344  t.Join();
5345//  AnnotateSetVerbosity(__FILE__, __LINE__, 1);
5346}
5347REGISTER_TEST2(Run, 111, FEATURE)
5348}  // namespace test111
5349
5350// test112: STAB. Test for ANNOTATE_PUBLISH_MEMORY_RANGE{{{1
5351namespace test112 {
5352char     *GLOB = 0;
5353const int N = 64 * 5;
5354Mutex mu;
5355bool ready = false; // under mu
5356int beg, end; // under mu
5357
5358Mutex mu1;
5359
5360void Worker() {
5361
5362  bool is_ready = false;
5363  int b, e;
5364  while (!is_ready) {
5365    mu.Lock();
5366    is_ready = ready;
5367    b = beg;
5368    e = end;
5369    mu.Unlock();
5370    usleep(1000);
5371  }
5372
5373  mu1.Lock();
5374  for (int i = b; i < e; i++) {
5375    GLOB[i]++;
5376  }
5377  mu1.Unlock();
5378}
5379
5380void PublishRange(int b, int e) {
5381  MyThreadArray t(Worker, Worker);
5382  ready = false; // runs before other threads
5383  t.Start();
5384
5385  ANNOTATE_NEW_MEMORY(GLOB + b, e - b);
5386  ANNOTATE_TRACE_MEMORY(GLOB + b);
5387  for (int j = b; j < e; j++) {
5388    GLOB[j] = 0;
5389  }
5390  ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB + b, e - b);
5391
5392  // hand off
5393  mu.Lock();
5394  ready = true;
5395  beg = b;
5396  end = e;
5397  mu.Unlock();
5398
5399  t.Join();
5400}
5401
5402void Run() {
5403  printf("test112: stability (ANNOTATE_PUBLISH_MEMORY_RANGE)\n");
5404  GLOB = new char [N];
5405
5406  PublishRange(0, 10);
5407  PublishRange(3, 5);
5408
5409  PublishRange(12, 13);
5410  PublishRange(10, 14);
5411
5412  PublishRange(15, 17);
5413  PublishRange(16, 18);
5414
5415  // do few more random publishes.
5416  for (int i = 0; i < 20; i++) {
5417    int beg = rand() % N;
5418    int size = (rand() % (N - beg)) + 1;
5419    CHECK(size > 0);
5420    CHECK(beg + size <= N);
5421    PublishRange(beg, beg + size);
5422  }
5423
5424  printf("GLOB = %d\n", (int)GLOB[0]);
5425}
5426REGISTER_TEST2(Run, 112, STABILITY)
5427}  // namespace test112
5428
5429
5430// test113: PERF. A lot of lock/unlock calls. Many locks {{{1
5431namespace    test113 {
5432const int kNumIter = 100000;
5433const int kNumLocks = 7;
5434Mutex   MU[kNumLocks];
5435void Run() {
5436  printf("test113: perf\n");
5437  for (int i = 0; i < kNumIter; i++ ) {
5438    for (int j = 0; j < kNumLocks; j++) {
5439      if (i & (1 << j)) MU[j].Lock();
5440    }
5441    for (int j = kNumLocks - 1; j >= 0; j--) {
5442      if (i & (1 << j)) MU[j].Unlock();
5443    }
5444  }
5445}
5446REGISTER_TEST(Run, 113)
5447}  // namespace test113
5448
5449
5450// test114: STAB. Recursive lock. {{{1
5451namespace    test114 {
5452int Bar() {
5453  static int bar = 1;
5454  return bar;
5455}
5456int Foo() {
5457  static int foo = Bar();
5458  return foo;
5459}
5460void Worker() {
5461  static int x = Foo();
5462  CHECK(x == 1);
5463}
5464void Run() {
5465  printf("test114: stab\n");
5466  MyThreadArray t(Worker, Worker);
5467  t.Start();
5468  t.Join();
5469}
5470REGISTER_TEST(Run, 114)
5471}  // namespace test114
5472
5473
5474// test115: TN. sem_open. {{{1
5475namespace    test115 {
5476int tid = 0;
5477Mutex mu;
5478const char *kSemName = "drt-test-sem";
5479
5480int GLOB = 0;
5481
5482sem_t *DoSemOpen() {
5483  // TODO: there is some race report inside sem_open
5484  // for which suppressions do not work... (???)
5485  ANNOTATE_IGNORE_WRITES_BEGIN();
5486  sem_t *sem = sem_open(kSemName, O_CREAT, 0600, 3);
5487  ANNOTATE_IGNORE_WRITES_END();
5488  return sem;
5489}
5490
5491void Worker() {
5492  mu.Lock();
5493  int my_tid = tid++;
5494  mu.Unlock();
5495
5496  if (my_tid == 0) {
5497    GLOB = 1;
5498  }
5499
5500  // if the detector observes a happens-before arc between
5501  // sem_open and sem_wait, it will be silent.
5502  sem_t *sem = DoSemOpen();
5503  usleep(100000);
5504  CHECK(sem != SEM_FAILED);
5505  CHECK(sem_wait(sem) == 0);
5506
5507  if (my_tid > 0) {
5508    CHECK(GLOB == 1);
5509  }
5510}
5511
5512void Run() {
5513  printf("test115: stab (sem_open())\n");
5514
5515  // just check that sem_open is not completely broken
5516  sem_unlink(kSemName);
5517  sem_t* sem = DoSemOpen();
5518  CHECK(sem != SEM_FAILED);
5519  CHECK(sem_wait(sem) == 0);
5520  sem_unlink(kSemName);
5521
5522  // check that sem_open and sem_wait create a happens-before arc.
5523  MyThreadArray t(Worker, Worker, Worker);
5524  t.Start();
5525  t.Join();
5526  // clean up
5527  sem_unlink(kSemName);
5528}
5529REGISTER_TEST(Run, 115)
5530}  // namespace test115
5531
5532
5533// test116: TN. some operations with string<> objects. {{{1
5534namespace test116 {
5535
5536void Worker() {
5537  string A[10], B[10], C[10];
5538  for (int i = 0; i < 1000; i++) {
5539    for (int j = 0; j < 10; j++) {
5540      string &a = A[j];
5541      string &b = B[j];
5542      string &c = C[j];
5543      a = "sdl;fkjhasdflksj df";
5544      b = "sdf sdf;ljsd ";
5545      c = "'sfdf df";
5546      c = b;
5547      a = c;
5548      b = a;
5549      swap(a,b);
5550      swap(b,c);
5551    }
5552    for (int j = 0; j < 10; j++) {
5553      string &a = A[j];
5554      string &b = B[j];
5555      string &c = C[j];
5556      a.clear();
5557      b.clear();
5558      c.clear();
5559    }
5560  }
5561}
5562
5563void Run() {
5564  printf("test116: negative (strings)\n");
5565  MyThreadArray t(Worker, Worker, Worker);
5566  t.Start();
5567  t.Join();
5568}
5569REGISTER_TEST2(Run, 116, FEATURE|EXCLUDE_FROM_ALL)
5570}  // namespace test116
5571
5572// test117: TN. Many calls to function-scope static init. {{{1
5573namespace test117 {
5574const int N = 50;
5575
5576int Foo() {
5577  usleep(20000);
5578  return 1;
5579}
5580
5581void Worker(void *a) {
5582  static int foo = Foo();
5583  CHECK(foo == 1);
5584}
5585
5586void Run() {
5587  printf("test117: negative\n");
5588  MyThread *t[N];
5589  for (int i  = 0; i < N; i++) {
5590    t[i] = new MyThread(Worker);
5591  }
5592  for (int i  = 0; i < N; i++) {
5593    t[i]->Start();
5594  }
5595  for (int i  = 0; i < N; i++) {
5596    t[i]->Join();
5597  }
5598  for (int i  = 0; i < N; i++) delete t[i];
5599}
5600REGISTER_TEST(Run, 117)
5601}  // namespace test117
5602
5603
5604
5605// test118 PERF: One signal, multiple waits. {{{1
5606namespace   test118 {
5607int     GLOB = 0;
5608const int kNumIter = 2000000;
5609void Signaller() {
5610  usleep(50000);
5611  ANNOTATE_CONDVAR_SIGNAL(&GLOB);
5612}
5613void Waiter() {
5614  for (int i = 0; i < kNumIter; i++) {
5615    ANNOTATE_CONDVAR_WAIT(&GLOB);
5616    if (i == kNumIter / 2)
5617      usleep(100000);
5618  }
5619}
5620void Run() {
5621  printf("test118: perf\n");
5622  MyThreadArray t(Signaller, Waiter, Signaller, Waiter);
5623  t.Start();
5624  t.Join();
5625  printf("\tGLOB=%d\n", GLOB);
5626}
5627REGISTER_TEST(Run, 118)
5628}  // namespace test118
5629
5630
5631// test119: TP. Testing that malloc does not introduce any HB arc. {{{1
5632namespace test119 {
5633int     GLOB = 0;
5634void Worker1() {
5635  GLOB = 1;
5636  free(malloc(123));
5637}
5638void Worker2() {
5639  usleep(100000);
5640  free(malloc(345));
5641  GLOB = 2;
5642}
5643void Run() {
5644  printf("test119: positive (checking if malloc creates HB arcs)\n");
5645  FAST_MODE_INIT(&GLOB);
5646  if (!(Tsan_PureHappensBefore() && kMallocUsesMutex))
5647    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "true race");
5648  MyThreadArray t(Worker1, Worker2);
5649  t.Start();
5650  t.Join();
5651  printf("\tGLOB=%d\n", GLOB);
5652}
5653REGISTER_TEST(Run, 119)
5654}  // namespace test119
5655
5656
5657// test120: TP. Thread1: write then read. Thread2: read. {{{1
5658namespace test120 {
5659int     GLOB = 0;
5660
5661void Thread1() {
5662  GLOB = 1;           // write
5663  CHECK(GLOB);        // read
5664}
5665
5666void Thread2() {
5667  usleep(100000);
5668  CHECK(GLOB >= 0);   // read
5669}
5670
5671void Run() {
5672  FAST_MODE_INIT(&GLOB);
5673  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "TP (T1: write then read, T2: read)");
5674  printf("test120: positive\n");
5675  MyThreadArray t(Thread1, Thread2);
5676  GLOB = 1;
5677  t.Start();
5678  t.Join();
5679  printf("\tGLOB=%d\n", GLOB);
5680}
5681REGISTER_TEST(Run, 120)
5682}  // namespace test120
5683
5684
5685// test121: TP. Example of double-checked-locking  {{{1
5686namespace test121 {
5687struct Foo {
5688  uintptr_t a, b[15];
5689} __attribute__ ((aligned (64)));
5690
5691static Mutex mu;
5692static Foo  *foo;
5693
5694void InitMe() {
5695  if (!foo) {
5696    MutexLock lock(&mu);
5697    if (!foo) {
5698      ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo, "test121. Double-checked locking (ptr)");
5699      foo = new Foo;
5700      if (!Tsan_FastMode())
5701        ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo->a, "test121. Double-checked locking (obj)");
5702      foo->a = 42;
5703    }
5704  }
5705}
5706
5707void UseMe() {
5708  InitMe();
5709  CHECK(foo && foo->a == 42);
5710}
5711
5712void Worker1() { UseMe(); }
5713void Worker2() { UseMe(); }
5714void Worker3() { UseMe(); }
5715
5716
5717void Run() {
5718  FAST_MODE_INIT(&foo);
5719  printf("test121: TP. Example of double-checked-locking\n");
5720  MyThreadArray t1(Worker1, Worker2, Worker3);
5721  t1.Start();
5722  t1.Join();
5723  delete foo;
5724}
5725REGISTER_TEST(Run, 121)
5726}  // namespace test121
5727
5728// test122 TP: Simple test with RWLock {{{1
5729namespace  test122 {
5730int     VAR1 = 0;
5731int     VAR2 = 0;
5732RWLock mu;
5733
5734void WriteWhileHoldingReaderLock(int *p) {
5735  usleep(100000);
5736  ReaderLockScoped lock(&mu);  // Reader lock for writing. -- bug.
5737  (*p)++;
5738}
5739
5740void CorrectWrite(int *p) {
5741  WriterLockScoped lock(&mu);
5742  (*p)++;
5743}
5744
5745void Thread1() { WriteWhileHoldingReaderLock(&VAR1); }
5746void Thread2() { CorrectWrite(&VAR1); }
5747void Thread3() { CorrectWrite(&VAR2); }
5748void Thread4() { WriteWhileHoldingReaderLock(&VAR2); }
5749
5750
5751void Run() {
5752  printf("test122: positive (rw-lock)\n");
5753  VAR1 = 0;
5754  VAR2 = 0;
5755  ANNOTATE_TRACE_MEMORY(&VAR1);
5756  ANNOTATE_TRACE_MEMORY(&VAR2);
5757  if (!Tsan_PureHappensBefore()) {
5758    ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR1, "test122. TP. ReaderLock-ed while writing");
5759    ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR2, "test122. TP. ReaderLock-ed while writing");
5760  }
5761  MyThreadArray t(Thread1, Thread2, Thread3, Thread4);
5762  t.Start();
5763  t.Join();
5764}
5765REGISTER_TEST(Run, 122)
5766}  // namespace test122
5767
5768
5769// test123 TP: accesses of different sizes. {{{1
5770namespace test123 {
5771
5772uint64_t MEM[8];
5773
5774#define GenericWrite(p,size,off) { \
5775  if (size == 64) {\
5776    CHECK(off == 0);\
5777    (p)[off] = 1;\
5778  } else if (size == 32) {\
5779    CHECK(off <= 2);\
5780    uint32_t *x = (uint32_t*)(p);\
5781    x[off] = 1;\
5782  } else if (size == 16) {\
5783    CHECK(off <= 4);\
5784    uint16_t *x = (uint16_t*)(p);\
5785    x[off] = 1;\
5786  } else if (size == 8) {\
5787    CHECK(off <= 8);\
5788    uint8_t *x = (uint8_t*)(p);\
5789    x[off] = 1;\
5790  } else {\
5791    CHECK(0);\
5792  }\
5793}\
5794
5795// Q. Hey dude, why so many functions?
5796// A. I need different stack traces for different accesses.
5797
5798void Wr64_0() { GenericWrite(&MEM[0], 64, 0); }
5799void Wr64_1() { GenericWrite(&MEM[1], 64, 0); }
5800void Wr64_2() { GenericWrite(&MEM[2], 64, 0); }
5801void Wr64_3() { GenericWrite(&MEM[3], 64, 0); }
5802void Wr64_4() { GenericWrite(&MEM[4], 64, 0); }
5803void Wr64_5() { GenericWrite(&MEM[5], 64, 0); }
5804void Wr64_6() { GenericWrite(&MEM[6], 64, 0); }
5805void Wr64_7() { GenericWrite(&MEM[7], 64, 0); }
5806
5807void Wr32_0() { GenericWrite(&MEM[0], 32, 0); }
5808void Wr32_1() { GenericWrite(&MEM[1], 32, 1); }
5809void Wr32_2() { GenericWrite(&MEM[2], 32, 0); }
5810void Wr32_3() { GenericWrite(&MEM[3], 32, 1); }
5811void Wr32_4() { GenericWrite(&MEM[4], 32, 0); }
5812void Wr32_5() { GenericWrite(&MEM[5], 32, 1); }
5813void Wr32_6() { GenericWrite(&MEM[6], 32, 0); }
5814void Wr32_7() { GenericWrite(&MEM[7], 32, 1); }
5815
5816void Wr16_0() { GenericWrite(&MEM[0], 16, 0); }
5817void Wr16_1() { GenericWrite(&MEM[1], 16, 1); }
5818void Wr16_2() { GenericWrite(&MEM[2], 16, 2); }
5819void Wr16_3() { GenericWrite(&MEM[3], 16, 3); }
5820void Wr16_4() { GenericWrite(&MEM[4], 16, 0); }
5821void Wr16_5() { GenericWrite(&MEM[5], 16, 1); }
5822void Wr16_6() { GenericWrite(&MEM[6], 16, 2); }
5823void Wr16_7() { GenericWrite(&MEM[7], 16, 3); }
5824
5825void Wr8_0() { GenericWrite(&MEM[0], 8, 0); }
5826void Wr8_1() { GenericWrite(&MEM[1], 8, 1); }
5827void Wr8_2() { GenericWrite(&MEM[2], 8, 2); }
5828void Wr8_3() { GenericWrite(&MEM[3], 8, 3); }
5829void Wr8_4() { GenericWrite(&MEM[4], 8, 4); }
5830void Wr8_5() { GenericWrite(&MEM[5], 8, 5); }
5831void Wr8_6() { GenericWrite(&MEM[6], 8, 6); }
5832void Wr8_7() { GenericWrite(&MEM[7], 8, 7); }
5833
5834void WriteAll64() {
5835  Wr64_0();
5836  Wr64_1();
5837  Wr64_2();
5838  Wr64_3();
5839  Wr64_4();
5840  Wr64_5();
5841  Wr64_6();
5842  Wr64_7();
5843}
5844
5845void WriteAll32() {
5846  Wr32_0();
5847  Wr32_1();
5848  Wr32_2();
5849  Wr32_3();
5850  Wr32_4();
5851  Wr32_5();
5852  Wr32_6();
5853  Wr32_7();
5854}
5855
5856void WriteAll16() {
5857  Wr16_0();
5858  Wr16_1();
5859  Wr16_2();
5860  Wr16_3();
5861  Wr16_4();
5862  Wr16_5();
5863  Wr16_6();
5864  Wr16_7();
5865}
5866
5867void WriteAll8() {
5868  Wr8_0();
5869  Wr8_1();
5870  Wr8_2();
5871  Wr8_3();
5872  Wr8_4();
5873  Wr8_5();
5874  Wr8_6();
5875  Wr8_7();
5876}
5877
5878void W00() { WriteAll64(); }
5879void W01() { WriteAll64(); }
5880void W02() { WriteAll64(); }
5881
5882void W10() { WriteAll32(); }
5883void W11() { WriteAll32(); }
5884void W12() { WriteAll32(); }
5885
5886void W20() { WriteAll16(); }
5887void W21() { WriteAll16(); }
5888void W22() { WriteAll16(); }
5889
5890void W30() { WriteAll8(); }
5891void W31() { WriteAll8(); }
5892void W32() { WriteAll8(); }
5893
5894typedef void (*F)(void);
5895
5896void TestTwoSizes(F f1, F f2) {
5897  // first f1, then f2
5898  ANNOTATE_NEW_MEMORY(MEM, sizeof(MEM));
5899  memset(MEM, 0, sizeof(MEM));
5900  MyThreadArray t1(f1, f2);
5901  t1.Start();
5902  t1.Join();
5903  // reverse order
5904  ANNOTATE_NEW_MEMORY(MEM, sizeof(MEM));
5905  memset(MEM, 0, sizeof(MEM));
5906  MyThreadArray t2(f2, f1);
5907  t2.Start();
5908  t2.Join();
5909}
5910
5911void Run() {
5912  printf("test123: positive (different sizes)\n");
5913  TestTwoSizes(W00, W10);
5914//  TestTwoSizes(W01, W20);
5915//  TestTwoSizes(W02, W30);
5916//  TestTwoSizes(W11, W21);
5917//  TestTwoSizes(W12, W31);
5918//  TestTwoSizes(W22, W32);
5919
5920}
5921REGISTER_TEST2(Run, 123, FEATURE|EXCLUDE_FROM_ALL)
5922}  // namespace test123
5923
5924
5925// test124: What happens if we delete an unlocked lock? {{{1
5926namespace test124 {
5927// This test does not worg with pthreads (you can't call
5928// pthread_mutex_destroy on a locked lock).
5929int     GLOB = 0;
5930const int N = 1000;
5931void Worker() {
5932  Mutex *a_large_local_array_of_mutexes;
5933  a_large_local_array_of_mutexes = new Mutex[N];
5934  for (int i = 0; i < N; i++) {
5935    a_large_local_array_of_mutexes[i].Lock();
5936  }
5937  delete []a_large_local_array_of_mutexes;
5938  GLOB = 1;
5939}
5940
5941void Run() {
5942  printf("test124: negative\n");
5943  MyThreadArray t(Worker, Worker, Worker);
5944  t.Start();
5945  t.Join();
5946  printf("\tGLOB=%d\n", GLOB);
5947}
5948REGISTER_TEST2(Run, 124, FEATURE|EXCLUDE_FROM_ALL)
5949}  // namespace test124
5950
5951
5952// test125 TN: Backwards lock (annotated). {{{1
5953namespace test125 {
5954// This test uses "Backwards mutex" locking protocol.
5955// We take a *reader* lock when writing to a per-thread data
5956// (GLOB[thread_num])  and we take a *writer* lock when we
5957// are reading from the entire array at once.
5958//
5959// Such locking protocol is not understood by ThreadSanitizer's
5960// hybrid state machine. So, you either have to use a pure-happens-before
5961// detector ("tsan --pure-happens-before") or apply pure happens-before mode
5962// to this particular lock by using ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu).
5963
5964const int n_threads = 3;
5965RWLock   mu;
5966int     GLOB[n_threads];
5967
5968int adder_num; // updated atomically.
5969
5970void Adder() {
5971  int my_num = AtomicIncrement(&adder_num, 1);
5972
5973  ReaderLockScoped lock(&mu);
5974  GLOB[my_num]++;
5975}
5976
5977void Aggregator() {
5978  int sum = 0;
5979  {
5980    WriterLockScoped lock(&mu);
5981    for (int i = 0; i < n_threads; i++) {
5982      sum += GLOB[i];
5983    }
5984  }
5985  printf("sum=%d\n", sum);
5986}
5987
5988void Run() {
5989  printf("test125: negative\n");
5990
5991  ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu);
5992
5993  // run Adders, then Aggregator
5994  {
5995    MyThreadArray t(Adder, Adder, Adder, Aggregator);
5996    t.Start();
5997    t.Join();
5998  }
5999
6000  // Run Aggregator first.
6001  adder_num = 0;
6002  {
6003    MyThreadArray t(Aggregator, Adder, Adder, Adder);
6004    t.Start();
6005    t.Join();
6006  }
6007
6008}
6009REGISTER_TEST(Run, 125)
6010}  // namespace test125
6011
6012// test126 TN: test for BlockingCounter {{{1
6013namespace  test126 {
6014BlockingCounter *blocking_counter;
6015int     GLOB = 0;
6016void Worker() {
6017  CHECK(blocking_counter);
6018  CHECK(GLOB == 0);
6019  blocking_counter->DecrementCount();
6020}
6021void Run() {
6022  printf("test126: negative\n");
6023  MyThreadArray t(Worker, Worker, Worker);
6024  blocking_counter = new BlockingCounter(3);
6025  t.Start();
6026  blocking_counter->Wait();
6027  GLOB = 1;
6028  t.Join();
6029  printf("\tGLOB=%d\n", GLOB);
6030}
6031REGISTER_TEST(Run, 126)
6032}  // namespace test126
6033
6034
6035// test127. Bad code: unlocking a mutex locked by another thread. {{{1
6036namespace test127 {
6037Mutex mu;
6038void Thread1() {
6039  mu.Lock();
6040}
6041void Thread2() {
6042  usleep(100000);
6043  mu.Unlock();
6044}
6045void Run() {
6046  printf("test127: unlocking a mutex locked by another thread.\n");
6047  MyThreadArray t(Thread1, Thread2);
6048  t.Start();
6049  t.Join();
6050}
6051REGISTER_TEST(Run, 127)
6052}  // namespace test127
6053
6054// test128. Suppressed code in concurrent accesses {{{1
6055// Please use --suppressions=unittest.supp flag when running this test.
6056namespace test128 {
6057Mutex mu;
6058int GLOB = 0;
6059void Worker() {
6060  usleep(100000);
6061  mu.Lock();
6062  GLOB++;
6063  mu.Unlock();
6064}
6065void ThisFunctionShouldBeSuppressed() {
6066  GLOB++;
6067}
6068void Run() {
6069  printf("test128: Suppressed code in concurrent accesses.\n");
6070  MyThreadArray t(Worker, ThisFunctionShouldBeSuppressed);
6071  t.Start();
6072  t.Join();
6073}
6074REGISTER_TEST2(Run, 128, FEATURE | EXCLUDE_FROM_ALL)
6075}  // namespace test128
6076
6077// test129: TN. Synchronization via ReaderLockWhen(). {{{1
6078namespace test129 {
6079int     GLOB = 0;
6080Mutex   MU;
6081bool WeirdCondition(int* param) {
6082  *param = GLOB;  // a write into Waiter's memory
6083  return GLOB > 0;
6084}
6085void Waiter() {
6086  int param = 0;
6087  MU.ReaderLockWhen(Condition(WeirdCondition, &param));
6088  MU.ReaderUnlock();
6089  CHECK(GLOB > 0);
6090  CHECK(param > 0);
6091}
6092void Waker() {
6093  usleep(100000);  // Make sure the waiter blocks.
6094  MU.Lock();
6095  GLOB++;
6096  MU.Unlock();     // calls ANNOTATE_CONDVAR_SIGNAL;
6097}
6098void Run() {
6099  printf("test129: Synchronization via ReaderLockWhen()\n");
6100  MyThread mt(Waiter, NULL, "Waiter Thread");
6101  mt.Start();
6102  Waker();
6103  mt.Join();
6104  printf("\tGLOB=%d\n", GLOB);
6105}
6106REGISTER_TEST2(Run, 129, FEATURE);
6107}  // namespace test129
6108
6109// test130: TN. Per-thread. {{{1
6110namespace test130 {
6111#ifndef NO_TLS
6112// This test verifies that the race detector handles
6113// thread-local storage (TLS) correctly.
6114// As of 09-03-30 ThreadSanitizer has a bug:
6115//   - Thread1 starts
6116//   - Thread1 touches per_thread_global
6117//   - Thread1 ends
6118//   - Thread2 starts (and there is no happens-before relation between it and
6119//   Thread1)
6120//   - Thread2 touches per_thread_global
6121// It may happen so that Thread2 will have per_thread_global in the same address
6122// as Thread1. Since there is no happens-before relation between threads,
6123// ThreadSanitizer reports a race.
6124//
6125// test131 does the same for stack.
6126
6127static __thread int per_thread_global[10] = {0};
6128
6129void RealWorker() {  // Touch per_thread_global.
6130  per_thread_global[1]++;
6131  errno++;
6132}
6133
6134void Worker() {  // Spawn few threads that touch per_thread_global.
6135  MyThreadArray t(RealWorker, RealWorker);
6136  t.Start();
6137  t.Join();
6138}
6139void Worker0() { sleep(0); Worker(); }
6140void Worker1() { sleep(1); Worker(); }
6141void Worker2() { sleep(2); Worker(); }
6142void Worker3() { sleep(3); Worker(); }
6143
6144void Run() {
6145  printf("test130: Per-thread\n");
6146  MyThreadArray t1(Worker0, Worker1, Worker2, Worker3);
6147  t1.Start();
6148  t1.Join();
6149  printf("\tper_thread_global=%d\n", per_thread_global[1]);
6150}
6151REGISTER_TEST(Run, 130)
6152#endif // NO_TLS
6153}  // namespace test130
6154
6155
6156// test131: TN. Stack. {{{1
6157namespace test131 {
6158// Same as test130, but for stack.
6159
6160void RealWorker() {  // Touch stack.
6161  int stack_var = 0;
6162  stack_var++;
6163}
6164
6165void Worker() {  // Spawn few threads that touch stack.
6166  MyThreadArray t(RealWorker, RealWorker);
6167  t.Start();
6168  t.Join();
6169}
6170void Worker0() { sleep(0); Worker(); }
6171void Worker1() { sleep(1); Worker(); }
6172void Worker2() { sleep(2); Worker(); }
6173void Worker3() { sleep(3); Worker(); }
6174
6175void Run() {
6176  printf("test131: stack\n");
6177  MyThreadArray t(Worker0, Worker1, Worker2, Worker3);
6178  t.Start();
6179  t.Join();
6180}
6181REGISTER_TEST(Run, 131)
6182}  // namespace test131
6183
6184
6185// test132: TP. Simple race (write vs write). Works in fast-mode. {{{1
6186namespace test132 {
6187int     GLOB = 0;
6188void Worker() { GLOB = 1; }
6189
6190void Run1() {
6191  FAST_MODE_INIT(&GLOB);
6192  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test132");
6193  printf("test132: positive; &GLOB=%p\n", &GLOB);
6194  ANNOTATE_TRACE_MEMORY(&GLOB);
6195  GLOB = 7;
6196  MyThreadArray t(Worker, Worker);
6197  t.Start();
6198  t.Join();
6199}
6200
6201void Run() {
6202  Run1();
6203}
6204REGISTER_TEST(Run, 132);
6205}  // namespace test132
6206
6207
6208// test133: TP. Simple race (write vs write). Works in fast mode. {{{1
6209namespace test133 {
6210// Same as test132, but everything is run from a separate thread spawned from
6211// the main thread.
6212int     GLOB = 0;
6213void Worker() { GLOB = 1; }
6214
6215void Run1() {
6216  FAST_MODE_INIT(&GLOB);
6217  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test133");
6218  printf("test133: positive; &GLOB=%p\n", &GLOB);
6219  ANNOTATE_TRACE_MEMORY(&GLOB);
6220  GLOB = 7;
6221  MyThreadArray t(Worker, Worker);
6222  t.Start();
6223  t.Join();
6224}
6225void Run() {
6226  MyThread t(Run1);
6227  t.Start();
6228  t.Join();
6229}
6230REGISTER_TEST(Run, 133);
6231}  // namespace test133
6232
6233
6234// test134 TN. Swap. Variant of test79. {{{1
6235namespace test134 {
6236#if 0
6237typedef __gnu_cxx::hash_map<int, int> map_t;
6238#else
6239typedef std::map<int, int> map_t;
6240#endif
6241map_t   map;
6242Mutex   mu;
6243// Here we use swap to pass map between threads.
6244// The synchronization is correct, but w/o the annotation
6245// any hybrid detector will complain.
6246
6247// Swap is very unfriendly to the lock-set (and hybrid) race detectors.
6248// Since tmp is destructed outside the mutex, we need to have a happens-before
6249// arc between any prior access to map and here.
6250// Since the internals of tmp are created ouside the mutex and are passed to
6251// other thread, we need to have a h-b arc between here and any future access.
6252// These arcs can be created by HAPPENS_{BEFORE,AFTER} annotations, but it is
6253// much simpler to apply pure-happens-before mode to the mutex mu.
6254void Swapper() {
6255  map_t tmp;
6256  MutexLock lock(&mu);
6257  ANNOTATE_HAPPENS_AFTER(&map);
6258  // We swap the new empty map 'tmp' with 'map'.
6259  map.swap(tmp);
6260  ANNOTATE_HAPPENS_BEFORE(&map);
6261  // tmp (which is the old version of map) is destroyed here.
6262}
6263
6264void Worker() {
6265  MutexLock lock(&mu);
6266  ANNOTATE_HAPPENS_AFTER(&map);
6267  map[1]++;
6268  ANNOTATE_HAPPENS_BEFORE(&map);
6269}
6270
6271void Run() {
6272  printf("test134: negative (swap)\n");
6273  // ********************** Shorter way: ***********************
6274  // ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu);
6275  MyThreadArray t(Worker, Worker, Swapper, Worker, Worker);
6276  t.Start();
6277  t.Join();
6278}
6279REGISTER_TEST(Run, 134)
6280}  // namespace test134
6281
6282// test135 TN. Swap. Variant of test79. {{{1
6283namespace test135 {
6284
6285void SubWorker() {
6286  const long SIZE = 65536;
6287  for (int i = 0; i < 32; i++) {
6288    int *ptr = (int*)mmap(NULL, SIZE, PROT_READ | PROT_WRITE,
6289                          MAP_PRIVATE | MAP_ANON, -1, 0);
6290    *ptr = 42;
6291    munmap(ptr, SIZE);
6292  }
6293}
6294
6295void Worker() {
6296  MyThreadArray t(SubWorker, SubWorker, SubWorker, SubWorker);
6297  t.Start();
6298  t.Join();
6299}
6300
6301void Run() {
6302  printf("test135: negative (mmap)\n");
6303  MyThreadArray t(Worker, Worker, Worker, Worker);
6304  t.Start();
6305  t.Join();
6306}
6307REGISTER_TEST(Run, 135)
6308}  // namespace test135
6309
6310// test136. Unlock twice. {{{1
6311namespace test136 {
6312void Run() {
6313  printf("test136: unlock twice\n");
6314  pthread_mutexattr_t attr;
6315  CHECK(0 == pthread_mutexattr_init(&attr));
6316  CHECK(0 == pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK));
6317
6318  pthread_mutex_t mu;
6319  CHECK(0 == pthread_mutex_init(&mu, &attr));
6320  CHECK(0 == pthread_mutex_lock(&mu));
6321  CHECK(0 == pthread_mutex_unlock(&mu));
6322  int ret_unlock = pthread_mutex_unlock(&mu);  // unlocking twice.
6323  int ret_destroy = pthread_mutex_destroy(&mu);
6324  printf("  pthread_mutex_unlock returned %d\n", ret_unlock);
6325  printf("  pthread_mutex_destroy returned %d\n", ret_destroy);
6326
6327}
6328
6329REGISTER_TEST(Run, 136)
6330}  // namespace test136
6331
6332// test137 TP. Races on stack variables. {{{1
6333namespace test137 {
6334int GLOB = 0;
6335ProducerConsumerQueue q(10);
6336
6337void Worker() {
6338  int stack;
6339  int *tmp = (int*)q.Get();
6340  (*tmp)++;
6341  int *racey = &stack;
6342  q.Put(racey);
6343  (*racey)++;
6344  usleep(150000);
6345  // We may miss the races if we sleep less due to die_memory events...
6346}
6347
6348void Run() {
6349  int tmp = 0;
6350  printf("test137: TP. Races on stack variables.\n");
6351  q.Put(&tmp);
6352  MyThreadArray t(Worker, Worker, Worker, Worker);
6353  t.Start();
6354  t.Join();
6355  q.Get();
6356}
6357
6358REGISTER_TEST2(Run, 137, FEATURE | EXCLUDE_FROM_ALL)
6359}  // namespace test137
6360
6361// test138 FN. Two closures hit the same thread in ThreadPool. {{{1
6362namespace test138 {
6363int GLOB = 0;
6364
6365void Worker() {
6366  usleep(100000);
6367  GLOB++;
6368}
6369
6370void Run() {
6371  FAST_MODE_INIT(&GLOB);
6372  printf("test138: FN. Two closures hit the same thread in ThreadPool.\n");
6373
6374  // When using thread pools, two concurrent callbacks might be scheduled
6375  // onto the same executor thread. As a result, unnecessary happens-before
6376  // relation may be introduced between callbacks.
6377  // If we set the number of executor threads to 1, any known data
6378  // race detector will be silent. However, the same situation may happen
6379  // with any number of executor threads (with some probability).
6380  ThreadPool tp(1);
6381  tp.StartWorkers();
6382  tp.Add(NewCallback(Worker));
6383  tp.Add(NewCallback(Worker));
6384}
6385
6386REGISTER_TEST2(Run, 138, FEATURE)
6387}  // namespace test138
6388
6389// test139: FN. A true race hidden by reference counting annotation. {{{1
6390namespace test139 {
6391int GLOB = 0;
6392RefCountedClass *obj;
6393
6394void Worker1() {
6395  GLOB++;  // First access.
6396  obj->Unref();
6397}
6398
6399void Worker2() {
6400  usleep(100000);
6401  obj->Unref();
6402  GLOB++;  // Second access.
6403}
6404
6405void Run() {
6406  FAST_MODE_INIT(&GLOB);
6407  printf("test139: FN. A true race hidden by reference counting annotation.\n");
6408
6409  obj = new RefCountedClass;
6410  obj->AnnotateUnref();
6411  obj->Ref();
6412  obj->Ref();
6413  MyThreadArray mt(Worker1, Worker2);
6414  mt.Start();
6415  mt.Join();
6416}
6417
6418REGISTER_TEST2(Run, 139, FEATURE)
6419}  // namespace test139
6420
6421// test140 TN. Swap. Variant of test79 and test134. {{{1
6422namespace test140 {
6423#if 0
6424typedef __gnu_cxx::hash_map<int, int> Container;
6425#else
6426typedef std::map<int,int>             Container;
6427#endif
6428Mutex mu;
6429static Container container;
6430
6431// Here we use swap to pass a Container between threads.
6432// The synchronization is correct, but w/o the annotation
6433// any hybrid detector will complain.
6434//
6435// Unlike the test134, we try to have a minimal set of annotations
6436// so that extra h-b arcs do not hide other races.
6437
6438// Swap is very unfriendly to the lock-set (and hybrid) race detectors.
6439// Since tmp is destructed outside the mutex, we need to have a happens-before
6440// arc between any prior access to map and here.
6441// Since the internals of tmp are created ouside the mutex and are passed to
6442// other thread, we need to have a h-b arc between here and any future access.
6443//
6444// We want to be able to annotate swapper so that we don't need to annotate
6445// anything else.
6446void Swapper() {
6447  Container tmp;
6448  tmp[1] = tmp[2] = tmp[3] = 0;
6449  {
6450    MutexLock lock(&mu);
6451    container.swap(tmp);
6452    // we are unpublishing the old container.
6453    ANNOTATE_UNPUBLISH_MEMORY_RANGE(&container, sizeof(container));
6454    // we are publishing the new container.
6455    ANNOTATE_PUBLISH_MEMORY_RANGE(&container, sizeof(container));
6456  }
6457  tmp[1]++;
6458  tmp[2]++;
6459  // tmp (which is the old version of container) is destroyed here.
6460}
6461
6462void Worker() {
6463  MutexLock lock(&mu);
6464  container[1]++;
6465  int *v = &container[2];
6466  for (int i = 0; i < 10; i++) {
6467    // if uncommented, this will break ANNOTATE_UNPUBLISH_MEMORY_RANGE():
6468    // ANNOTATE_HAPPENS_BEFORE(v);
6469    if (i % 3) {
6470      (*v)++;
6471    }
6472  }
6473}
6474
6475void Run() {
6476  printf("test140: negative (swap) %p\n", &container);
6477  MyThreadArray t(Worker, Worker, Swapper, Worker, Worker);
6478  t.Start();
6479  t.Join();
6480}
6481REGISTER_TEST(Run, 140)
6482}  // namespace test140
6483
6484// test141 FP. unlink/fopen, rmdir/opendir. {{{1
6485namespace test141 {
6486int GLOB1 = 0,
6487    GLOB2 = 0;
6488char *dir_name = NULL,
6489     *filename = NULL;
6490
6491void Waker1() {
6492  usleep(100000);
6493  GLOB1 = 1;  // Write
6494  // unlink deletes a file 'filename'
6495  // which exits spin-loop in Waiter1().
6496  printf("  Deleting file...\n");
6497  CHECK(unlink(filename) == 0);
6498}
6499
6500void Waiter1() {
6501  FILE *tmp;
6502  while ((tmp = fopen(filename, "r")) != NULL) {
6503    fclose(tmp);
6504    usleep(10000);
6505  }
6506  printf("  ...file has been deleted\n");
6507  GLOB1 = 2;  // Write
6508}
6509
6510void Waker2() {
6511  usleep(100000);
6512  GLOB2 = 1;  // Write
6513  // rmdir deletes a directory 'dir_name'
6514  // which exit spin-loop in Waker().
6515  printf("  Deleting directory...\n");
6516  CHECK(rmdir(dir_name) == 0);
6517}
6518
6519void Waiter2() {
6520  DIR *tmp;
6521  while ((tmp = opendir(dir_name)) != NULL) {
6522    closedir(tmp);
6523    usleep(10000);
6524  }
6525  printf("  ...directory has been deleted\n");
6526  GLOB2 = 2;
6527}
6528
6529void Run() {
6530  FAST_MODE_INIT(&GLOB1);
6531  FAST_MODE_INIT(&GLOB2);
6532  printf("test141: FP. unlink/fopen, rmdir/opendir.\n");
6533
6534  dir_name = strdup("/tmp/tsan-XXXXXX");
6535  mkdtemp(dir_name);
6536
6537  filename = strdup((std::string() + dir_name + "/XXXXXX").c_str());
6538  const int fd = mkstemp(filename);
6539  CHECK(fd >= 0);
6540  close(fd);
6541
6542  MyThreadArray mta1(Waker1, Waiter1);
6543  mta1.Start();
6544  mta1.Join();
6545
6546  MyThreadArray mta2(Waker2, Waiter2);
6547  mta2.Start();
6548  mta2.Join();
6549}
6550REGISTER_TEST(Run, 141)
6551}  // namespace test141
6552
6553// test300: {{{1
6554namespace test300 {
6555int     GLOB = 0;
6556void Run() {
6557}
6558REGISTER_TEST2(Run, 300, RACE_DEMO)
6559}  // namespace test300
6560
6561// test301: Simple race.  {{{1
6562namespace test301 {
6563Mutex mu1;  // This Mutex guards var.
6564Mutex mu2;  // This Mutex is not related to var.
6565int   var;  // GUARDED_BY(mu1)
6566
6567void Thread1() {  // Runs in thread named 'test-thread-1'.
6568  MutexLock lock(&mu1);  // Correct Mutex.
6569  var = 1;
6570}
6571
6572void Thread2() {  // Runs in thread named 'test-thread-2'.
6573  MutexLock lock(&mu2);  // Wrong Mutex.
6574  var = 2;
6575}
6576
6577void Run() {
6578  var = 0;
6579  printf("test301: simple race.\n");
6580  MyThread t1(Thread1, NULL, "test-thread-1");
6581  MyThread t2(Thread2, NULL, "test-thread-2");
6582  t1.Start();
6583  t2.Start();
6584  t1.Join();
6585  t2.Join();
6586}
6587REGISTER_TEST2(Run, 301, RACE_DEMO)
6588}  // namespace test301
6589
6590// test302: Complex race which happens at least twice.  {{{1
6591namespace test302 {
6592// In this test we have many different accesses to GLOB and only one access
6593// is not synchronized properly.
6594int     GLOB = 0;
6595
6596Mutex MU1;
6597Mutex MU2;
6598void Worker() {
6599  for(int i = 0; i < 100; i++) {
6600    switch(i % 4) {
6601      case 0:
6602        // This read is protected correctly.
6603        MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock();
6604        break;
6605      case 1:
6606        // Here we used the wrong lock! The reason of the race is here.
6607        MU2.Lock(); CHECK(GLOB >= 0); MU2.Unlock();
6608        break;
6609      case 2:
6610        // This read is protected correctly.
6611        MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock();
6612        break;
6613      case 3:
6614        // This write is protected correctly.
6615        MU1.Lock(); GLOB++; MU1.Unlock();
6616        break;
6617    }
6618    // sleep a bit so that the threads interleave
6619    // and the race happens at least twice.
6620    usleep(100);
6621  }
6622}
6623
6624void Run() {
6625  printf("test302: Complex race that happens twice.\n");
6626  MyThread t1(Worker), t2(Worker);
6627  t1.Start();
6628  t2.Start();
6629  t1.Join();   t2.Join();
6630}
6631REGISTER_TEST2(Run, 302, RACE_DEMO)
6632}  // namespace test302
6633
6634
6635// test303: Need to trace the memory to understand the report. {{{1
6636namespace test303 {
6637int     GLOB = 0;
6638
6639Mutex MU;
6640void Worker1() { CHECK(GLOB >= 0); }
6641void Worker2() { MU.Lock(); GLOB=1;  MU.Unlock();}
6642
6643void Run() {
6644  printf("test303: a race that needs annotations.\n");
6645  ANNOTATE_TRACE_MEMORY(&GLOB);
6646  MyThreadArray t(Worker1, Worker2);
6647  t.Start();
6648  t.Join();
6649}
6650REGISTER_TEST2(Run, 303, RACE_DEMO)
6651}  // namespace test303
6652
6653
6654
6655// test304: Can not trace the memory, since it is a library object. {{{1
6656namespace test304 {
6657string *STR;
6658Mutex   MU;
6659
6660void Worker1() {
6661  sleep(0);
6662  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6663  MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
6664}
6665void Worker2() {
6666  sleep(1);
6667  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6668  CHECK(STR->length() >= 4); // Unprotected!
6669}
6670void Worker3() {
6671  sleep(2);
6672  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6673  MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
6674}
6675void Worker4() {
6676  sleep(3);
6677  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6678  MU.Lock(); *STR += " + a very very long string"; MU.Unlock();
6679}
6680
6681void Run() {
6682  STR = new string ("The String");
6683  printf("test304: a race where memory tracing does not work.\n");
6684  MyThreadArray t(Worker1, Worker2, Worker3, Worker4);
6685  t.Start();
6686  t.Join();
6687
6688  printf("%s\n", STR->c_str());
6689  delete STR;
6690}
6691REGISTER_TEST2(Run, 304, RACE_DEMO)
6692}  // namespace test304
6693
6694
6695
6696// test305: A bit more tricky: two locks used inconsistenly. {{{1
6697namespace test305 {
6698int     GLOB = 0;
6699
6700// In this test GLOB is protected by MU1 and MU2, but inconsistently.
6701// The TRACES observed by helgrind are:
6702// TRACE[1]: Access{T2/S2 wr} -> new State{Mod; #LS=2; #SS=1; T2/S2}
6703// TRACE[2]: Access{T4/S9 wr} -> new State{Mod; #LS=1; #SS=2; T2/S2, T4/S9}
6704// TRACE[3]: Access{T5/S13 wr} -> new State{Mod; #LS=1; #SS=3; T2/S2, T4/S9, T5/S13}
6705// TRACE[4]: Access{T6/S19 wr} -> new State{Mod; #LS=0; #SS=4; T2/S2, T4/S9, T5/S13, T6/S19}
6706//
6707// The guilty access is either Worker2() or Worker4(), depending on
6708// which mutex is supposed to protect GLOB.
6709Mutex MU1;
6710Mutex MU2;
6711void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
6712void Worker2() { MU1.Lock();             GLOB=2;               MU1.Unlock(); }
6713void Worker3() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
6714void Worker4() {             MU2.Lock(); GLOB=4; MU2.Unlock();               }
6715
6716void Run() {
6717  ANNOTATE_TRACE_MEMORY(&GLOB);
6718  printf("test305: simple race.\n");
6719  MyThread t1(Worker1), t2(Worker2), t3(Worker3), t4(Worker4);
6720  t1.Start(); usleep(100);
6721  t2.Start(); usleep(100);
6722  t3.Start(); usleep(100);
6723  t4.Start(); usleep(100);
6724  t1.Join(); t2.Join(); t3.Join(); t4.Join();
6725}
6726REGISTER_TEST2(Run, 305, RACE_DEMO)
6727}  // namespace test305
6728
6729// test306: Two locks are used to protect a var.  {{{1
6730namespace test306 {
6731int     GLOB = 0;
6732// Thread1 and Thread2 access the var under two locks.
6733// Thread3 uses no locks.
6734
6735Mutex MU1;
6736Mutex MU2;
6737void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
6738void Worker2() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
6739void Worker3() {                         GLOB=4;               }
6740
6741void Run() {
6742  ANNOTATE_TRACE_MEMORY(&GLOB);
6743  printf("test306: simple race.\n");
6744  MyThread t1(Worker1), t2(Worker2), t3(Worker3);
6745  t1.Start(); usleep(100);
6746  t2.Start(); usleep(100);
6747  t3.Start(); usleep(100);
6748  t1.Join(); t2.Join(); t3.Join();
6749}
6750REGISTER_TEST2(Run, 306, RACE_DEMO)
6751}  // namespace test306
6752
6753// test307: Simple race, code with control flow  {{{1
6754namespace test307 {
6755int     *GLOB = 0;
6756volatile /*to fake the compiler*/ bool some_condition = true;
6757
6758
6759void SomeFunc() { }
6760
6761int FunctionWithControlFlow() {
6762  int unrelated_stuff = 0;
6763  unrelated_stuff++;
6764  SomeFunc();                // "--keep-history=1" will point somewhere here.
6765  if (some_condition) {      // Or here
6766    if (some_condition) {
6767      unrelated_stuff++;     // Or here.
6768      unrelated_stuff++;
6769      (*GLOB)++;             // "--keep-history=2" will point here (experimental).
6770    }
6771  }
6772  usleep(100000);
6773  return unrelated_stuff;
6774}
6775
6776void Worker1() { FunctionWithControlFlow(); }
6777void Worker2() { Worker1(); }
6778void Worker3() { Worker2(); }
6779void Worker4() { Worker3(); }
6780
6781void Run() {
6782  GLOB = new int;
6783  *GLOB = 1;
6784  printf("test307: simple race, code with control flow\n");
6785  MyThreadArray t1(Worker1, Worker2, Worker3, Worker4);
6786  t1.Start();
6787  t1.Join();
6788}
6789REGISTER_TEST2(Run, 307, RACE_DEMO)
6790}  // namespace test307
6791
6792// test308: Example of double-checked-locking  {{{1
6793namespace test308 {
6794struct Foo {
6795  int a;
6796};
6797
6798static int   is_inited = 0;
6799static Mutex lock;
6800static Foo  *foo;
6801
6802void InitMe() {
6803  if (!is_inited) {
6804    lock.Lock();
6805      if (!is_inited) {
6806        foo = new Foo;
6807        foo->a = 42;
6808        is_inited = 1;
6809      }
6810    lock.Unlock();
6811  }
6812}
6813
6814void UseMe() {
6815  InitMe();
6816  CHECK(foo && foo->a == 42);
6817}
6818
6819void Worker1() { UseMe(); }
6820void Worker2() { UseMe(); }
6821void Worker3() { UseMe(); }
6822
6823
6824void Run() {
6825  ANNOTATE_TRACE_MEMORY(&is_inited);
6826  printf("test308: Example of double-checked-locking\n");
6827  MyThreadArray t1(Worker1, Worker2, Worker3);
6828  t1.Start();
6829  t1.Join();
6830}
6831REGISTER_TEST2(Run, 308, RACE_DEMO)
6832}  // namespace test308
6833
6834// test309: Simple race on an STL object.  {{{1
6835namespace test309 {
6836string  GLOB;
6837
6838void Worker1() {
6839  GLOB="Thread1";
6840}
6841void Worker2() {
6842  usleep(100000);
6843  GLOB="Booooooooooo";
6844}
6845
6846void Run() {
6847  printf("test309: simple race on an STL object.\n");
6848  MyThread t1(Worker1), t2(Worker2);
6849  t1.Start();
6850  t2.Start();
6851  t1.Join();   t2.Join();
6852}
6853REGISTER_TEST2(Run, 309, RACE_DEMO)
6854}  // namespace test309
6855
6856// test310: One more simple race.  {{{1
6857namespace test310 {
6858int     *PTR = NULL;  // GUARDED_BY(mu1)
6859
6860Mutex mu1;  // Protects PTR.
6861Mutex mu2;  // Unrelated to PTR.
6862Mutex mu3;  // Unrelated to PTR.
6863
6864void Writer1() {
6865  MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
6866  MutexLock lock1(&mu1);  // Protect PTR.
6867  *PTR = 1;
6868}
6869
6870void Writer2() {
6871  MutexLock lock2(&mu2);  // This lock is unrelated to PTR.
6872  MutexLock lock1(&mu1);  // Protect PTR.
6873  int some_unrelated_stuff = 0;
6874  if (some_unrelated_stuff == 0)
6875    some_unrelated_stuff++;
6876  *PTR = 2;
6877}
6878
6879
6880void Reader() {
6881  MutexLock lock2(&mu2);  // Oh, gosh, this is a wrong mutex!
6882  CHECK(*PTR <= 2);
6883}
6884
6885// Some functions to make the stack trace non-trivial.
6886void DoWrite1() { Writer1();  }
6887void Thread1()  { DoWrite1(); }
6888
6889void DoWrite2() { Writer2();  }
6890void Thread2()  { DoWrite2(); }
6891
6892void DoRead()  { Reader();  }
6893void Thread3() { DoRead();  }
6894
6895void Run() {
6896  printf("test310: simple race.\n");
6897  PTR = new int;
6898  ANNOTATE_TRACE_MEMORY(PTR);
6899  *PTR = 0;
6900  MyThread t1(Thread1, NULL, "writer1"),
6901           t2(Thread2, NULL, "writer2"),
6902           t3(Thread3, NULL, "buggy reader");
6903  t1.Start();
6904  t2.Start();
6905  usleep(100000);  // Let the writers go first.
6906  t3.Start();
6907
6908  t1.Join();
6909  t2.Join();
6910  t3.Join();
6911}
6912REGISTER_TEST2(Run, 310, RACE_DEMO)
6913}  // namespace test310
6914
6915// test311: Yet another simple race.  {{{1
6916namespace test311 {
6917int     *PTR = NULL;  // GUARDED_BY(mu1)
6918
6919Mutex mu1;  // Protects PTR.
6920Mutex mu2;  // Unrelated to PTR.
6921Mutex mu3;  // Unrelated to PTR.
6922
6923void GoodWriter1() {
6924  MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
6925  MutexLock lock1(&mu1);  // Protect PTR.
6926  *PTR = 1;
6927}
6928
6929void GoodWriter2() {
6930  MutexLock lock2(&mu2);  // This lock is unrelated to PTR.
6931  MutexLock lock1(&mu1);  // Protect PTR.
6932  *PTR = 2;
6933}
6934
6935void GoodReader() {
6936  MutexLock lock1(&mu1);  // Protect PTR.
6937  CHECK(*PTR >= 0);
6938}
6939
6940void BuggyWriter() {
6941  MutexLock lock2(&mu2);  // Wrong mutex!
6942  *PTR = 3;
6943}
6944
6945// Some functions to make the stack trace non-trivial.
6946void DoWrite1() { GoodWriter1();  }
6947void Thread1()  { DoWrite1(); }
6948
6949void DoWrite2() { GoodWriter2();  }
6950void Thread2()  { DoWrite2(); }
6951
6952void DoGoodRead()  { GoodReader();  }
6953void Thread3()     { DoGoodRead();  }
6954
6955void DoBadWrite()  { BuggyWriter(); }
6956void Thread4()     { DoBadWrite(); }
6957
6958void Run() {
6959  printf("test311: simple race.\n");
6960  PTR = new int;
6961  ANNOTATE_TRACE_MEMORY(PTR);
6962  *PTR = 0;
6963  MyThread t1(Thread1, NULL, "good writer1"),
6964           t2(Thread2, NULL, "good writer2"),
6965           t3(Thread3, NULL, "good reader"),
6966           t4(Thread4, NULL, "buggy writer");
6967  t1.Start();
6968  t3.Start();
6969  // t2 goes after t3. This way a pure happens-before detector has no chance.
6970  usleep(10000);
6971  t2.Start();
6972  usleep(100000);  // Let the good folks go first.
6973  t4.Start();
6974
6975  t1.Join();
6976  t2.Join();
6977  t3.Join();
6978  t4.Join();
6979}
6980REGISTER_TEST2(Run, 311, RACE_DEMO)
6981}  // namespace test311
6982
6983// test312: A test with a very deep stack. {{{1
6984namespace test312 {
6985int     GLOB = 0;
6986void RaceyWrite() { GLOB++; }
6987void Func1() { RaceyWrite(); }
6988void Func2() { Func1(); }
6989void Func3() { Func2(); }
6990void Func4() { Func3(); }
6991void Func5() { Func4(); }
6992void Func6() { Func5(); }
6993void Func7() { Func6(); }
6994void Func8() { Func7(); }
6995void Func9() { Func8(); }
6996void Func10() { Func9(); }
6997void Func11() { Func10(); }
6998void Func12() { Func11(); }
6999void Func13() { Func12(); }
7000void Func14() { Func13(); }
7001void Func15() { Func14(); }
7002void Func16() { Func15(); }
7003void Func17() { Func16(); }
7004void Func18() { Func17(); }
7005void Func19() { Func18(); }
7006void Worker() { Func19(); }
7007void Run() {
7008  printf("test312: simple race with deep stack.\n");
7009  MyThreadArray t(Worker, Worker, Worker);
7010  t.Start();
7011  t.Join();
7012}
7013REGISTER_TEST2(Run, 312, RACE_DEMO)
7014}  // namespace test312
7015
7016// test313 TP: test for thread graph output {{{1
7017namespace  test313 {
7018BlockingCounter *blocking_counter;
7019int     GLOB = 0;
7020
7021// Worker(N) will do 2^N increments of GLOB, each increment in a separate thread
7022void Worker(int depth) {
7023  CHECK(depth >= 0);
7024  if (depth > 0) {
7025    ThreadPool pool(2);
7026    pool.StartWorkers();
7027    pool.Add(NewCallback(Worker, depth-1));
7028    pool.Add(NewCallback(Worker, depth-1));
7029  } else {
7030    GLOB++; // Race here
7031  }
7032}
7033void Run() {
7034  printf("test313: positive\n");
7035  Worker(4);
7036  printf("\tGLOB=%d\n", GLOB);
7037}
7038REGISTER_TEST2(Run, 313, RACE_DEMO)
7039}  // namespace test313
7040
7041
7042
7043// test400: Demo of a simple false positive. {{{1
7044namespace test400 {
7045static Mutex mu;
7046static vector<int> *vec; // GUARDED_BY(mu);
7047
7048void InitAllBeforeStartingThreads() {
7049  vec = new vector<int>;
7050  vec->push_back(1);
7051  vec->push_back(2);
7052}
7053
7054void Thread1() {
7055  MutexLock lock(&mu);
7056  vec->pop_back();
7057}
7058
7059void Thread2() {
7060  MutexLock lock(&mu);
7061  vec->pop_back();
7062}
7063
7064//---- Sub-optimal code ---------
7065size_t NumberOfElementsLeft() {
7066  MutexLock lock(&mu);
7067  return vec->size();
7068}
7069
7070void WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly() {
7071  while(NumberOfElementsLeft()) {
7072    ; // sleep or print or do nothing.
7073  }
7074  // It is now safe to access vec w/o lock.
7075  // But a hybrid detector (like ThreadSanitizer) can't see it.
7076  // Solutions:
7077  //   1. Use pure happens-before detector (e.g. "tsan --pure-happens-before")
7078  //   2. Call ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu)
7079  //      in InitAllBeforeStartingThreads()
7080  //   3. (preferred) Use WaitForAllThreadsToFinish_Good() (see below).
7081  CHECK(vec->empty());
7082  delete vec;
7083}
7084
7085//----- Better code -----------
7086
7087bool NoElementsLeft(vector<int> *v) {
7088  return v->empty();
7089}
7090
7091void WaitForAllThreadsToFinish_Good() {
7092  mu.LockWhen(Condition(NoElementsLeft, vec));
7093  mu.Unlock();
7094
7095  // It is now safe to access vec w/o lock.
7096  CHECK(vec->empty());
7097  delete vec;
7098}
7099
7100
7101void Run() {
7102  MyThreadArray t(Thread1, Thread2);
7103  InitAllBeforeStartingThreads();
7104  t.Start();
7105  WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly();
7106//  WaitForAllThreadsToFinish_Good();
7107  t.Join();
7108}
7109REGISTER_TEST2(Run, 400, RACE_DEMO)
7110}  // namespace test400
7111
7112// test401: Demo of false positive caused by reference counting. {{{1
7113namespace test401 {
7114// A simplified example of reference counting.
7115// DecRef() does ref count increment in a way unfriendly to race detectors.
7116// DecRefAnnotated() does the same in a friendly way.
7117
7118static vector<int> *vec;
7119static int ref_count;
7120
7121void InitAllBeforeStartingThreads(int number_of_threads) {
7122  vec = new vector<int>;
7123  vec->push_back(1);
7124  ref_count = number_of_threads;
7125}
7126
7127// Correct, but unfriendly to race detectors.
7128int DecRef() {
7129  return AtomicIncrement(&ref_count, -1);
7130}
7131
7132// Correct and friendly to race detectors.
7133int DecRefAnnotated() {
7134  ANNOTATE_CONDVAR_SIGNAL(&ref_count);
7135  int res = AtomicIncrement(&ref_count, -1);
7136  if (res == 0) {
7137    ANNOTATE_CONDVAR_WAIT(&ref_count);
7138  }
7139  return res;
7140}
7141
7142void ThreadWorker() {
7143  CHECK(ref_count > 0);
7144  CHECK(vec->size() == 1);
7145  if (DecRef() == 0) {  // Use DecRefAnnotated() instead!
7146    // No one uses vec now ==> delete it.
7147    delete vec;  // A false race may be reported here.
7148    vec = NULL;
7149  }
7150}
7151
7152void Run() {
7153  MyThreadArray t(ThreadWorker, ThreadWorker, ThreadWorker);
7154  InitAllBeforeStartingThreads(3 /*number of threads*/);
7155  t.Start();
7156  t.Join();
7157  CHECK(vec == 0);
7158}
7159REGISTER_TEST2(Run, 401, RACE_DEMO)
7160}  // namespace test401
7161
7162// test501: Manually call PRINT_* annotations {{{1
7163namespace test501 {
7164int  COUNTER = 0;
7165int     GLOB = 0;
7166Mutex muCounter, muGlob[65];
7167
7168void Worker() {
7169   muCounter.Lock();
7170   int myId = ++COUNTER;
7171   muCounter.Unlock();
7172
7173   usleep(100);
7174
7175   muGlob[myId].Lock();
7176   muGlob[0].Lock();
7177   GLOB++;
7178   muGlob[0].Unlock();
7179   muGlob[myId].Unlock();
7180}
7181
7182void Worker_1() {
7183   MyThreadArray ta (Worker, Worker, Worker, Worker);
7184   ta.Start();
7185   usleep(500000);
7186   ta.Join ();
7187}
7188
7189void Worker_2() {
7190   MyThreadArray ta (Worker_1, Worker_1, Worker_1, Worker_1);
7191   ta.Start();
7192   usleep(300000);
7193   ta.Join ();
7194}
7195
7196void Run() {
7197   ANNOTATE_RESET_STATS();
7198   printf("test501: Manually call PRINT_* annotations.\n");
7199   MyThreadArray ta (Worker_2, Worker_2, Worker_2, Worker_2);
7200   ta.Start();
7201   usleep(100000);
7202   ta.Join ();
7203   ANNOTATE_PRINT_MEMORY_USAGE(0);
7204   ANNOTATE_PRINT_STATS();
7205}
7206
7207REGISTER_TEST2(Run, 501, FEATURE | EXCLUDE_FROM_ALL)
7208}  // namespace test501
7209
7210// test502: produce lots of segments without cross-thread relations {{{1
7211namespace test502 {
7212
7213/*
7214 * This test produces ~1Gb of memory usage when run with the following options:
7215 *
7216 * --tool=helgrind
7217 * --trace-after-race=0
7218 * --num-callers=2
7219 * --more-context=no
7220 */
7221
7222Mutex MU;
7223int     GLOB = 0;
7224
7225void TP() {
7226   for (int i = 0; i < 750000; i++) {
7227      MU.Lock();
7228      GLOB++;
7229      MU.Unlock();
7230   }
7231}
7232
7233void Run() {
7234   MyThreadArray t(TP, TP);
7235   printf("test502: produce lots of segments without cross-thread relations\n");
7236
7237   t.Start();
7238   t.Join();
7239}
7240
7241REGISTER_TEST2(Run, 502, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL
7242                              | PERFORMANCE)
7243}  // namespace test502
7244
7245// test503: produce lots of segments with simple HB-relations {{{1
7246// HB cache-miss rate is ~55%
7247namespace test503 {
7248
7249//  |- |  |  |  |  |
7250//  | \|  |  |  |  |
7251//  |  |- |  |  |  |
7252//  |  | \|  |  |  |
7253//  |  |  |- |  |  |
7254//  |  |  | \|  |  |
7255//  |  |  |  |- |  |
7256//  |  |  |  | \|  |
7257//  |  |  |  |  |- |
7258//  |  |  |  |  | \|
7259//  |  |  |  |  |  |----
7260//->|  |  |  |  |  |
7261//  |- |  |  |  |  |
7262//  | \|  |  |  |  |
7263//     ...
7264
7265const int N_threads = 32;
7266const int ARRAY_SIZE = 128;
7267int       GLOB[ARRAY_SIZE];
7268ProducerConsumerQueue *Q[N_threads];
7269int GLOB_limit = 100000;
7270int count = -1;
7271
7272void Worker(){
7273   int myId = AtomicIncrement(&count, 1);
7274
7275   ProducerConsumerQueue &myQ = *Q[myId], &nextQ = *Q[(myId+1) % N_threads];
7276
7277   // this code produces a new SS with each new segment
7278   while (myQ.Get() != NULL) {
7279      for (int i = 0; i < ARRAY_SIZE; i++)
7280         GLOB[i]++;
7281
7282      if (myId == 0 && GLOB[0] > GLOB_limit) {
7283         // Stop all threads
7284         for (int i = 0; i < N_threads; i++)
7285            Q[i]->Put(NULL);
7286      } else
7287         nextQ.Put(GLOB);
7288   }
7289}
7290
7291void Run() {
7292   printf("test503: produce lots of segments with simple HB-relations\n");
7293   for (int i = 0; i < N_threads; i++)
7294      Q[i] = new ProducerConsumerQueue(1);
7295   Q[0]->Put(GLOB);
7296
7297   {
7298      ThreadPool pool(N_threads);
7299      pool.StartWorkers();
7300      for (int i = 0; i < N_threads; i++) {
7301         pool.Add(NewCallback(Worker));
7302      }
7303   } // all folks are joined here.
7304
7305   for (int i = 0; i < N_threads; i++)
7306      delete Q[i];
7307}
7308
7309REGISTER_TEST2(Run, 503, MEMORY_USAGE | PRINT_STATS
7310                  | PERFORMANCE | EXCLUDE_FROM_ALL)
7311}  // namespace test503
7312
7313// test504: force massive cache fetch-wback (50% misses, mostly CacheLineZ) {{{1
7314namespace test504 {
7315
7316const int N_THREADS = 2,
7317          HG_CACHELINE_COUNT = 1 << 16,
7318          HG_CACHELINE_SIZE  = 1 << 6,
7319          HG_CACHE_SIZE = HG_CACHELINE_COUNT * HG_CACHELINE_SIZE;
7320
7321// int gives us ~4x speed of the byte test
7322// 4x array size gives us
7323// total multiplier of 16x over the cachesize
7324// so we can neglect the cached-at-the-end memory
7325const int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
7326          ITERATIONS = 30;
7327int array[ARRAY_SIZE];
7328
7329int count = 0;
7330Mutex count_mu;
7331
7332void Worker() {
7333   count_mu.Lock();
7334   int myId = ++count;
7335   count_mu.Unlock();
7336
7337   // all threads write to different memory locations,
7338   // so no synchronization mechanisms are needed
7339   int lower_bound = ARRAY_SIZE * (myId-1) / N_THREADS,
7340       upper_bound = ARRAY_SIZE * ( myId ) / N_THREADS;
7341   for (int j = 0; j < ITERATIONS; j++)
7342   for (int i = lower_bound; i < upper_bound;
7343            i += HG_CACHELINE_SIZE / sizeof(array[0])) {
7344      array[i] = i; // each array-write generates a cache miss
7345   }
7346}
7347
7348void Run() {
7349   printf("test504: force massive CacheLineZ fetch-wback\n");
7350   MyThreadArray t(Worker, Worker);
7351   t.Start();
7352   t.Join();
7353}
7354
7355REGISTER_TEST2(Run, 504, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7356}  // namespace test504
7357
7358// test505: force massive cache fetch-wback (60% misses) {{{1
7359// modification of test504 - more threads, byte accesses and lots of mutexes
7360// so it produces lots of CacheLineF misses (30-50% of CacheLineZ misses)
7361namespace test505 {
7362
7363const int N_THREADS = 2,
7364          HG_CACHELINE_COUNT = 1 << 16,
7365          HG_CACHELINE_SIZE  = 1 << 6,
7366          HG_CACHE_SIZE = HG_CACHELINE_COUNT * HG_CACHELINE_SIZE;
7367
7368const int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
7369          ITERATIONS = 3;
7370int64_t array[ARRAY_SIZE];
7371
7372int count = 0;
7373Mutex count_mu;
7374
7375void Worker() {
7376   const int N_MUTEXES = 5;
7377   Mutex mu[N_MUTEXES];
7378   count_mu.Lock();
7379   int myId = ++count;
7380   count_mu.Unlock();
7381
7382   // all threads write to different memory locations,
7383   // so no synchronization mechanisms are needed
7384   int lower_bound = ARRAY_SIZE * (myId-1) / N_THREADS,
7385       upper_bound = ARRAY_SIZE * ( myId ) / N_THREADS;
7386   for (int j = 0; j < ITERATIONS; j++)
7387   for (int mutex_id = 0; mutex_id < N_MUTEXES; mutex_id++) {
7388      Mutex *m = & mu[mutex_id];
7389      m->Lock();
7390      for (int i = lower_bound + mutex_id, cnt = 0;
7391               i < upper_bound;
7392               i += HG_CACHELINE_SIZE / sizeof(array[0]), cnt++) {
7393         array[i] = i; // each array-write generates a cache miss
7394      }
7395      m->Unlock();
7396   }
7397}
7398
7399void Run() {
7400   printf("test505: force massive CacheLineF fetch-wback\n");
7401   MyThreadArray t(Worker, Worker);
7402   t.Start();
7403   t.Join();
7404}
7405
7406REGISTER_TEST2(Run, 505, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7407}  // namespace test505
7408
7409// test506: massive HB's using Barriers {{{1
7410// HB cache miss is ~40%
7411// segments consume 10x more memory than SSs
7412// modification of test39
7413namespace test506 {
7414#ifndef NO_BARRIER
7415// Same as test17 but uses Barrier class (pthread_barrier_t).
7416int     GLOB = 0;
7417const int N_threads = 64,
7418          ITERATIONS = 1000;
7419Barrier *barrier[ITERATIONS];
7420Mutex   MU;
7421
7422void Worker() {
7423  for (int i = 0; i < ITERATIONS; i++) {
7424     MU.Lock();
7425     GLOB++;
7426     MU.Unlock();
7427     barrier[i]->Block();
7428  }
7429}
7430void Run() {
7431  printf("test506: massive HB's using Barriers\n");
7432  for (int i = 0; i < ITERATIONS; i++) {
7433     barrier[i] = new Barrier(N_threads);
7434  }
7435  {
7436    ThreadPool pool(N_threads);
7437    pool.StartWorkers();
7438    for (int i = 0; i < N_threads; i++) {
7439      pool.Add(NewCallback(Worker));
7440    }
7441  } // all folks are joined here.
7442  CHECK(GLOB == N_threads * ITERATIONS);
7443  for (int i = 0; i < ITERATIONS; i++) {
7444     delete barrier[i];
7445  }
7446}
7447REGISTER_TEST2(Run, 506, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL);
7448#endif // NO_BARRIER
7449}  // namespace test506
7450
7451// test507: vgHelgrind_initIterAtFM/stackClear benchmark {{{1
7452// vgHelgrind_initIterAtFM/stackClear consume ~8.5%/5.5% CPU
7453namespace test507 {
7454const int N_THREADS    = 1,
7455          BUFFER_SIZE  = 1,
7456          ITERATIONS   = 1 << 20;
7457
7458void Foo() {
7459  struct T {
7460    char temp;
7461    T() {
7462      ANNOTATE_RWLOCK_CREATE(&temp);
7463    }
7464    ~T() {
7465      ANNOTATE_RWLOCK_DESTROY(&temp);
7466    }
7467  } s[BUFFER_SIZE];
7468  s->temp = '\0';
7469}
7470
7471void Worker() {
7472  for (int j = 0; j < ITERATIONS; j++) {
7473    Foo();
7474  }
7475}
7476
7477void Run() {
7478  printf("test507: vgHelgrind_initIterAtFM/stackClear benchmark\n");
7479  {
7480    ThreadPool pool(N_THREADS);
7481    pool.StartWorkers();
7482    for (int i = 0; i < N_THREADS; i++) {
7483      pool.Add(NewCallback(Worker));
7484    }
7485  } // all folks are joined here.
7486}
7487REGISTER_TEST2(Run, 507, EXCLUDE_FROM_ALL);
7488}  // namespace test507
7489
7490// test508: cmp_WordVecs_for_FM benchmark {{{1
7491// 50+% of CPU consumption by cmp_WordVecs_for_FM
7492namespace test508 {
7493const int N_THREADS    = 1,
7494          BUFFER_SIZE  = 1 << 10,
7495          ITERATIONS   = 1 << 9;
7496
7497void Foo() {
7498  struct T {
7499    char temp;
7500    T() {
7501      ANNOTATE_RWLOCK_CREATE(&temp);
7502    }
7503    ~T() {
7504      ANNOTATE_RWLOCK_DESTROY(&temp);
7505    }
7506  } s[BUFFER_SIZE];
7507  s->temp = '\0';
7508}
7509
7510void Worker() {
7511  for (int j = 0; j < ITERATIONS; j++) {
7512    Foo();
7513  }
7514}
7515
7516void Run() {
7517  printf("test508: cmp_WordVecs_for_FM benchmark\n");
7518  {
7519    ThreadPool pool(N_THREADS);
7520    pool.StartWorkers();
7521    for (int i = 0; i < N_THREADS; i++) {
7522      pool.Add(NewCallback(Worker));
7523    }
7524  } // all folks are joined here.
7525}
7526REGISTER_TEST2(Run, 508, EXCLUDE_FROM_ALL);
7527}  // namespace test508
7528
7529// test509: avl_find_node benchmark {{{1
7530// 10+% of CPU consumption by avl_find_node
7531namespace test509 {
7532const int N_THREADS    = 16,
7533          ITERATIONS   = 1 << 8;
7534
7535void Worker() {
7536  std::vector<Mutex*> mu_list;
7537  for (int i = 0; i < ITERATIONS; i++) {
7538    Mutex * mu = new Mutex();
7539    mu_list.push_back(mu);
7540    mu->Lock();
7541  }
7542  for (int i = ITERATIONS - 1; i >= 0; i--) {
7543    Mutex * mu = mu_list[i];
7544    mu->Unlock();
7545    delete mu;
7546  }
7547}
7548
7549void Run() {
7550  printf("test509: avl_find_node benchmark\n");
7551  {
7552    ThreadPool pool(N_THREADS);
7553    pool.StartWorkers();
7554    for (int i = 0; i < N_THREADS; i++) {
7555      pool.Add(NewCallback(Worker));
7556    }
7557  } // all folks are joined here.
7558}
7559REGISTER_TEST2(Run, 509, EXCLUDE_FROM_ALL);
7560}  // namespace test509
7561
7562// test510: SS-recycle test {{{1
7563// this tests shows the case where only ~1% of SS are recycled
7564namespace test510 {
7565const int N_THREADS    = 16,
7566          ITERATIONS   = 1 << 10;
7567int GLOB = 0;
7568
7569void Worker() {
7570  usleep(100000);
7571  for (int i = 0; i < ITERATIONS; i++) {
7572    ANNOTATE_CONDVAR_SIGNAL((void*)0xDeadBeef);
7573    GLOB++;
7574    usleep(10);
7575  }
7576}
7577
7578void Run() {
7579  //ANNOTATE_BENIGN_RACE(&GLOB, "Test");
7580  printf("test510: SS-recycle test\n");
7581  {
7582    ThreadPool pool(N_THREADS);
7583    pool.StartWorkers();
7584    for (int i = 0; i < N_THREADS; i++) {
7585      pool.Add(NewCallback(Worker));
7586    }
7587  } // all folks are joined here.
7588}
7589REGISTER_TEST2(Run, 510, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7590}  // namespace test510
7591
7592// test511: Segment refcounting test ('1' refcounting) {{{1
7593namespace test511 {
7594int GLOB = 0;
7595
7596void Run () {
7597   for (int i = 0; i < 300; i++) {
7598      ANNOTATE_CONDVAR_SIGNAL(&GLOB);
7599      usleep(1000);
7600      GLOB++;
7601      ANNOTATE_CONDVAR_WAIT(&GLOB);
7602      if (i % 100 == 0)
7603         ANNOTATE_PRINT_MEMORY_USAGE(0);
7604   }
7605}
7606REGISTER_TEST2(Run, 511, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7607}  // namespace test511
7608
7609// test512: Segment refcounting test ('S' refcounting) {{{1
7610namespace test512 {
7611int GLOB = 0;
7612sem_t SEM;
7613
7614void Run () {
7615   sem_init(&SEM, 0, 0);
7616   for (int i = 0; i < 300; i++) {
7617      sem_post(&SEM);
7618      usleep(1000);
7619      GLOB++;
7620      sem_wait(&SEM);
7621      /*if (i % 100 == 0)
7622         ANNOTATE_PRINT_MEMORY_USAGE(0);*/
7623   }
7624   sem_destroy(&SEM);
7625}
7626REGISTER_TEST2(Run, 512, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7627}  // namespace test512
7628
7629// test513: --fast-mode benchmark {{{1
7630namespace test513 {
7631
7632const int N_THREADS = 2,
7633          HG_CACHELINE_SIZE  = 1 << 6,
7634          ARRAY_SIZE = HG_CACHELINE_SIZE * 512,
7635          MUTEX_ID_BITS = 8,
7636          MUTEX_ID_MASK = (1 << MUTEX_ID_BITS) - 1;
7637
7638// Each thread has its own cacheline and tackles with it intensively
7639const int ITERATIONS = 1024;
7640int array[N_THREADS][ARRAY_SIZE];
7641
7642int count = 0;
7643Mutex count_mu;
7644Mutex mutex_arr[N_THREADS][MUTEX_ID_BITS];
7645
7646void Worker() {
7647   count_mu.Lock();
7648   int myId = count++;
7649   count_mu.Unlock();
7650
7651   // all threads write to different memory locations
7652   for (int j = 0; j < ITERATIONS; j++) {
7653      int mutex_mask = j & MUTEX_ID_BITS;
7654      for (int m = 0; m < MUTEX_ID_BITS; m++)
7655         if (mutex_mask & (1 << m))
7656            mutex_arr[myId][m].Lock();
7657
7658      for (int i = 0; i < ARRAY_SIZE; i++) {
7659         array[myId][i] = i;
7660      }
7661
7662      for (int m = 0; m < MUTEX_ID_BITS; m++)
7663         if (mutex_mask & (1 << m))
7664            mutex_arr[myId][m].Unlock();
7665   }
7666}
7667
7668void Run() {
7669   printf("test513: --fast-mode benchmark\n");
7670   {
7671      ThreadPool pool(N_THREADS);
7672      pool.StartWorkers();
7673      for (int i = 0; i < N_THREADS; i++) {
7674         pool.Add(NewCallback(Worker));
7675      }
7676   } // all folks are joined here.
7677}
7678
7679REGISTER_TEST2(Run, 513, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7680}  // namespace test513
7681
7682// End {{{1
7683// vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker
7684