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