]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/drd/tests/tsan_unittest.cpp
eb4562100108dca823a421dc12074f1cc9157c97
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / drd / tests / tsan_unittest.cpp
1 /*
2   This file is part of Valgrind, a dynamic binary instrumentation
3   framework.
4
5   Copyright (C) 2008-2008 Google Inc
6      opensource@google.com 
7
8   This program is free software; you can redistribute it and/or
9   modify it under the terms of the GNU General Public License as
10   published by the Free Software Foundation; either version 2 of the
11   License, or (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21   02111-1307, USA.
22
23   The GNU General Public License is contained in the file COPYING.
24 */
25
26 // Author: Konstantin Serebryany <opensource@google.com> 
27 //
28 // This file contains a set of unit tests for a data race detection tool. 
29 //
30 //
31 //
32 // This test can be compiled with pthreads (default) or
33 // with any other library that supports threads, locks, cond vars, etc. 
34 // 
35 // To compile with pthreads: 
36 //   g++  racecheck_unittest.cc dynamic_annotations.cc 
37 //        -lpthread -g -DDYNAMIC_ANNOTATIONS=1
38 // 
39 // To compile with different library: 
40 //   1. cp thread_wrappers_pthread.h thread_wrappers_yourlib.h
41 //   2. edit thread_wrappers_yourlib.h
42 //   3. add '-DTHREAD_WRAPPERS="thread_wrappers_yourlib.h"' to your compilation.
43 //
44 //
45
46 // This test must not include any other file specific to threading library,
47 // everything should be inside THREAD_WRAPPERS. 
48 #ifndef THREAD_WRAPPERS 
49 # define THREAD_WRAPPERS "thread_wrappers_pthread.h"
50 #endif 
51 #include THREAD_WRAPPERS
52
53 #ifndef NEEDS_SEPERATE_RW_LOCK
54 #define RWLock Mutex // Mutex does work as an rw-lock.
55 #define WriterLockScoped MutexLock
56 #define ReaderLockScoped ReaderMutexLock
57 #endif // !NEEDS_SEPERATE_RW_LOCK
58
59
60 // Helgrind memory usage testing stuff
61 // If not present in dynamic_annotations.h/.cc - ignore
62 #ifndef ANNOTATE_RESET_STATS
63 #define ANNOTATE_RESET_STATS() do { } while(0)
64 #endif
65 #ifndef ANNOTATE_PRINT_STATS
66 #define ANNOTATE_PRINT_STATS() do { } while(0)
67 #endif
68 #ifndef ANNOTATE_PRINT_MEMORY_USAGE
69 #define ANNOTATE_PRINT_MEMORY_USAGE(a) do { } while(0)
70 #endif
71 //
72
73 // A function that allows to suppress gcc's warnings about
74 // unused return values in a portable way.
75 template <typename T>
76 static inline void IGNORE_RETURN_VALUE(T v)
77 { }
78
79 #include <vector>
80 #include <string>
81 #include <map>
82 #include <queue>
83 #include <algorithm>
84 #include <cstring>      // strlen(), index(), rindex()
85 #include <ctime>
86 #include <sys/time.h>
87 #include <sys/types.h>
88 #include <sys/stat.h>
89 #include <fcntl.h>
90 #include <sys/mman.h>  // mmap
91 #include <errno.h>
92 #include <stdint.h>    // uintptr_t
93 #include <stdlib.h>
94 #include <dirent.h>
95
96 #ifndef __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
127 CondVar CV; 
128 int     COND = 0;
129
130
131 typedef void (*void_func_void_t)(void);
132 enum 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.
144 Mutex printf_mu;
145 #define printf(args...) \
146     do{ \
147       printf_mu.Lock();\
148       fprintf(stderr, args);\
149       printf_mu.Unlock(); \
150     }while(0)
151
152 long GetTimeInMs() {
153    struct timeval tv;
154    gettimeofday(&tv, NULL);
155    return (tv.tv_sec * 1000L) + (tv.tv_usec / 1000L);
156 }
157
158 struct 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 };
181 std::map<int, Test> TheMapOfTests;
182
183 #define NOINLINE __attribute__ ((noinline))
184 extern "C" void NOINLINE AnnotateSetVerbosity(const char *, int, int) {};
185
186
187 struct 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
198 static bool ArgIsOne(int *arg) { return *arg == 1; };
199 static bool ArgIsZero(int *arg) { return *arg == 0; };
200 static 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
217 inline bool Tsan_PureHappensBefore() {
218   return true;
219 }
220
221 inline 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
234 int 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
278 class 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
318 namespace test00 {
319 int     GLOB = 0;
320 void Run() {
321   printf("test00: negative\n");
322   printf("\tGLOB=%d\n", GLOB);
323 }
324 REGISTER_TEST(Run, 00)
325 }  // namespace test00
326
327
328 // test01: TP. Simple race (write vs write). {{{1
329 namespace test01 {
330 int     GLOB = 0;
331 void Worker() {
332   GLOB = 1; 
333 }
334
335 void Parent() {
336   MyThread t(Worker);
337   t.Start();
338   GLOB = 2;
339   t.Join();
340 }
341 void 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 }
350 REGISTER_TEST(Run, 1);
351 }  // namespace test01
352
353
354 // test02: TN. Synchronization via CondVar. {{{1
355 namespace test02 {
356 int     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)
371 Mutex   MU; 
372
373 void 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
383 void 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 }
394 void Run() {
395   printf("test02: negative\n");
396   Waiter();
397   printf("\tGLOB=%d\n", GLOB);
398 }
399 REGISTER_TEST(Run, 2);
400 }  // namespace test02
401
402
403 // test03: TN. Synchronization via LockWhen, signaller gets there first. {{{1
404 namespace test03 {  
405 int     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)
419 Mutex   MU; 
420
421 void 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 }
429 void 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 }
439 void Run() {
440   printf("test03: negative\n");
441   Waiter();
442   printf("\tGLOB=%d\n", GLOB);
443 }
444 REGISTER_TEST2(Run, 3, FEATURE|NEEDS_ANNOTATIONS);
445 }  // namespace test03
446
447 // test04: TN. Synchronization via PCQ. {{{1
448 namespace test04 {
449 int     GLOB = 0;
450 ProducerConsumerQueue 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
460 void Putter() {
461   GLOB = 1; 
462   Q.Put(NULL);
463 }
464
465 void Getter() {
466   Q.Get();
467   GLOB = 2;
468 }
469
470 void Run() {
471   printf("test04: negative\n");
472   MyThreadArray t(Putter, Getter);
473   t.Start(); 
474   t.Join();
475   printf("\tGLOB=%d\n", GLOB);
476 }
477 REGISTER_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. 
483 namespace test05 {
484 int     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)      
501 Mutex   MU; 
502
503 void Waker() {
504   GLOB = 1; 
505   MU.Lock();
506   COND = 1;
507   CV.Signal(); 
508   MU.Unlock();
509 }
510
511 void 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 }
523 void 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 }
531 REGISTER_TEST(Run, 5);
532 }  // namespace test05
533
534
535 // test06: TN. Synchronization via CondVar, but Waker gets there first.  {{{1
536 namespace test06 {
537 int     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
553 Mutex   MU; 
554
555 void Waker() {
556   GLOB = 1; 
557   MU.Lock();
558   COND = 1;
559   CV.Signal(); 
560   MU.Unlock();
561 }
562
563 void 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 }
577 void Run() {
578   printf("test06: negative\n");
579   Waiter();
580   printf("\tGLOB=%d\n", GLOB);
581 }
582 REGISTER_TEST2(Run, 6, FEATURE|NEEDS_ANNOTATIONS);
583 }  // namespace test06
584
585
586 // test07: TN. Synchronization via LockWhen(), Signaller is observed first. {{{1
587 namespace test07 {  
588 int     GLOB = 0;
589 bool    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
605 Mutex   MU; 
606 void Signaller() {
607   GLOB = 1; 
608   MU.Lock();
609   COND = true; // We are done! Tell the Waiter. 
610   MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
611 }
612 void 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 }
624 void Run() {
625   printf("test07: negative\n");
626   Waiter();
627   printf("\tGLOB=%d\n", GLOB);
628 }
629 REGISTER_TEST2(Run, 7, FEATURE|NEEDS_ANNOTATIONS);
630 }  // namespace test07
631
632 // test08: TN. Synchronization via thread start/join. {{{1
633 namespace test08 {
634 int     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)
643 void Worker() {
644   GLOB = 2; 
645 }
646
647 void Parent() {
648   MyThread t(Worker);
649   GLOB = 1;
650   t.Start();
651   t.Join();
652   GLOB = 3;
653 }
654 void Run() {
655   printf("test08: negative\n");
656   Parent();
657   printf("\tGLOB=%d\n", GLOB);
658 }
659 REGISTER_TEST(Run, 8);
660 }  // namespace test08
661
662
663 // test09: TP. Simple race (read vs write). {{{1
664 namespace test09 {
665 int     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. 
669 void Writer() {
670   usleep(100000);
671   GLOB = 3; 
672 }
673 void Reader() {
674   CHECK(GLOB != -777);
675 }
676
677 void 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 }
687 REGISTER_TEST(Run, 9);
688 }  // namespace test09
689
690
691 // test10: FN. Simple race (write vs read). {{{1
692 namespace test10 {
693 int     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 //
707 void Writer() {
708   GLOB = 3; 
709 }
710 void Reader() {
711   usleep(100000);
712   CHECK(GLOB != -777);
713 }
714
715 void 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 }
724 REGISTER_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 //
740 namespace test11 {
741 int     GLOB = 0;
742 Mutex   MU; 
743 void Worker() {
744   usleep(200000);
745   CHECK(GLOB != 777); 
746
747   MU.Lock();
748   COND++;
749   CV.Signal();
750   MU.Unlock();
751 }
752
753 void 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
770 void 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 }
776 REGISTER_TEST(Run, 11);
777 }  // namespace test11
778
779
780 // test12: FP. Synchronization via Mutex, then via PCQ. {{{1
781 namespace test12 {
782 int     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                                
796 ProducerConsumerQueue Q(INT_MAX);
797 Mutex   MU; 
798
799 void Putter() {
800   MU.Lock();
801   GLOB++; 
802   MU.Unlock();
803
804   Q.Put(NULL);
805 }
806
807 void Getter() {
808   MU.Lock();
809   GLOB++; 
810   MU.Unlock();
811
812   Q.Get();
813   GLOB++;
814 }
815
816 void 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 }
824 REGISTER_TEST(Run, 12);
825 }  // namespace test12
826
827
828 // test13: FP. Synchronization via Mutex, then via LockWhen. {{{1
829 namespace test13 { 
830 int     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)
845 Mutex   MU; 
846
847 void 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
858 void Waiter() {
859   MU.Lock();
860   GLOB++; 
861   MU.Unlock();
862
863   MU.LockWhen(Condition(&ArgIsOne, &COND));
864   MU.Unlock();
865   GLOB++;
866 }
867
868 void 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 }
879 REGISTER_TEST2(Run, 13, FEATURE|NEEDS_ANNOTATIONS);
880 }  // namespace test13
881
882
883 // test14: FP. Synchronization via PCQ, reads, 2 workers. {{{1
884 namespace test14 {
885 int     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)
897 ProducerConsumerQueue Q1(INT_MAX), Q2(INT_MAX);
898
899 void Putter1() {
900   CHECK(GLOB != 777);
901   Q1.Put(NULL);
902 }
903 void Putter2() {
904   CHECK(GLOB != 777);
905   Q2.Put(NULL);
906 }
907 void Getter() {
908   Q1.Get();
909   Q2.Get(); 
910   GLOB++;
911 }
912 void 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 }
920 REGISTER_TEST(Run, 14);
921 }  // namespace test14
922
923
924 // test15: TN. Synchronization via LockWhen. One waker and 2 waiters. {{{1
925 namespace 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
934 int     GLOB = 0;
935 Mutex   MU; 
936
937 void Waker() {
938   GLOB = 2;
939
940   MU.Lock();
941   COND = 1;
942   ANNOTATE_CONDVAR_SIGNAL(&MU);
943   MU.Unlock();
944 };
945
946 void Waiter() {
947   MU.LockWhen(Condition(&ArgIsOne, &COND));
948   MU.Unlock();
949   CHECK(GLOB != 777);
950 }
951
952
953 void 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 }
961 REGISTER_TEST(Run, 15);
962 }  // namespace test15
963
964
965 // test16: FP. Barrier (emulated by CV), 2 threads. {{{1
966 namespace 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 //
986 int     GLOB = 0;
987 Mutex   MU; 
988 Mutex MU2; 
989
990 void 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
1004 void 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 }
1013 REGISTER_TEST2(Run, 16, FEATURE|NEEDS_ANNOTATIONS);
1014 }  // namespace test16
1015
1016
1017 // test17: FP. Barrier (emulated by CV), 3 threads. {{{1
1018 namespace test17 {
1019 // Same as test16, but with 3 threads.
1020 int     GLOB = 0;
1021 Mutex   MU; 
1022 Mutex MU2; 
1023
1024 void 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
1038 void 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 }
1047 REGISTER_TEST2(Run, 17, FEATURE|NEEDS_ANNOTATIONS);
1048 }  // namespace test17
1049
1050
1051 // test18: TN. Synchronization via Await(), signaller gets there first. {{{1
1052 namespace test18 {  
1053 int     GLOB = 0;
1054 Mutex   MU; 
1055 // Same as test03, but uses Mutex::Await() instead of Mutex::LockWhen(). 
1056
1057 void 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 }
1065 void 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 }
1077 void Run() {
1078   printf("test18: negative\n");
1079   Waiter();
1080   printf("\tGLOB=%d\n", GLOB);
1081 }
1082 REGISTER_TEST2(Run, 18, FEATURE|NEEDS_ANNOTATIONS);
1083 }  // namespace test18
1084
1085 // test19: TN. Synchronization via AwaitWithTimeout(). {{{1
1086 namespace test19 {  
1087 int     GLOB = 0;
1088 // Same as test18, but with AwaitWithTimeout. Do not timeout. 
1089 Mutex   MU; 
1090 void 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 }
1098 void 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 }
1110 void Run() {
1111   printf("test19: negative\n");
1112   Waiter();
1113   printf("\tGLOB=%d\n", GLOB);
1114 }
1115 REGISTER_TEST2(Run, 19, FEATURE|NEEDS_ANNOTATIONS);
1116 }  // namespace test19
1117
1118 // test20: TP. Incorrect synchronization via AwaitWhen(), timeout. {{{1
1119 namespace test20 {  
1120 int     GLOB = 0;
1121 Mutex   MU; 
1122 // True race. We timeout in AwaitWhen.
1123 void Waker() {
1124   GLOB = 1; 
1125   usleep(100 * 1000);
1126 }
1127 void 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 }
1139 void 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 }
1146 REGISTER_TEST2(Run, 20, FEATURE|NEEDS_ANNOTATIONS);
1147 }  // namespace test20
1148
1149 // test21: TP. Incorrect synchronization via LockWhenWithTimeout(). {{{1
1150 namespace test21 {  
1151 int     GLOB = 0;
1152 // True race. We timeout in LockWhenWithTimeout().
1153 Mutex   MU; 
1154 void Waker() {
1155   GLOB = 1; 
1156   usleep(100 * 1000);
1157 }
1158 void 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 }
1169 void 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 }
1176 REGISTER_TEST2(Run, 21, FEATURE|NEEDS_ANNOTATIONS);
1177 }  // namespace test21
1178
1179 // test22: TP. Incorrect synchronization via CondVar::WaitWithTimeout(). {{{1
1180 namespace test22 {  
1181 int     GLOB = 0;
1182 Mutex   MU; 
1183 // True race. We timeout in CondVar::WaitWithTimeout().
1184 void Waker() {
1185   GLOB = 1; 
1186   usleep(100 * 1000);
1187 }
1188 void 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 }
1205 void 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 }
1212 REGISTER_TEST(Run, 22);
1213 }  // namespace test22
1214
1215 // test23: TN. TryLock, ReaderLock, ReaderTryLock. {{{1
1216 namespace test23 {  
1217 // Correct synchronization with TryLock, Lock, ReaderTryLock, ReaderLock. 
1218 int     GLOB = 0;
1219 Mutex   MU; 
1220 void 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
1233 void 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
1246 void 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
1255 void Worker_Lock() {
1256   for (int i = 0; i < 20; i++) {
1257     MU.Lock();
1258     GLOB++;
1259     MU.Unlock();
1260     usleep(1000);
1261   }
1262 }
1263
1264 void 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 }
1275 REGISTER_TEST(Run, 23);
1276 }  // namespace test23
1277
1278 // test24: TN. Synchronization via ReaderLockWhen(). {{{1
1279 namespace test24 {  
1280 int     GLOB = 0;
1281 Mutex   MU; 
1282 // Same as test03, but uses ReaderLockWhen(). 
1283
1284 void 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 }
1292 void 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 }
1302 void Run() {
1303   printf("test24: negative\n");
1304   Waiter();
1305   printf("\tGLOB=%d\n", GLOB);
1306 }
1307 REGISTER_TEST2(Run, 24, FEATURE|NEEDS_ANNOTATIONS);
1308 }  // namespace test24
1309
1310 // test25: TN. Synchronization via ReaderLockWhenWithTimeout(). {{{1
1311 namespace test25 {  
1312 int     GLOB = 0;
1313 Mutex   MU; 
1314 // Same as test24, but uses ReaderLockWhenWithTimeout(). 
1315 // We do not timeout. 
1316
1317 void 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 }
1325 void 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 }
1335 void Run() {
1336   printf("test25: negative\n");
1337   Waiter();
1338   printf("\tGLOB=%d\n", GLOB);
1339 }
1340 REGISTER_TEST2(Run, 25, FEATURE|NEEDS_ANNOTATIONS);
1341 }  // namespace test25
1342
1343 // test26: TP. Incorrect synchronization via ReaderLockWhenWithTimeout(). {{{1
1344 namespace test26 {  
1345 int     GLOB = 0;
1346 Mutex   MU; 
1347 // Same as test25, but we timeout and incorrectly assume happens-before. 
1348
1349 void Waker() {
1350   GLOB = 1; 
1351   usleep(10000);
1352 }
1353 void 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 }
1363 void 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 }
1370 REGISTER_TEST2(Run, 26, FEATURE|NEEDS_ANNOTATIONS);
1371 }  // namespace test26
1372
1373
1374 // test27: TN. Simple synchronization via SpinLock. {{{1
1375 namespace test27 {
1376 #ifndef NO_SPINLOCK
1377 int     GLOB = 0;
1378 SpinLock MU;
1379 void Worker() {
1380   MU.Lock();
1381   GLOB++; 
1382   MU.Unlock();
1383   usleep(10000);
1384 }
1385
1386 void 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 }
1393 REGISTER_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
1399 namespace 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)
1409 ProducerConsumerQueue Q(INT_MAX);
1410 int     GLOB = 0;
1411 Mutex   MU; 
1412
1413 void 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
1425 void Getter() {
1426   Q.Get();
1427   Q.Get();
1428   usleep(100000);
1429   CHECK(GLOB == 2);
1430 }
1431
1432 void 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 }
1439 REGISTER_TEST(Run, 28);
1440 }  // namespace test28
1441
1442
1443 // test29: TN. Synchronization via Mutex, then PCQ. 4 threads. {{{1
1444 namespace test29 {
1445 // Similar to test28, but has two Getters and two PCQs. 
1446 ProducerConsumerQueue *Q1, *Q2;
1447 Mutex   MU; 
1448 int     GLOB = 0;
1449
1450 void 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
1464 void Putter1() { Putter(Q1); }
1465 void Putter2() { Putter(Q2); }
1466
1467 void 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
1475 void 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 }
1486 REGISTER_TEST(Run, 29);
1487 }  // namespace test29
1488
1489
1490 // test30: TN. Synchronization via 'safe' race. Writer vs multiple Readers. {{{1
1491 namespace 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
1512 const int N = 48;
1513 static int GLOB[N];
1514 volatile int BOUNDARY = 0;
1515
1516 void 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
1528 void 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
1541 void 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 }
1550 REGISTER_TEST2(Run, 30, FEATURE|NEEDS_ANNOTATIONS);
1551 }  // namespace test30
1552
1553
1554 // test31: TN. Synchronization via 'safe' race. Writer vs Writer. {{{1
1555 namespace 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
1565 const int N = 48;
1566 static int GLOB[N];
1567 volatile int BOUNDARY = 0;
1568
1569 void 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
1581 void 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
1596 void 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 }
1605 REGISTER_TEST2(Run, 31, FEATURE|NEEDS_ANNOTATIONS);
1606 }  // namespace test31
1607
1608
1609 // test32: FP. Synchronization via thread create/join. W/R. {{{1
1610 namespace 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 //
1631 int     GLOB = 0;
1632 Mutex   MU; 
1633
1634 void Writer() {
1635   MU.Lock();
1636   GLOB = 1;
1637   MU.Unlock();
1638 }
1639
1640 void Reader() {
1641   usleep(480000);
1642   MU.Lock();
1643   CHECK(GLOB != 777);
1644   MU.Unlock();
1645 }
1646
1647 void 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
1659 void 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
1666 REGISTER_TEST(Run, 32);
1667 }  // namespace test32
1668
1669
1670 // test33: STAB. Stress test for the number of thread sets (TSETs). {{{1
1671 namespace test33 {
1672 int     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). 
1676 const int N_iter = 48;
1677 const int Nlog  = 15;
1678 const int N     = 1 << Nlog;
1679 static int ARR[N];
1680 Mutex   MU; 
1681
1682 void 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
1696 void 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 }
1720 REGISTER_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
1725 namespace test34 {
1726 // Similar to test33, but for lock sets. 
1727 int     GLOB = 0;
1728 const int N_iter = 48;
1729 const int Nlog = 10;
1730 const int N    = 1 << Nlog;
1731 static int ARR[N];
1732 static Mutex *MUs[Nlog];
1733
1734 void 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
1743 void 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 }
1759 REGISTER_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
1764 namespace 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. 
1770 int **ARR; 
1771 const int N_mu   = 25000;
1772 const int N_free = 48000;
1773
1774 void Worker() {
1775   for (int i = 0; i < N_free; i++) 
1776     CHECK(777 == *ARR[i]);
1777 }
1778
1779 void 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 }
1807 REGISTER_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
1812 namespace 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() 
1828 ProducerConsumerQueue Q(INT_MAX);
1829 int     GLOB = 0;
1830 Mutex   MU, MU1; 
1831
1832 void 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
1846 void Getter() {
1847   Q.Get();
1848   Q.Get();
1849   usleep(100000);
1850   MU1.Lock();
1851   GLOB++;
1852   MU1.Unlock();
1853 }
1854
1855 void 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 }
1862 REGISTER_TEST(Run, 36);
1863 }  // namespace test36
1864
1865
1866 // test37: TN. Simple synchronization (write vs read). {{{1
1867 namespace test37 {
1868 int     GLOB = 0;
1869 Mutex   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
1879 void Writer() {
1880   MU.Lock();
1881   GLOB = 3; 
1882   MU.Unlock();
1883 }
1884 void Reader() {
1885   usleep(100000);
1886   MU.Lock();
1887   CHECK(GLOB != -777);
1888   MU.Unlock();
1889 }
1890
1891 void Run() {
1892   printf("test37: negative\n");
1893   MyThreadArray t(Writer, Reader);
1894   t.Start();
1895   t.Join();
1896   printf("\tGLOB=%d\n", GLOB);
1897 }
1898 REGISTER_TEST(Run, 37);
1899 }  // namespace test37
1900
1901
1902 // test38: TN. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1
1903 namespace 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
1925 ProducerConsumerQueue *Q1, *Q2;
1926 int     GLOB = 0;
1927 Mutex   MU, MU1, MU2; 
1928
1929 void 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
1945 void Putter1() { Putter(Q1); }
1946 void Putter2() { Putter(Q2); }
1947
1948 void 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
1960 void 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 }
1971 REGISTER_TEST(Run, 38);
1972 }  // namespace test38
1973
1974 // test39: FP. Barrier. {{{1
1975 namespace test39 {
1976 #ifndef NO_BARRIER
1977 // Same as test17 but uses Barrier class (pthread_barrier_t). 
1978 int     GLOB = 0;
1979 const int N_threads = 3;
1980 Barrier barrier(N_threads);
1981 Mutex   MU; 
1982
1983 void Worker() {
1984   MU.Lock();
1985   GLOB++;
1986   MU.Unlock();
1987   barrier.Block();
1988   CHECK(GLOB == N_threads);
1989 }
1990 void 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 }
2003 REGISTER_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
2009 namespace 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
2031 ProducerConsumerQueue *Q1, *Q2;
2032 int     GLOB = 0;
2033 Mutex   MU, MU1, MU2; 
2034
2035 void 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
2052 void Putter1() { Putter(Q1); }
2053 void Putter2() { Putter(Q2); }
2054
2055 void 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
2066 void 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 }
2078 REGISTER_TEST(Run, 40);
2079 }  // namespace test40
2080
2081 // test41: TN. Test for race that appears when loading a dynamic symbol. {{{1
2082 namespace test41 {
2083 void Worker() {
2084   ANNOTATE_NO_OP(NULL); // An empty function, loaded from dll. 
2085 }
2086 void Run() {
2087   printf("test41: negative\n");
2088   MyThreadArray t(Worker, Worker, Worker);
2089   t.Start();
2090   t.Join();
2091 }
2092 REGISTER_TEST2(Run, 41, FEATURE|NEEDS_ANNOTATIONS);
2093 }  // namespace test41
2094
2095
2096 // test42: TN. Using the same cond var several times. {{{1
2097 namespace test42 {
2098 int GLOB = 0;
2099 int COND = 0;
2100 int N_threads = 3;
2101 Mutex   MU; 
2102
2103 void 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
2121 void 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
2138 void 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 }
2146 REGISTER_TEST2(Run, 42, FEATURE|NEEDS_ANNOTATIONS);
2147 }  // namespace test42
2148
2149
2150
2151 // test43: TN. {{{1
2152 namespace test43 {
2153 // 
2154 // Putter:            Getter: 
2155 // 1. write          
2156 // 2. Q.Put() --\     .
2157 // 3. read       \--> a. Q.Get()    
2158 //                    b. read
2159 int     GLOB = 0;
2160 ProducerConsumerQueue Q(INT_MAX);
2161 void Putter() {
2162   GLOB = 1;
2163   Q.Put(NULL);
2164   CHECK(GLOB == 1);
2165 }
2166 void Getter() {
2167   Q.Get();
2168   usleep(100000);
2169   CHECK(GLOB == 1);
2170 }
2171 void Run() {
2172   printf("test43: negative\n");
2173   MyThreadArray t(Putter, Getter);
2174   t.Start();
2175   t.Join();
2176   printf("\tGLOB=%d\n", GLOB);
2177 }
2178 REGISTER_TEST(Run, 43)
2179 }  // namespace test43
2180
2181
2182 // test44: FP. {{{1
2183 namespace 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();              
2194 int     GLOB = 0;
2195 Mutex   MU; 
2196 ProducerConsumerQueue Q(INT_MAX);
2197 void Putter() {
2198   CHECK(GLOB == 0);
2199   Q.Put(NULL);
2200   MU.Lock();
2201   GLOB = 1;
2202   MU.Unlock();
2203 }
2204 void Getter() {
2205   Q.Get();
2206   usleep(100000);
2207   MU.Lock();
2208   GLOB = 1;
2209   MU.Unlock();
2210 }
2211 void 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 }
2219 REGISTER_TEST(Run, 44)
2220 }  // namespace test44
2221
2222
2223 // test45: TN. {{{1
2224 namespace 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();              
2235 int     GLOB = 0;
2236 Mutex   MU; 
2237 ProducerConsumerQueue Q(INT_MAX);
2238 void Putter() {
2239   CHECK(GLOB == 0);
2240   Q.Put(NULL);
2241   MU.Lock();
2242   GLOB++;
2243   MU.Unlock();
2244 }
2245 void Getter() {
2246   Q.Get();
2247   usleep(100000);
2248   MU.Lock();
2249   CHECK(GLOB <= 1);
2250   MU.Unlock();
2251 }
2252 void Run() {
2253   printf("test45: negative\n");
2254   MyThreadArray t(Putter, Getter);
2255   t.Start();
2256   t.Join();
2257   printf("\tGLOB=%d\n", GLOB);
2258 }
2259 REGISTER_TEST(Run, 45)
2260 }  // namespace test45
2261
2262
2263 // test46: FN. {{{1
2264 namespace 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();              
2274 int     GLOB = 0;
2275 Mutex   MU; 
2276 void First() {
2277   GLOB++;
2278   MU.Lock();
2279   GLOB++;
2280   MU.Unlock();
2281 }
2282 void 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 }
2295 void Run() {
2296   ANNOTATE_TRACE_MEMORY(&GLOB);
2297   MyThreadArray t(First, Second);
2298   t.Start();
2299   t.Join();
2300 }
2301 REGISTER_TEST(Run, 46)
2302 }  // namespace test46
2303
2304
2305 // test47: TP. Not detected by pure happens-before detectors. {{{1
2306 namespace 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
2317 int     GLOB = 0;
2318 Mutex   MU; 
2319 void First() {
2320   GLOB=1;
2321   MU.Lock();
2322   MU.Unlock();
2323 }
2324 void Second() {
2325   usleep(480000);
2326   MU.Lock();
2327   MU.Unlock();
2328   GLOB++;
2329 }
2330 void 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 }
2340 REGISTER_TEST(Run, 47)
2341 }  // namespace test47
2342
2343
2344 // test48: FN. Simple race (single write vs multiple reads). {{{1
2345 namespace test48 {
2346 int     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 //
2361 void Writer() {
2362   GLOB = 3; 
2363 }
2364 void Reader() {
2365   usleep(100000);
2366   CHECK(GLOB != -777);
2367 }
2368
2369 void 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 }
2378 REGISTER_TEST(Run, 48)
2379 }  // namespace test48
2380
2381
2382 // test49: FN. Simple race (single write vs multiple reads). {{{1
2383 namespace test49 {
2384 int     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 //
2401 void Writer() {
2402   GLOB = 3; 
2403 }
2404 void Reader() {
2405   usleep(100000);
2406   CHECK(GLOB != -777);
2407   CHECK(GLOB != -777);
2408   CHECK(GLOB != -777);
2409   CHECK(GLOB != -777);
2410 }
2411
2412 void 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 }
2421 REGISTER_TEST(Run, 49);
2422 }  // namespace test49
2423
2424
2425 // test50: TP. Synchronization via CondVar. {{{1
2426 namespace test50 {
2427 int     GLOB = 0;
2428 Mutex   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
2446 void 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
2462 void 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 }
2476 void 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 }
2483 REGISTER_TEST2(Run, 50, FEATURE|NEEDS_ANNOTATIONS);
2484 }  // namespace test50
2485
2486
2487 // test51: TP. Synchronization via CondVar: problem with several signals. {{{1
2488 namespace test51 {
2489 int     GLOB = 0;
2490 int     COND = 0;
2491 Mutex   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
2516 void 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
2537 void 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 }
2551 void 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 }
2558 REGISTER_TEST(Run, 51);
2559 }  // namespace test51
2560
2561
2562 // test52: TP. Synchronization via CondVar: problem with several signals. {{{1
2563 namespace test52 {
2564 int     GLOB = 0;
2565 int     COND = 0;
2566 Mutex   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
2589 void 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
2608 void 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 }
2622 void 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 }
2629 REGISTER_TEST(Run, 52);
2630 }  // namespace test52
2631
2632
2633 // test53: FP. Synchronization via implicit semaphore. {{{1
2634 namespace 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
2656 int     GLOB = 0;
2657 bool    FLAG = false;
2658 Mutex   MU1, MU2; 
2659
2660 void Initializer() {
2661   MU1.Lock();
2662   GLOB = 1000;
2663   FLAG = true;
2664   MU1.Unlock();
2665   usleep(100000); // just in case
2666 }
2667
2668 void 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
2683 void 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 }
2693 REGISTER_TEST(Run, 53)
2694 }  // namespace test53
2695
2696
2697 // test54: TN. Synchronization via implicit semaphore. Annotated {{{1
2698 namespace test54 {
2699 // Same as test53, but annotated. 
2700 int     GLOB = 0;
2701 bool    FLAG = false;
2702 Mutex   MU1, MU2; 
2703
2704 void 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
2713 void 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
2729 void 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 }
2736 REGISTER_TEST2(Run, 54, FEATURE|NEEDS_ANNOTATIONS)
2737 }  // namespace test54
2738
2739
2740 // test55: FP. Synchronization with TryLock. Not easy for race detectors {{{1
2741 namespace 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). 
2747 int     GLOB = 0;
2748 Mutex   MU; 
2749
2750 void Worker_Lock() {
2751   GLOB = 1;
2752   MU.Lock();
2753 }
2754
2755 void 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
2768 void 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 }
2775 REGISTER_TEST2(Run, 55, FEATURE|EXCLUDE_FROM_ALL);
2776 }  // namespace test55
2777
2778
2779
2780 // test56: TP. Use of ANNOTATE_BENIGN_RACE. {{{1
2781 namespace test56 {
2782 // For whatever reason the user wants to treat 
2783 // a race on GLOB as a benign race. 
2784 int     GLOB = 0;
2785 int     GLOB2 = 0;
2786
2787 void Worker() {
2788   GLOB++;
2789 }
2790
2791 void 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 }
2800 REGISTER_TEST2(Run, 56, FEATURE|NEEDS_ANNOTATIONS)
2801 }  // namespace test56
2802
2803
2804 // test57: TN: Correct use of atomics. {{{1
2805 namespace test57 {
2806 int     GLOB = 0;
2807 void Writer() {
2808   for (int i = 0; i < 10; i++) {
2809     AtomicIncrement(&GLOB, 1);
2810     usleep(1000);
2811   }
2812 }
2813 void Reader() {
2814   while (GLOB < 20) usleep(1000);
2815 }
2816 void 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 }
2824 REGISTER_TEST(Run, 57)
2825 }  // namespace test57
2826
2827
2828 // test58: TN. User defined synchronization. {{{1
2829 namespace test58 {
2830 int     GLOB1 = 1;
2831 int     GLOB2 = 2;
2832 int     FLAG1 = 0;
2833 int     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
2840 void Worker2() {
2841   FLAG1=GLOB2;
2842
2843   while(!FLAG2)
2844     ;
2845   GLOB2=FLAG2;
2846 }
2847
2848 void Worker1() {
2849   FLAG2=GLOB1;
2850
2851   while(!FLAG1)
2852     ;
2853   GLOB1=FLAG1;
2854 }
2855
2856 void 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 }
2864 REGISTER_TEST2(Run, 58, FEATURE|EXCLUDE_FROM_ALL)
2865 }  // namespace test58
2866
2867
2868
2869 // test59: TN. User defined synchronization. Annotated {{{1
2870 namespace test59 {
2871 int     COND1 = 0;
2872 int     COND2 = 0;
2873 int     GLOB1 = 1;
2874 int     GLOB2 = 2;
2875 int     FLAG1 = 0;
2876 int     FLAG2 = 0;
2877 // same as test 58 but annotated
2878
2879 void Worker2() {
2880   FLAG1=GLOB2;
2881   ANNOTATE_CONDVAR_SIGNAL(&COND2);
2882   while(!FLAG2) usleep(1);
2883   ANNOTATE_CONDVAR_WAIT(&COND1);
2884   GLOB2=FLAG2;
2885 }
2886
2887 void Worker1() {
2888   FLAG2=GLOB1;
2889   ANNOTATE_CONDVAR_SIGNAL(&COND1);
2890   while(!FLAG1) usleep(1);
2891   ANNOTATE_CONDVAR_WAIT(&COND2);
2892   GLOB1=FLAG1;
2893 }
2894
2895 void 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 }
2905 REGISTER_TEST2(Run, 59, FEATURE|NEEDS_ANNOTATIONS)
2906 }  // namespace test59
2907
2908
2909 // test60: TN. Correct synchronization using signal-wait {{{1
2910 namespace test60 {
2911 int     COND1 = 0;
2912 int     COND2 = 0;
2913 int     GLOB1 = 1;
2914 int     GLOB2 = 2;
2915 int     FLAG2 = 0;
2916 int     FLAG1 = 0;
2917 Mutex   MU; 
2918 // same as test 59 but synchronized with signal-wait.
2919
2920 void 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
2937 void 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
2954 void 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 }
2962 REGISTER_TEST2(Run, 60, FEATURE|NEEDS_ANNOTATIONS)
2963 }  // namespace test60
2964
2965
2966 // test61: TN. Synchronization via Mutex as in happens-before, annotated. {{{1
2967 namespace test61 {
2968 Mutex MU;
2969 int     GLOB = 0;
2970 int     *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
2976 void 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
2986 void 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
3001 void Run() {
3002   printf("test61: negative\n");
3003   MyThreadArray t(Putter, Getter);
3004   t.Start();
3005   t.Join();
3006   printf("\tGLOB=%d\n", GLOB);
3007 }
3008 REGISTER_TEST2(Run, 61, FEATURE|NEEDS_ANNOTATIONS)
3009 }  // namespace test61
3010
3011
3012 // test62: STAB. Create as many segments as possible. {{{1
3013 namespace 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. 
3016 ProducerConsumerQueue Q(INT_MAX);
3017 const int N = 1 << 22;
3018
3019 void 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
3028 void Getter() {
3029   for (int i = 0; i < N; i++)
3030     Q.Get();
3031 }
3032
3033 void Run() {
3034   printf("test62:\n");
3035   MyThreadArray t(Putter, Getter);
3036   t.Start();
3037   t.Join();
3038 }
3039 REGISTER_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
3044 namespace 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. 
3047 const int N = 1 << 24;
3048 int C = 0;
3049
3050 void 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
3059 void Getter() {
3060 }
3061
3062 void Run() {
3063   printf("test63:\n");
3064   MyThreadArray t(Putter, Getter);
3065   t.Start();
3066   t.Join();
3067 }
3068 REGISTER_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
3073 namespace 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
3084 int     GLOB = 0;
3085 ProducerConsumerQueue Q(INT_MAX);
3086
3087 void T1() {
3088   CHECK(GLOB == 0);
3089 }
3090
3091 void T2() {
3092   usleep(100000);
3093   CHECK(GLOB == 0);
3094   Q.Put(NULL);
3095 }
3096
3097 void T3() {
3098   Q.Get();
3099   GLOB = 1;
3100 }
3101
3102
3103 void 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 }
3112 REGISTER_TEST(Run, 64)
3113 }  // namespace test64
3114
3115
3116 // test65: TP. T2 happens-before T3, but T1 is independent. Writes in T1/T2. {{{1
3117 namespace 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
3133 int     GLOB = 0;
3134 Mutex   MU; 
3135 ProducerConsumerQueue Q(INT_MAX);
3136
3137 void T1() {
3138   MU.Lock();
3139   GLOB++;
3140   MU.Unlock();
3141 }
3142
3143 void T2() {
3144   usleep(100000);
3145   MU.Lock();
3146   GLOB++;
3147   MU.Unlock();
3148   Q.Put(NULL);
3149 }
3150
3151 void T3() {
3152   Q.Get();
3153   GLOB = 1;
3154 }
3155
3156
3157 void 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 }
3167 REGISTER_TEST(Run, 65)
3168 }  // namespace test65
3169
3170
3171 // test66: TN. Two separate pairs of signaller/waiter using the same CV. {{{1
3172 namespace test66 {
3173 int     GLOB1 = 0;
3174 int     GLOB2 = 0;
3175 int     C1 = 0;
3176 int     C2 = 0;
3177 Mutex   MU; 
3178
3179 void Signaller1() {
3180   GLOB1 = 1;
3181   MU.Lock();
3182   C1 = 1;
3183   CV.Signal();
3184   MU.Unlock();
3185 }
3186
3187 void Signaller2() {
3188   GLOB2 = 1;
3189   usleep(100000);
3190   MU.Lock();
3191   C2 = 1;
3192   CV.Signal();
3193   MU.Unlock();
3194 }
3195
3196 void Waiter1() {
3197   MU.Lock();
3198   while (C1 != 1) CV.Wait(&MU);
3199   ANNOTATE_CONDVAR_WAIT(&CV);
3200   MU.Unlock();
3201   GLOB1 = 2;
3202 }
3203
3204 void Waiter2() {
3205   MU.Lock();
3206   while (C2 != 1) CV.Wait(&MU);
3207   ANNOTATE_CONDVAR_WAIT(&CV);
3208   MU.Unlock();
3209   GLOB2 = 2;
3210 }
3211
3212 void 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 }
3219 REGISTER_TEST2(Run, 66, FEATURE|NEEDS_ANNOTATIONS)
3220 }  // namespace test66
3221
3222
3223 // test67: FN. Race between Signaller1 and Waiter2 {{{1
3224 namespace 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. 
3230 int     GLOB = 0;
3231 int     C1 = 0;
3232 int     C2 = 0;
3233 Mutex   MU; 
3234
3235 void Signaller1() {
3236   GLOB = 1;
3237   MU.Lock();
3238   C1 = 1;
3239   CV.Signal();
3240   MU.Unlock();
3241 }
3242
3243 void Signaller2() {
3244   usleep(100000);
3245   MU.Lock();
3246   C2 = 1;
3247   CV.Signal();
3248   MU.Unlock();
3249 }
3250
3251 void Waiter1() {
3252   MU.Lock();
3253   while (C1 != 1) CV.Wait(&MU);
3254   ANNOTATE_CONDVAR_WAIT(&CV);
3255   MU.Unlock();
3256 }
3257
3258 void Waiter2() {
3259   MU.Lock();
3260   while (C2 != 1) CV.Wait(&MU);
3261   ANNOTATE_CONDVAR_WAIT(&CV);
3262   MU.Unlock();
3263   GLOB = 2;
3264 }
3265
3266 void 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 }
3275 REGISTER_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
3280 namespace 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. 
3286 int     GLOB = 0;
3287 int     COND = 0;
3288 const int N_writers = 3;
3289 Mutex MU, MU1;
3290
3291 void 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
3304 void 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
3318 void 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 }
3327 REGISTER_TEST(Run, 68)
3328 }  // namespace test68
3329
3330
3331 // test69:  {{{1
3332 namespace 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: 
3338 int     GLOB = 0;
3339 int     COND = 0;
3340 const int N_writers = 3;
3341 int     FAKE_MU = 0;
3342 Mutex MU, MU1;
3343
3344 void 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
3357 void 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
3373 void 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 }
3380 REGISTER_TEST(Run, 69)
3381 }  // namespace test69
3382
3383 // test70: STAB. Check that TRACE_MEMORY works. {{{1
3384 namespace test70 {
3385 int     GLOB = 0;
3386 void Run() {
3387   printf("test70: negative\n");
3388   ANNOTATE_TRACE_MEMORY(&GLOB);
3389   GLOB = 1;
3390   printf("\tGLOB=%d\n", GLOB);
3391 }
3392 REGISTER_TEST(Run, 70)
3393 }  // namespace test70
3394
3395
3396
3397 // test71: TN. strlen, index. {{{1
3398 namespace 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
3411 char    *str;
3412 void 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 }
3422 void WorkerY() {
3423   str[5] = 'Y';
3424   str[6] = 'Y';
3425   str[7] = '\0';
3426 }
3427
3428 void 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 }
3445 REGISTER_TEST(Run, 71)
3446 }  // namespace test71
3447
3448
3449 // test72: STAB. Stress test for the number of segment sets (SSETs). {{{1
3450 namespace 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. 
3455 int     GLOB = 0;
3456 const int N_iter = 30;
3457 const int Nlog  = 16;
3458 const int N     = 1 << Nlog;
3459 static int64_t ARR1[N];
3460 static int64_t ARR2[N];
3461 Barrier *barriers[N_iter];
3462 Mutex   MU; 
3463
3464 void 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
3500 void 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 }
3525 REGISTER_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
3531 namespace test73 {
3532 #ifndef NO_BARRIER
3533 // Variation of test72. 
3534 // We perform accesses of different sizes to the same location. 
3535 int     GLOB = 0;
3536 const int N_iter = 2;
3537 const int Nlog  = 16;
3538 const int N     = 1 << Nlog;
3539 union uint64_union {
3540   uint64_t u64[1];
3541   uint32_t u32[2];
3542   uint16_t u16[4];
3543   uint8_t  u8 [8];
3544 };
3545 static uint64_union ARR1[N];
3546 union uint32_union {
3547   uint32_t u32[1];
3548   uint16_t u16[2];
3549   uint8_t  u8 [4];
3550 };
3551 static uint32_union ARR2[N];
3552 Barrier *barriers[N_iter];
3553 Mutex   MU; 
3554
3555 void 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
3592 void 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 }
3617 REGISTER_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
3623 namespace    test74 {
3624 const int N = 100000;
3625 Mutex   MU; 
3626 void Run() {
3627   printf("test74: perf\n");
3628   for (int i = 0; i < N; i++ ) {
3629     MU.Lock();
3630     MU.Unlock();
3631   }
3632 }
3633 REGISTER_TEST(Run, 74)
3634 }  // namespace test74
3635
3636
3637 // test75: TN. Test for sem_post, sem_wait, sem_trywait. {{{1
3638 namespace test75 {
3639 int     GLOB = 0;
3640 sem_t   sem[2];
3641
3642 void Poster() {
3643   GLOB = 1;
3644   sem_post(&sem[0]);
3645   sem_post(&sem[1]);
3646 }
3647
3648 void Waiter() {
3649   sem_wait(&sem[0]);
3650   CHECK(GLOB==1);
3651 }
3652 void TryWaiter() {
3653   usleep(500000);
3654   sem_trywait(&sem[1]);
3655   CHECK(GLOB==1);
3656 }
3657
3658 void 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 }
3681 REGISTER_TEST(Run, 75)
3682 }  // namespace test75
3683
3684 // RefCountedClass {{{1
3685 struct 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
3752 Mutex RefCountedClass::MU;
3753
3754 // test76: FP. Ref counting, no annotations. {{{1
3755 namespace test76 {
3756 #ifndef NO_BARRIER
3757 int     GLOB = 0;
3758 Barrier barrier(4);
3759 RefCountedClass *object = NULL; 
3760 void Worker() {
3761   object->Ref();
3762   barrier.Block();
3763   object->AccessData();
3764   object->Unref();
3765 }
3766 void 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 }
3774 REGISTER_TEST2(Run, 76, FEATURE)
3775 #endif // NO_BARRIER
3776 }  // namespace test76
3777
3778
3779
3780 // test77: TN. Ref counting, MU is annotated. {{{1
3781 namespace test77 {
3782 #ifndef NO_BARRIER
3783 // same as test76, but RefCountedClass::MU is annotated. 
3784 int     GLOB = 0;
3785 Barrier barrier(4);
3786 RefCountedClass *object = NULL; 
3787 void Worker() {
3788   object->Ref();
3789   barrier.Block();
3790   object->AccessData();
3791   object->Unref();
3792 }
3793 void 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 }
3801 REGISTER_TEST(Run, 77)
3802 #endif // NO_BARRIER
3803 }  // namespace test77
3804
3805
3806
3807 // test78: TN. Ref counting, Unref is annotated. {{{1
3808 namespace test78 {
3809 #ifndef NO_BARRIER
3810 // same as test76, but RefCountedClass::Unref is annotated. 
3811 int     GLOB = 0;
3812 Barrier barrier(4);
3813 RefCountedClass *object = NULL; 
3814 void Worker() {
3815   object->Ref();
3816   barrier.Block();
3817   object->AccessData();
3818   object->Unref();
3819 }
3820 void 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 }
3828 REGISTER_TEST(Run, 78)
3829 #endif // NO_BARRIER
3830 }  // namespace test78
3831
3832
3833
3834 // test79 TN. Swap. {{{1
3835 namespace test79 {
3836 #if 0
3837 typedef __gnu_cxx::hash_map<int, int> map_t;
3838 #else
3839 typedef std::map<int, int> map_t;
3840 #endif
3841 map_t   MAP;
3842 Mutex   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
3848 void 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
3857 void Worker2() {
3858   MU.Lock();
3859   MAP[1]++;  // Just update MAP under MU.
3860   MU.Unlock();
3861 }
3862
3863 void Worker3() { Worker1(); } 
3864 void Worker4() { Worker2(); } 
3865
3866 void 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 }
3873 REGISTER_TEST(Run, 79)
3874 }  // namespace test79
3875
3876
3877 // AtomicRefCountedClass. {{{1
3878 // Same as RefCountedClass, but using atomic ops instead of mutex.
3879 struct 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
3934 namespace test80 {
3935 #ifndef NO_BARRIER
3936 int     GLOB = 0;
3937 Barrier barrier(4);
3938 AtomicRefCountedClass *object = NULL; 
3939 void Worker() {
3940   object->Ref();
3941   barrier.Block();
3942   object->AccessData();
3943   object->Unref(); // All the tricky stuff is here.
3944 }
3945 void 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 }
3953 REGISTER_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
3959 namespace test81 {
3960 #ifndef NO_BARRIER
3961 // same as test80, but Unref is annotated.
3962 int     GLOB = 0;
3963 Barrier barrier(4);
3964 AtomicRefCountedClass *object = NULL; 
3965 void Worker() {
3966   object->Ref();
3967   barrier.Block();
3968   object->AccessData();
3969   object->Unref(); // All the tricky stuff is here.
3970 }
3971 void 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 }
3979 REGISTER_TEST2(Run, 81, FEATURE|EXCLUDE_FROM_ALL)
3980 #endif // NO_BARRIER
3981 }  // namespace test81
3982
3983
3984 // test82: Object published w/o synchronization. {{{1
3985 namespace 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
4005 class 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
4020 const int N = 100000;
4021 static volatile FOO *foo[N];
4022 Mutex   MU; 
4023
4024 void Writer() {
4025   for (int i = 0; i < N; i++) {
4026     foo[i] = new FOO;
4027     usleep(100);
4028   }
4029 }
4030
4031 void 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
4047 void Run() {
4048   printf("test82: positive\n");
4049   MyThreadArray t(Writer, Reader);
4050   t.Start();
4051   t.Join();
4052 }
4053 REGISTER_TEST2(Run, 82, FEATURE|EXCLUDE_FROM_ALL)
4054 }  // namespace test82
4055
4056
4057 // test83: Object published w/o synchronization (simple version){{{1
4058 namespace test83 {
4059 // A simplified version of test83 (example of a wrong code).
4060 // This test, though incorrect, will almost never fail.
4061 volatile static int *ptr = NULL;
4062 Mutex   MU; 
4063
4064 void Writer() {
4065   usleep(100);
4066   ptr = new int(777);
4067 }
4068
4069 void Reader() {
4070   while(!ptr) {
4071     MU.Lock(); // Not a synchronization!
4072     MU.Unlock(); 
4073   }
4074   CHECK(*ptr == 777);
4075 }
4076
4077 void Run() {
4078 //  printf("test83: positive\n");
4079   MyThreadArray t(Writer, Reader);
4080   t.Start();
4081   t.Join();
4082 }
4083 REGISTER_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
4088 namespace 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.
4093 static int s_x = 0;
4094 /* s_dummy[] ensures that s_x and s_y are not in the same cache line. */
4095 static char s_dummy[512] = {0};
4096 static int s_y;
4097
4098 void thread_func_1()
4099 {
4100   s_y = 1;
4101   AtomicIncrement(&s_x, 1);
4102 }
4103
4104 void thread_func_2()
4105 {
4106   while (AtomicIncrement(&s_x, 0) == 0)
4107     ;
4108   printf("y = %d\n", s_y);
4109 }
4110
4111
4112 void 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 }
4121 REGISTER_TEST(Run, 84)
4122 }  // namespace test84
4123
4124
4125 // test85: Test for RunningOnValgrind(). {{{1
4126 namespace  test85 {
4127 int     GLOB = 0;
4128 void Run() {
4129   printf("test85: RunningOnValgrind() = %d\n", RunningOnValgrind());
4130 }
4131 REGISTER_TEST(Run, 85)
4132 }  // namespace test85
4133
4134
4135 // test86: Test for race inside DTOR: racey write to vptr. Benign. {{{1
4136 namespace 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
4163 bool flag_stopped = false;
4164 Mutex mu;
4165
4166 ProducerConsumerQueue Q(INT_MAX);  // Used to pass A* between threads.
4167
4168 struct 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
4176 struct 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
4189 void 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
4203 void 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
4215 void Run() {
4216   printf("test86: positive, race inside DTOR\n");
4217   MyThreadArray t(Waiter, Worker);
4218   t.Start();
4219   t.Join();
4220 }
4221 REGISTER_TEST(Run, 86)
4222 }  // namespace test86
4223
4224
4225 // test87: Test for race inside DTOR: racey write to vptr. Harmful.{{{1
4226 namespace 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 //
4236 bool flag_stopped = false;
4237 Mutex mu;
4238
4239 ProducerConsumerQueue Q(INT_MAX);  // Used to pass A* between threads.
4240
4241 struct A {
4242   A()  { printf("A::A()\n"); }
4243   virtual ~A() { printf("A::~A()\n"); }
4244   virtual void f() = 0; // pure virtual.
4245 };
4246
4247 struct 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
4260 struct C: B {
4261   C()  { printf("C::C()\n"); }
4262   virtual ~C() { printf("C::~C()\n"); }
4263   virtual void f() { }
4264 };
4265
4266 void Waiter() {
4267   A *a = new C;
4268   Q.Put(a);
4269   delete a;
4270 }
4271
4272 void 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
4282 void Run() {
4283   printf("test87: positive, race inside DTOR\n");
4284   MyThreadArray t(Waiter, Worker);
4285   t.Start();
4286   t.Join();
4287 }
4288 REGISTER_TEST2(Run, 87, FEATURE|EXCLUDE_FROM_ALL)
4289 }  // namespace test87
4290
4291
4292 // test88: Test for ANNOTATE_IGNORE_WRITES_*{{{1
4293 namespace test88 {
4294 // a recey write annotated with ANNOTATE_IGNORE_WRITES_BEGIN/END.
4295 int     GLOB = 0;
4296 void Worker() {
4297   ANNOTATE_IGNORE_WRITES_BEGIN();
4298   GLOB = 1;
4299   ANNOTATE_IGNORE_WRITES_END();
4300 }
4301 void 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 }
4309 REGISTER_TEST(Run, 88)
4310 }  // namespace test88
4311
4312
4313 // test89: Test for debug info. {{{1
4314 namespace 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.
4318 struct STRUCT {
4319   int a, b, c;
4320 };
4321
4322 struct A {
4323   int a;  
4324   A() { 
4325     ANNOTATE_TRACE_MEMORY(&a);
4326     a = 1; 
4327   } 
4328   virtual ~A() {
4329     a = 4;
4330   }
4331 }; 
4332
4333 struct B : A {  
4334   B()  { CHECK(a == 1); } 
4335   virtual ~B() { CHECK(a == 3); }
4336 };
4337 struct C : B {
4338   C()  { a = 2; }
4339   virtual ~C() { a = 3; } 
4340 };
4341
4342 int            GLOBAL = 0;
4343 int           *STACK  = 0;
4344 STRUCT         GLOB_STRUCT;
4345 STRUCT        *STACK_STRUCT;
4346 STRUCT        *HEAP_STRUCT;
4347
4348 void Worker() {
4349   GLOBAL = 1;
4350   *STACK = 1;
4351   GLOB_STRUCT.b   = 1;
4352   STACK_STRUCT->b = 1;
4353   HEAP_STRUCT->b  = 1;
4354 }
4355
4356 void 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 }
4376 REGISTER_TEST2(Run, 89, FEATURE|EXCLUDE_FROM_ALL)
4377 }  // namespace test89
4378
4379
4380 // test90: FP. Test for a safely-published pointer (read-only). {{{1
4381 namespace 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
4393 int     *GLOB = 0;
4394 Mutex   MU; 
4395
4396 void 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
4406 void 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
4419 void 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 }
4427 REGISTER_TEST(Run, 90)
4428 }  // namespace test90
4429
4430
4431 // test91: FP. Test for a safely-published pointer (read-write). {{{1
4432 namespace 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
4440 int     *GLOB = 0;
4441 Mutex   MU, MU1, MU2; 
4442
4443 void 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
4452 void 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
4468 void 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 }
4476 REGISTER_TEST(Run, 91)
4477 }  // namespace test91
4478
4479
4480 // test92: TN. Test for a safely-published pointer (read-write), annotated. {{{1
4481 namespace 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
4499 struct ObjType {
4500   int arr[10];
4501 };
4502
4503 ObjType *GLOB = 0;
4504 Mutex   MU, MU1, MU2; 
4505
4506 void 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
4517 void 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
4532 void Accessor0() { Accessor(0); }
4533 void Accessor5() { Accessor(5); }
4534 void Accessor9() { Accessor(9); }
4535
4536 void 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 }
4543 REGISTER_TEST(Run, 92)
4544 }  // namespace test92
4545
4546
4547 // test93: TP. Test for incorrect usage of ANNOTATE_PUBLISH_MEMORY_RANGE. {{{1
4548 namespace test93 {
4549 int     GLOB = 0;
4550
4551 void Reader() {
4552   CHECK(GLOB == 0);
4553 }
4554
4555 void 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
4561 void 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 }
4568 REGISTER_TEST2(Run, 93, FEATURE|EXCLUDE_FROM_ALL)
4569 }  // namespace test93
4570
4571
4572 // test94: TP. Check do_cv_signal/fake segment logic {{{1
4573 namespace test94 {
4574 int     GLOB;
4575
4576 int COND  = 0;
4577 int COND2 = 0;
4578 Mutex MU, MU2;
4579 CondVar CV, CV2;
4580
4581 void 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 }
4591 void 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 }
4600 void Thr3() {
4601   MU.Lock();
4602   while(COND != 1)
4603     CV.Wait(&MU);
4604   MU.Unlock();  
4605 }
4606 void 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 }
4613 void 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 }
4622 REGISTER_TEST(Run, 94);
4623 }  // namespace test94
4624
4625 // test95: TP. Check do_cv_signal/fake segment logic {{{1
4626 namespace test95 {
4627 int     GLOB = 0;
4628
4629 int COND  = 0;
4630 int COND2 = 0;
4631 Mutex MU, MU2;
4632 CondVar CV, CV2;
4633
4634 void 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 }
4645 void Thr2() {
4646   usleep(10000);  // Make sure the waiter blocks.
4647   
4648   MU2.Lock();
4649   COND2 = 1;
4650   CV2.Signal(); 
4651   MU2.Unlock();
4652 }
4653 void Thr3() {
4654   MU.Lock();
4655   while(COND != 1)
4656     CV.Wait(&MU);
4657   MU.Unlock();  
4658 }
4659 void 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 }
4666 void 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 }
4675 REGISTER_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
4682 namespace test96 {
4683 int     GLOB = 0;
4684
4685 Mutex A, B, C;
4686
4687 void Thread1() {
4688   MutexLock a(&A);
4689   MutexLock b(&B);
4690   GLOB++;
4691 }
4692
4693 void Thread2() {
4694   MutexLock b(&B);
4695   MutexLock c(&C);
4696   GLOB++;
4697 }
4698
4699 void Thread3() {
4700   MutexLock a(&A);
4701   MutexLock c(&C);
4702   GLOB++;
4703 }
4704
4705 void 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 }
4714 REGISTER_TEST(Run, 96);
4715 }  // namespace test96
4716
4717 // test97: This test shows false negative with --fast-mode=yes {{{1
4718 namespace test97 {
4719 const int HG_CACHELINE_SIZE = 64;
4720
4721 Mutex MU;
4722
4723 const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4724 int array[ARRAY_SIZE];
4725 int * 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
4731 void Reader() {
4732   usleep(500000);
4733   CHECK(777 == *GLOB);
4734 }
4735
4736 void 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
4747 REGISTER_TEST2(Run, 97, FEATURE)
4748 }  // namespace test97
4749
4750 // test98: Synchronization via read/write (or send/recv). {{{1
4751 namespace 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 //
4762 int     GLOB = 0;
4763 int fd_out = -1;
4764 int fd_in  = -1;
4765
4766 void 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
4773 void 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
4781 void 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 }
4809 REGISTER_TEST(Run, 98)
4810 }  // namespace test98
4811
4812
4813 // test99: TP. Unit test for a bug in LockWhen*. {{{1
4814 namespace test99 {
4815
4816
4817 bool GLOB = false;
4818 Mutex mu;
4819
4820 static 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
4829 static void Thread2() {
4830   for (int i = 0; i < 100; i++) {
4831     mu.Lock();
4832     mu.Unlock();
4833     usleep(10000);
4834   }
4835 }
4836
4837 void Run() {
4838   printf("test99: regression test for LockWhen*\n");
4839   MyThreadArray t(Thread1, Thread2);
4840   t.Start();
4841   t.Join();
4842 }
4843 REGISTER_TEST(Run, 99);
4844 }  // namespace test99
4845
4846
4847 // test100: Test for initialization bit. {{{1
4848 namespace test100 {
4849 int     G1 = 0;
4850 int     G2 = 0;
4851 int     G3 = 0;
4852 int     G4 = 0;
4853
4854 void Creator() {
4855   G1 = 1; CHECK(G1);
4856   G2 = 1;
4857   G3 = 1; CHECK(G3);
4858   G4 = 1;
4859 }
4860
4861 void Worker1() {
4862   usleep(100000);
4863   CHECK(G1);
4864   CHECK(G2);
4865   G3 = 3;
4866   G4 = 3;
4867 }
4868
4869 void Worker2() {
4870
4871 }
4872
4873
4874 void 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 }
4884 REGISTER_TEST2(Run, 100, FEATURE|EXCLUDE_FROM_ALL)
4885 }  // namespace test100
4886
4887
4888 // test101: TN. Two signals and two waits. {{{1
4889 namespace test101 {
4890 Mutex MU;
4891 CondVar CV;
4892 int     GLOB = 0;
4893
4894 int C1 = 0, C2 = 0;
4895
4896 void 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
4914 void 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
4931 void Run() {
4932   printf("test101: negative\n");
4933   MyThreadArray t(Waiter, Signaller);
4934   t.Start();
4935   t.Join();
4936   printf("\tGLOB=%d\n", GLOB);
4937 }
4938 REGISTER_TEST(Run, 101)
4939 }  // namespace test101
4940
4941 // test102: --fast-mode=yes vs. --initialization-bit=yes {{{1
4942 namespace test102 {
4943 const int HG_CACHELINE_SIZE = 64;
4944
4945 Mutex MU;
4946
4947 const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4948 int array[ARRAY_SIZE + 1];
4949 int * 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
4955 void Reader() {
4956   usleep(200000);
4957   CHECK(777 == GLOB[0]);
4958   usleep(400000);
4959   CHECK(777 == GLOB[1]);
4960 }
4961
4962 void 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
4976 REGISTER_TEST2(Run, 102, FEATURE)
4977 }  // namespace test102
4978
4979 // test103: Access different memory locations with different LockSets {{{1
4980 namespace test103 {
4981 const int N_MUTEXES = 6;
4982 const int LOCKSET_INTERSECTION_SIZE = 3;
4983
4984 int data[1 << LOCKSET_INTERSECTION_SIZE] = {0};
4985 Mutex MU[N_MUTEXES];
4986
4987 inline int LS_to_idx (int ls) {
4988   return (ls >> (N_MUTEXES - LOCKSET_INTERSECTION_SIZE))
4989       & ((1 << LOCKSET_INTERSECTION_SIZE) - 1);
4990 }
4991
4992 void 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
5008 void 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 }
5014 REGISTER_TEST2(Run, 103, FEATURE)
5015 }  // namespace test103
5016
5017 // test104: TP. Simple race (write vs write). Heap mem. {{{1
5018 namespace test104 {
5019 int     *GLOB = NULL;
5020 void Worker() {
5021   *GLOB = 1; 
5022 }
5023
5024 void Parent() {
5025   MyThread t(Worker);
5026   t.Start();
5027   usleep(100000);
5028   *GLOB = 2;
5029   t.Join();
5030 }
5031 void 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 }
5041 REGISTER_TEST(Run, 104);
5042 }  // namespace test104
5043
5044
5045 // test105: Checks how stack grows. {{{1
5046 namespace test105 {
5047 int     GLOB = 0;
5048
5049 void 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
5057 void 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
5066 void 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 }
5074 REGISTER_TEST(Run, 105)
5075 }  // namespace test105
5076
5077
5078 // test106: TN. pthread_once. {{{1
5079 namespace test106 {
5080 int     *GLOB = NULL;
5081 static pthread_once_t once = PTHREAD_ONCE_INIT;
5082 void Init() {
5083   GLOB = new int;
5084   ANNOTATE_TRACE_MEMORY(GLOB);
5085   *GLOB = 777;
5086 }
5087
5088 void Worker0() {
5089   pthread_once(&once, Init);
5090 }
5091 void Worker1() {
5092   usleep(100000);
5093   pthread_once(&once, Init);
5094   CHECK(*GLOB == 777);
5095 }
5096
5097
5098 void 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 }
5105 REGISTER_TEST2(Run, 106, FEATURE)
5106 }  // namespace test106
5107
5108
5109 // test107: Test for ANNOTATE_EXPECT_RACE {{{1
5110 namespace test107 {
5111 int     GLOB = 0;
5112 void 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 }
5117 REGISTER_TEST2(Run, 107, FEATURE|EXCLUDE_FROM_ALL)
5118 }  // namespace test107
5119
5120
5121 // test108: TN. initialization of static object. {{{1
5122 namespace 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. 
5131 class 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
5142 const Foo *GetFoo() {
5143   static const Foo *foo = new Foo();
5144   return foo;
5145 }
5146 void Worker0() {
5147   GetFoo();
5148 }
5149
5150 void Worker() {
5151   usleep(200000);
5152   const Foo *foo = GetFoo();
5153   foo->Check();
5154 }
5155
5156
5157 void Run() {
5158   printf("test108: negative, initialization of static object\n");
5159   MyThreadArray t(Worker0, Worker, Worker);
5160   t.Start();
5161   t.Join();
5162 }
5163 REGISTER_TEST2(Run, 108, FEATURE)
5164 }  // namespace test108
5165
5166
5167 // test109: TN. Checking happens before between parent and child threads. {{{1
5168 namespace test109 {
5169 // Check that the detector correctly connects 
5170 //   pthread_create with the new thread
5171 // and 
5172 //   thread exit with pthread_join
5173 const int N = 32;
5174 static int GLOB[N];
5175
5176 void 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
5183 void 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 }
5205 REGISTER_TEST(Run, 109)
5206 }  // namespace test109
5207
5208
5209 // test110: TP. Simple races with stack, global and heap objects. {{{1
5210 namespace test110 {
5211 int        GLOB = 0;
5212 static int STATIC;
5213
5214 int       *STACK = 0;
5215
5216 int       *MALLOC;
5217 int       *CALLOC;
5218 int       *REALLOC;
5219 int       *VALLOC;
5220 int       *PVALLOC;
5221 int       *MEMALIGN;
5222 union pi_pv_union { int* pi; void* pv; } POSIX_MEMALIGN;
5223 int       *MMAP;
5224
5225 int       *NEW;
5226 int       *NEW_ARR;
5227
5228 void 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 }
5246 void 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 }
5311 REGISTER_TEST(Run, 110)
5312 }  // namespace test110
5313
5314
5315 // test111: TN. Unit test for a bug related to stack handling. {{{1
5316 namespace test111 {
5317 char     *GLOB = 0;
5318 bool COND = false;
5319 Mutex mu;
5320 const int N = 3000;
5321
5322 void write_to_p(char *p, int val) {
5323   for (int i = 0; i < N; i++) 
5324     p[i] = val;
5325 }
5326
5327 static bool ArgIsTrue(bool *arg) {
5328 //  printf("ArgIsTrue: %d tid=%d\n", *arg, (int)pthread_self());
5329   return *arg == true; 
5330 }
5331
5332 void f1() {
5333   char some_stack[N];
5334   write_to_p(some_stack, 1);
5335   mu.LockWhen(Condition(&ArgIsTrue, &COND));
5336   mu.Unlock();
5337 }
5338
5339 void 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
5346 void f0() { f2(); }
5347
5348 void Worker1() {
5349   f0();
5350   f1();
5351   f2();
5352 }
5353
5354 void Worker2() {
5355   usleep(100000);
5356   mu.Lock();
5357   COND = true;
5358   mu.Unlock();
5359 }
5360
5361 void 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 }
5369 REGISTER_TEST2(Run, 111, FEATURE)
5370 }  // namespace test111
5371
5372 // test112: STAB. Test for ANNOTATE_PUBLISH_MEMORY_RANGE{{{1
5373 namespace test112 {
5374 char     *GLOB = 0;
5375 const int N = 64 * 5;
5376 Mutex mu;
5377 bool ready = false; // under mu
5378 int beg, end; // under mu
5379
5380 Mutex mu1;
5381
5382 void 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
5402 void 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
5424 void 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 }
5448 REGISTER_TEST2(Run, 112, STABILITY)
5449 }  // namespace test112
5450
5451
5452 // test113: PERF. A lot of lock/unlock calls. Many locks {{{1
5453 namespace    test113 {
5454 const int kNumIter = 100000;
5455 const int kNumLocks = 7;
5456 Mutex   MU[kNumLocks]; 
5457 void 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 }
5468 REGISTER_TEST(Run, 113)
5469 }  // namespace test113
5470
5471
5472 // test114: STAB. Recursive lock. {{{1
5473 namespace    test114 {
5474 int Bar() {
5475   static int bar = 1;
5476   return bar;
5477 }
5478 int Foo() {
5479   static int foo = Bar();
5480   return foo;
5481 }
5482 void Worker() {
5483   static int x = Foo();
5484   CHECK(x == 1);
5485 }
5486 void Run() {
5487   printf("test114: stab\n");
5488   MyThreadArray t(Worker, Worker);
5489   t.Start();
5490   t.Join();
5491 }
5492 REGISTER_TEST(Run, 114)
5493 }  // namespace test114
5494
5495
5496 // test115: TN. sem_open. {{{1
5497 namespace    test115 {
5498 int tid = 0;
5499 Mutex mu;
5500 const char *kSemName = "drt-test-sem";
5501
5502 int GLOB = 0;
5503
5504 sem_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
5513 void 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
5534 void 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 }
5551 REGISTER_TEST(Run, 115)
5552 }  // namespace test115
5553
5554
5555 // test116: TN. some operations with string<> objects. {{{1
5556 namespace test116 {
5557
5558 void 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
5585 void Run() {
5586   printf("test116: negative (strings)\n");
5587   MyThreadArray t(Worker, Worker, Worker);
5588   t.Start();
5589   t.Join();
5590 }
5591 REGISTER_TEST2(Run, 116, FEATURE|EXCLUDE_FROM_ALL)
5592 }  // namespace test116
5593
5594 // test117: TN. Many calls to function-scope static init. {{{1
5595 namespace test117 {
5596 const int N = 50;
5597
5598 int Foo() {
5599   usleep(20000);
5600   return 1;
5601 }
5602
5603 void Worker(void *a) {
5604   static int foo = Foo();
5605   CHECK(foo == 1);
5606 }
5607
5608 void 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 }
5622 REGISTER_TEST(Run, 117)
5623 }  // namespace test117
5624
5625
5626
5627 // test118 PERF: One signal, multiple waits. {{{1
5628 namespace   test118 {
5629 int     GLOB = 0;
5630 const int kNumIter = 2000000;
5631 void Signaller() {
5632   usleep(50000);
5633   ANNOTATE_CONDVAR_SIGNAL(&GLOB);
5634 }
5635 void Waiter() {
5636   for (int i = 0; i < kNumIter; i++) {
5637     ANNOTATE_CONDVAR_WAIT(&GLOB);
5638     if (i == kNumIter / 2) 
5639       usleep(100000);
5640   }
5641 }
5642 void 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 }
5649 REGISTER_TEST(Run, 118)
5650 }  // namespace test118
5651
5652
5653 // test119: TP. Testing that malloc does not introduce any HB arc. {{{1
5654 namespace test119 {
5655 int     GLOB = 0;
5656 void Worker1() {
5657   GLOB = 1;
5658   free(malloc(123));
5659 }
5660 void Worker2() {
5661   usleep(100000);
5662   free(malloc(345));
5663   GLOB = 2;
5664 }
5665 void 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 }
5675 REGISTER_TEST(Run, 119)
5676 }  // namespace test119
5677
5678
5679 // test120: TP. Thread1: write then read. Thread2: read. {{{1
5680 namespace test120 {
5681 int     GLOB = 0;
5682
5683 void Thread1() {
5684   GLOB = 1;           // write
5685   CHECK(GLOB);        // read
5686 }
5687
5688 void Thread2() {
5689   usleep(100000);
5690   CHECK(GLOB >= 0);   // read
5691 }
5692
5693 void 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 }
5703 REGISTER_TEST(Run, 120)
5704 }  // namespace test120
5705
5706
5707 // test121: TP. Example of double-checked-locking  {{{1
5708 namespace test121 {
5709 struct Foo {
5710   uintptr_t a, b[15];
5711 } __attribute__ ((aligned (64)));
5712
5713 static Mutex mu;
5714 static Foo  *foo;
5715
5716 void 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
5729 void UseMe() { 
5730   InitMe();
5731   CHECK(foo && foo->a == 42); 
5732 }
5733
5734 void Worker1() { UseMe(); }
5735 void Worker2() { UseMe(); }
5736 void Worker3() { UseMe(); }
5737
5738
5739 void 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 }
5747 REGISTER_TEST(Run, 121)
5748 }  // namespace test121
5749
5750 // test122 TP: Simple test with RWLock {{{1
5751 namespace  test122 {
5752 int     VAR1 = 0;
5753 int     VAR2 = 0;
5754 RWLock mu;
5755
5756 void WriteWhileHoldingReaderLock(int *p) {
5757   usleep(100000);
5758   ReaderLockScoped lock(&mu);  // Reader lock for writing. -- bug.
5759   (*p)++;
5760 }
5761
5762 void CorrectWrite(int *p) {
5763   WriterLockScoped lock(&mu);
5764   (*p)++;
5765 }
5766
5767 void Thread1() { WriteWhileHoldingReaderLock(&VAR1); } 
5768 void Thread2() { CorrectWrite(&VAR1); }
5769 void Thread3() { CorrectWrite(&VAR2); }
5770 void Thread4() { WriteWhileHoldingReaderLock(&VAR2); } 
5771
5772
5773 void 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 }
5787 REGISTER_TEST(Run, 122)
5788 }  // namespace test122
5789
5790
5791 // test123 TP: accesses of different sizes. {{{1
5792 namespace test123 {
5793
5794 union uint_union {
5795   uint64_t u64[1];
5796   uint32_t u32[2];
5797   uint16_t u16[4];
5798   uint8_t  u8[8];
5799 };
5800
5801 uint_union MEM[8];
5802
5803 // Q. Hey dude, why so many functions? 
5804 // A. I need different stack traces for different accesses.
5805
5806 void Wr64_0() { MEM[0].u64[0] = 1; } 
5807 void Wr64_1() { MEM[1].u64[0] = 1; } 
5808 void Wr64_2() { MEM[2].u64[0] = 1; } 
5809 void Wr64_3() { MEM[3].u64[0] = 1; } 
5810 void Wr64_4() { MEM[4].u64[0] = 1; } 
5811 void Wr64_5() { MEM[5].u64[0] = 1; } 
5812 void Wr64_6() { MEM[6].u64[0] = 1; } 
5813 void Wr64_7() { MEM[7].u64[0] = 1; } 
5814
5815 void Wr32_0() { MEM[0].u32[0] = 1; } 
5816 void Wr32_1() { MEM[1].u32[1] = 1; } 
5817 void Wr32_2() { MEM[2].u32[0] = 1; } 
5818 void Wr32_3() { MEM[3].u32[1] = 1; } 
5819 void Wr32_4() { MEM[4].u32[0] = 1; } 
5820 void Wr32_5() { MEM[5].u32[1] = 1; } 
5821 void Wr32_6() { MEM[6].u32[0] = 1; } 
5822 void Wr32_7() { MEM[7].u32[1] = 1; } 
5823
5824 void Wr16_0() { MEM[0].u16[0] = 1; } 
5825 void Wr16_1() { MEM[1].u16[1] = 1; } 
5826 void Wr16_2() { MEM[2].u16[2] = 1; } 
5827 void Wr16_3() { MEM[3].u16[3] = 1; } 
5828 void Wr16_4() { MEM[4].u16[0] = 1; } 
5829 void Wr16_5() { MEM[5].u16[1] = 1; } 
5830 void Wr16_6() { MEM[6].u16[2] = 1; } 
5831 void Wr16_7() { MEM[7].u16[3] = 1; } 
5832
5833 void Wr8_0() { MEM[0].u8[0] = 1; } 
5834 void Wr8_1() { MEM[1].u8[1] = 1; } 
5835 void Wr8_2() { MEM[2].u8[2] = 1; } 
5836 void Wr8_3() { MEM[3].u8[3] = 1; } 
5837 void Wr8_4() { MEM[4].u8[4] = 1; } 
5838 void Wr8_5() { MEM[5].u8[5] = 1; } 
5839 void Wr8_6() { MEM[6].u8[6] = 1; } 
5840 void Wr8_7() { MEM[7].u8[7] = 1; } 
5841
5842 void 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
5853 void 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
5864 void 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
5875 void 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
5886 void W00() { WriteAll64(); } 
5887 void W01() { WriteAll64(); } 
5888 void W02() { WriteAll64(); } 
5889
5890 void W10() { WriteAll32(); } 
5891 void W11() { WriteAll32(); } 
5892 void W12() { WriteAll32(); } 
5893
5894 void W20() { WriteAll16(); } 
5895 void W21() { WriteAll16(); } 
5896 void W22() { WriteAll16(); } 
5897
5898 void W30() { WriteAll8(); } 
5899 void W31() { WriteAll8(); } 
5900 void W32() { WriteAll8(); } 
5901
5902 typedef void (*F)(void);
5903
5904 void 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
5919 void 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 }
5929 REGISTER_TEST2(Run, 123, FEATURE|EXCLUDE_FROM_ALL)
5930 }  // namespace test123
5931
5932
5933 // test124: What happens if we delete an unlocked lock? {{{1
5934 namespace test124 {
5935 // This test does not worg with pthreads (you can't call 
5936 // pthread_mutex_destroy on a locked lock).
5937 int     GLOB = 0;
5938 const int N = 1000;
5939 void 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
5949 void 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 }
5956 REGISTER_TEST2(Run, 124, FEATURE|EXCLUDE_FROM_ALL)
5957 }  // namespace test124
5958
5959
5960 // test125 TN: Backwards lock (annotated). {{{1
5961 namespace 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
5972 const int n_threads = 3;
5973 RWLock   mu;
5974 int     GLOB[n_threads];
5975
5976 int adder_num; // updated atomically.
5977
5978 void Adder() {
5979   int my_num = AtomicIncrement(&adder_num, 1);
5980
5981   ReaderLockScoped lock(&mu);
5982   GLOB[my_num]++;
5983 }
5984
5985 void 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
5996 void 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 }
6017 REGISTER_TEST(Run, 125)
6018 }  // namespace test125
6019
6020 // test126 TN: test for BlockingCounter {{{1
6021 namespace  test126 {
6022 BlockingCounter *blocking_counter;
6023 int     GLOB = 0;
6024 void Worker() {
6025   CHECK(blocking_counter);
6026   CHECK(GLOB == 0);
6027   blocking_counter->DecrementCount();
6028 }
6029 void 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 }
6039 REGISTER_TEST(Run, 126)
6040 }  // namespace test126
6041
6042
6043 // test127. Bad code: unlocking a mutex locked by another thread. {{{1
6044 namespace test127 {
6045 Mutex mu;
6046 void Thread1() {
6047   mu.Lock();
6048 }
6049 void Thread2() {
6050   usleep(100000);
6051   mu.Unlock();
6052 }
6053 void Run() {
6054   printf("test127: unlocking a mutex locked by another thread.\n");
6055   MyThreadArray t(Thread1, Thread2);
6056   t.Start();
6057   t.Join();
6058 }
6059 REGISTER_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.
6064 namespace test128 {
6065 Mutex mu;
6066 int GLOB = 0;
6067 void Worker() {
6068   usleep(100000);
6069   mu.Lock();
6070   GLOB++;
6071   mu.Unlock();
6072 }
6073 void ThisFunctionShouldBeSuppressed() {
6074   GLOB++;
6075 }
6076 void Run() {
6077   printf("test128: Suppressed code in concurrent accesses.\n");
6078   MyThreadArray t(Worker, ThisFunctionShouldBeSuppressed);
6079   t.Start();
6080   t.Join();
6081 }
6082 REGISTER_TEST2(Run, 128, FEATURE | EXCLUDE_FROM_ALL)
6083 }  // namespace test128
6084
6085 // test129: TN. Synchronization via ReaderLockWhen(). {{{1
6086 namespace test129 {  
6087 int     GLOB = 0;
6088 Mutex   MU; 
6089 bool WeirdCondition(int* param) {
6090   *param = GLOB;  // a write into Waiter's memory
6091   return GLOB > 0;
6092 }
6093 void Waiter() {
6094   int param = 0;
6095   MU.ReaderLockWhen(Condition(WeirdCondition, &param));
6096   MU.ReaderUnlock();
6097   CHECK(GLOB > 0);
6098   CHECK(param > 0);
6099 }
6100 void Waker() {
6101   usleep(100000);  // Make sure the waiter blocks.
6102   MU.Lock();
6103   GLOB++;
6104   MU.Unlock();     // calls ANNOTATE_CONDVAR_SIGNAL;
6105 }
6106 void 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 }
6114 REGISTER_TEST2(Run, 129, FEATURE);
6115 }  // namespace test129
6116
6117 // test130: TN. Per-thread. {{{1
6118 namespace 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
6135 static __thread int per_thread_global[10] = {0};
6136
6137 void RealWorker() {  // Touch per_thread_global.
6138   per_thread_global[1]++;
6139   errno++;
6140 }
6141
6142 void Worker() {  // Spawn few threads that touch per_thread_global.
6143   MyThreadArray t(RealWorker, RealWorker);
6144   t.Start();
6145   t.Join();
6146 }
6147 void Worker0() { sleep(0); Worker(); }
6148 void Worker1() { sleep(1); Worker(); }
6149 void Worker2() { sleep(2); Worker(); }
6150 void Worker3() { sleep(3); Worker(); }
6151
6152 void 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 }
6159 REGISTER_TEST(Run, 130)
6160 #endif // NO_TLS
6161 }  // namespace test130
6162
6163
6164 // test131: TN. Stack. {{{1
6165 namespace test131 {
6166 // Same as test130, but for stack.
6167
6168 void RealWorker() {  // Touch stack.
6169   int stack_var = 0;
6170   stack_var++;
6171 }
6172
6173 void Worker() {  // Spawn few threads that touch stack.
6174   MyThreadArray t(RealWorker, RealWorker);
6175   t.Start();
6176   t.Join();
6177 }
6178 void Worker0() { sleep(0); Worker(); }
6179 void Worker1() { sleep(1); Worker(); }
6180 void Worker2() { sleep(2); Worker(); }
6181 void Worker3() { sleep(3); Worker(); }
6182
6183 void Run() {
6184   printf("test131: stack\n");
6185   MyThreadArray t(Worker0, Worker1, Worker2, Worker3);
6186   t.Start();
6187   t.Join();
6188 }
6189 REGISTER_TEST(Run, 131)
6190 }  // namespace test131
6191
6192
6193 // test132: TP. Simple race (write vs write). Works in fast-mode. {{{1
6194 namespace test132 {
6195 int     GLOB = 0;
6196 void Worker() { GLOB = 1; }
6197
6198 void 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
6209 void Run() {
6210   Run1();
6211 }
6212 REGISTER_TEST(Run, 132);
6213 }  // namespace test132
6214
6215
6216 // test133: TP. Simple race (write vs write). Works in fast mode. {{{1
6217 namespace test133 {
6218 // Same as test132, but everything is run from a separate thread spawned from
6219 // the main thread.
6220 int     GLOB = 0;
6221 void Worker() { GLOB = 1; }
6222
6223 void 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 }
6233 void Run() {
6234   MyThread t(Run1);
6235   t.Start();
6236   t.Join();
6237 }
6238 REGISTER_TEST(Run, 133);
6239 }  // namespace test133
6240
6241
6242 // test134 TN. Swap. Variant of test79. {{{1
6243 namespace test134 {
6244 #if 0
6245 typedef __gnu_cxx::hash_map<int, int> map_t;
6246 #else
6247 typedef std::map<int, int> map_t;
6248 #endif
6249 map_t   map;
6250 Mutex   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.
6262 void 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
6272 void Worker() {
6273   MutexLock lock(&mu);
6274   ANNOTATE_HAPPENS_AFTER(&map);
6275   map[1]++;
6276   ANNOTATE_HAPPENS_BEFORE(&map);
6277 }
6278
6279 void 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 }
6287 REGISTER_TEST(Run, 134)
6288 }  // namespace test134
6289
6290 // test135 TN. Swap. Variant of test79. {{{1
6291 namespace test135 {
6292
6293 void 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
6303 void Worker() {
6304   MyThreadArray t(SubWorker, SubWorker, SubWorker, SubWorker);
6305   t.Start();
6306   t.Join();
6307 }
6308
6309 void Run() {
6310   printf("test135: negative (mmap)\n");
6311   MyThreadArray t(Worker, Worker, Worker, Worker);
6312   t.Start();
6313   t.Join();
6314 }
6315 REGISTER_TEST(Run, 135)
6316 }  // namespace test135
6317
6318 // test136. Unlock twice. {{{1
6319 namespace test136 {
6320 void 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
6337 REGISTER_TEST(Run, 136)
6338 }  // namespace test136
6339
6340 // test137 TP. Races on stack variables. {{{1
6341 namespace test137 {
6342 int GLOB = 0;
6343 ProducerConsumerQueue q(10);
6344
6345 void 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
6356 void 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
6366 REGISTER_TEST2(Run, 137, FEATURE | EXCLUDE_FROM_ALL)
6367 }  // namespace test137
6368
6369 // test138 FN. Two closures hit the same thread in ThreadPool. {{{1
6370 namespace test138 {
6371 int GLOB = 0;
6372
6373 void Worker() {
6374   usleep(100000);
6375   GLOB++;
6376 }
6377
6378 void 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
6394 REGISTER_TEST2(Run, 138, FEATURE)
6395 }  // namespace test138
6396
6397 // test139: FN. A true race hidden by reference counting annotation. {{{1
6398 namespace test139 {
6399 int GLOB = 0;
6400 RefCountedClass *obj;
6401
6402 void Worker1() {
6403   GLOB++;  // First access.
6404   obj->Unref();
6405 }
6406
6407 void Worker2() {
6408   usleep(100000);
6409   obj->Unref();
6410   GLOB++;  // Second access.
6411 }
6412
6413 void 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
6426 REGISTER_TEST2(Run, 139, FEATURE)
6427 }  // namespace test139
6428
6429 // test140 TN. Swap. Variant of test79 and test134. {{{1
6430 namespace test140 {
6431 #if 0
6432 typedef __gnu_cxx::hash_map<int, int> Container;
6433 #else
6434 typedef std::map<int,int>             Container;
6435 #endif
6436 Mutex mu;
6437 static 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.
6454 void 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
6470 void 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
6483 void Run() {
6484   printf("test140: negative (swap) %p\n", &container);
6485   MyThreadArray t(Worker, Worker, Swapper, Worker, Worker);
6486   t.Start();
6487   t.Join();
6488 }
6489 REGISTER_TEST(Run, 140)
6490 }  // namespace test140
6491
6492 // test141 FP. unlink/fopen, rmdir/opendir. {{{1
6493 namespace test141 {
6494 int GLOB1 = 0,
6495     GLOB2 = 0;
6496 char *dir_name = NULL,
6497      *filename = NULL;
6498
6499 void 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
6508 void 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
6518 void 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
6527 void 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
6537 void 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 }
6562 REGISTER_TEST(Run, 141)
6563 }  // namespace test141
6564
6565
6566 // Simple FIFO queue annotated with PCQ annotations. {{{1
6567 class 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
6595 namespace 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
6600 const int N = 1000;
6601 int array[N+1];
6602
6603 FifoMessageQueue q;
6604
6605 void Putter() {
6606   for (int i = 1; i <= N; i++) {
6607     array[i] = i*i;
6608     q.Put(i);
6609     usleep(1000);
6610   }
6611 }
6612
6613 void 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=%d: non_zero_received=%d\n", 
6624          (int)pthread_self(), non_zero_received);
6625
6626
6627 void Run() {
6628   printf("test142: tests PCQ annotations\n");
6629   MyThreadArray t(Putter, Getter, Getter);
6630   t.Start();
6631   t.Join();
6632 }
6633 REGISTER_TEST(Run, 142)
6634 }  // namespace test142
6635
6636
6637 // test143: TP. Check PCQ_* annotations. {{{1
6638 namespace 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.
6645 int     GLOB = 0;
6646
6647 FifoMessageQueue q;
6648
6649 void Putter() {
6650   GLOB = 1;
6651   q.Put(1);
6652 }
6653
6654 void Getter() {
6655   usleep(10000);
6656   q.Get();
6657   CHECK(GLOB == 1);  // Race here
6658 }
6659
6660 void 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 }
6670 REGISTER_TEST(Run, 143);
6671 }  // namespace test143
6672
6673
6674
6675
6676 // test300: {{{1
6677 namespace test300 {
6678 int     GLOB = 0;
6679 void Run() {
6680 }
6681 REGISTER_TEST2(Run, 300, RACE_DEMO)
6682 }  // namespace test300
6683
6684 // test301: Simple race.  {{{1
6685 namespace test301 {
6686 Mutex mu1;  // This Mutex guards var.
6687 Mutex mu2;  // This Mutex is not related to var.
6688 int   var;  // GUARDED_BY(mu1)
6689
6690 void Thread1() {  // Runs in thread named 'test-thread-1'.
6691   MutexLock lock(&mu1);  // Correct Mutex.
6692   var = 1; 
6693 }
6694
6695 void Thread2() {  // Runs in thread named 'test-thread-2'.
6696   MutexLock lock(&mu2);  // Wrong Mutex.
6697   var = 2; 
6698 }
6699
6700 void 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 }
6710 REGISTER_TEST2(Run, 301, RACE_DEMO)
6711 }  // namespace test301
6712
6713 // test302: Complex race which happens at least twice.  {{{1
6714 namespace test302 {
6715 // In this test we have many different accesses to GLOB and only one access 
6716 // is not synchronized properly. 
6717 int     GLOB = 0;
6718
6719 Mutex MU1;
6720 Mutex MU2;
6721 void 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
6747 void 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 }
6754 REGISTER_TEST2(Run, 302, RACE_DEMO)
6755 }  // namespace test302
6756
6757
6758 // test303: Need to trace the memory to understand the report. {{{1
6759 namespace test303 {
6760 int     GLOB = 0;
6761
6762 Mutex MU;
6763 void Worker1() { CHECK(GLOB >= 0); }
6764 void Worker2() { MU.Lock(); GLOB=1;  MU.Unlock();}
6765
6766 void 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 }
6773 REGISTER_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
6779 namespace test304 {
6780 string *STR;
6781 Mutex   MU; 
6782
6783 void Worker1() {
6784   sleep(0); 
6785   ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6786   MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
6787 }
6788 void Worker2() {
6789   sleep(1);            
6790   ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6791   CHECK(STR->length() >= 4); // Unprotected! 
6792 }
6793 void Worker3() {
6794   sleep(2); 
6795   ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6796   MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
6797 }
6798 void Worker4() {
6799   sleep(3); 
6800   ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6801   MU.Lock(); *STR += " + a very very long string"; MU.Unlock();  
6802 }
6803
6804 void 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 }
6814 REGISTER_TEST2(Run, 304, RACE_DEMO)
6815 }  // namespace test304
6816
6817
6818
6819 // test305: A bit more tricky: two locks used inconsistenly. {{{1
6820 namespace test305 {
6821 int     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.
6832 Mutex MU1;
6833 Mutex MU2;
6834 void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
6835 void Worker2() { MU1.Lock();             GLOB=2;               MU1.Unlock(); }
6836 void Worker3() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
6837 void Worker4() {             MU2.Lock(); GLOB=4; MU2.Unlock();               }
6838
6839 void 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 }
6849 REGISTER_TEST2(Run, 305, RACE_DEMO)
6850 }  // namespace test305
6851
6852 // test306: Two locks are used to protect a var.  {{{1
6853 namespace test306 {
6854 int     GLOB = 0;
6855 // Thread1 and Thread2 access the var under two locks.
6856 // Thread3 uses no locks.
6857
6858 Mutex MU1;
6859 Mutex MU2;
6860 void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
6861 void Worker2() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
6862 void Worker3() {                         GLOB=4;               }
6863
6864 void 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 }
6873 REGISTER_TEST2(Run, 306, RACE_DEMO)
6874 }  // namespace test306
6875
6876 // test307: Simple race, code with control flow  {{{1
6877 namespace test307 {
6878 int     *GLOB = 0;
6879 volatile /*to fake the compiler*/ bool some_condition = true;
6880
6881
6882 void SomeFunc() { }
6883
6884 int 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
6899 void Worker1() { FunctionWithControlFlow(); }
6900 void Worker2() { Worker1(); }
6901 void Worker3() { Worker2(); }
6902 void Worker4() { Worker3(); }
6903
6904 void 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 }
6912 REGISTER_TEST2(Run, 307, RACE_DEMO)
6913 }  // namespace test307
6914
6915 // test308: Example of double-checked-locking  {{{1
6916 namespace test308 {
6917 struct Foo {
6918   int a;
6919 };
6920
6921 static int   is_inited = 0;
6922 static Mutex lock;
6923 static Foo  *foo;
6924
6925 void 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
6937 void UseMe() { 
6938   InitMe();
6939   CHECK(foo && foo->a == 42); 
6940 }
6941
6942 void Worker1() { UseMe(); }
6943 void Worker2() { UseMe(); }
6944 void Worker3() { UseMe(); }
6945
6946
6947 void 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 }
6954 REGISTER_TEST2(Run, 308, RACE_DEMO)
6955 }  // namespace test308
6956
6957 // test309: Simple race on an STL object.  {{{1
6958 namespace test309 {
6959 string  GLOB;
6960
6961 void Worker1() { 
6962   GLOB="Thread1";
6963 }
6964 void Worker2() { 
6965   usleep(100000);
6966   GLOB="Booooooooooo"; 
6967 }
6968
6969 void 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 }
6976 REGISTER_TEST2(Run, 309, RACE_DEMO)
6977 }  // namespace test309
6978
6979 // test310: One more simple race.  {{{1
6980 namespace test310 {
6981 int     *PTR = NULL;  // GUARDED_BY(mu1)
6982
6983 Mutex mu1;  // Protects PTR.
6984 Mutex mu2;  // Unrelated to PTR.
6985 Mutex mu3;  // Unrelated to PTR.
6986
6987 void Writer1() {
6988   MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
6989   MutexLock lock1(&mu1);  // Protect PTR.
6990   *PTR = 1; 
6991 }
6992
6993 void 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
7003 void 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.
7009 void DoWrite1() { Writer1();  }
7010 void Thread1()  { DoWrite1(); }
7011
7012 void DoWrite2() { Writer2();  }
7013 void Thread2()  { DoWrite2(); }
7014
7015 void DoRead()  { Reader();  }
7016 void Thread3() { DoRead();  }
7017
7018 void 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 }
7035 REGISTER_TEST2(Run, 310, RACE_DEMO)
7036 }  // namespace test310
7037
7038 // test311: Yet another simple race.  {{{1
7039 namespace test311 {
7040 int     *PTR = NULL;  // GUARDED_BY(mu1)
7041
7042 Mutex mu1;  // Protects PTR.
7043 Mutex mu2;  // Unrelated to PTR.
7044 Mutex mu3;  // Unrelated to PTR.
7045
7046 void GoodWriter1() {
7047   MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
7048   MutexLock lock1(&mu1);  // Protect PTR.
7049   *PTR = 1; 
7050 }
7051
7052 void GoodWriter2() {
7053   MutexLock lock2(&mu2);  // This lock is unrelated to PTR.
7054   MutexLock lock1(&mu1);  // Protect PTR.
7055   *PTR = 2; 
7056 }
7057
7058 void GoodReader() {
7059   MutexLock lock1(&mu1);  // Protect PTR.
7060   CHECK(*PTR >= 0); 
7061 }
7062
7063 void BuggyWriter() {
7064   MutexLock lock2(&mu2);  // Wrong mutex!
7065   *PTR = 3;
7066 }
7067
7068 // Some functions to make the stack trace non-trivial.
7069 void DoWrite1() { GoodWriter1();  }
7070 void Thread1()  { DoWrite1(); }
7071
7072 void DoWrite2() { GoodWriter2();  }
7073 void Thread2()  { DoWrite2(); }
7074
7075 void DoGoodRead()  { GoodReader();  }
7076 void Thread3()     { DoGoodRead();  }
7077
7078 void DoBadWrite()  { BuggyWriter(); }
7079 void Thread4()     { DoBadWrite(); }
7080
7081 void 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 }
7103 REGISTER_TEST2(Run, 311, RACE_DEMO)
7104 }  // namespace test311
7105
7106 // test312: A test with a very deep stack. {{{1
7107 namespace test312 {
7108 int     GLOB = 0;
7109 void RaceyWrite() { GLOB++; }
7110 void Func1() { RaceyWrite(); }
7111 void Func2() { Func1(); }
7112 void Func3() { Func2(); }
7113 void Func4() { Func3(); }
7114 void Func5() { Func4(); }
7115 void Func6() { Func5(); }
7116 void Func7() { Func6(); }
7117 void Func8() { Func7(); }
7118 void Func9() { Func8(); }
7119 void Func10() { Func9(); }
7120 void Func11() { Func10(); }
7121 void Func12() { Func11(); }
7122 void Func13() { Func12(); }
7123 void Func14() { Func13(); }
7124 void Func15() { Func14(); }
7125 void Func16() { Func15(); }
7126 void Func17() { Func16(); }
7127 void Func18() { Func17(); }
7128 void Func19() { Func18(); }
7129 void Worker() { Func19(); }
7130 void Run() {
7131   printf("test312: simple race with deep stack.\n");
7132   MyThreadArray t(Worker, Worker, Worker);
7133   t.Start();
7134   t.Join();
7135 }
7136 REGISTER_TEST2(Run, 312, RACE_DEMO)
7137 }  // namespace test312
7138
7139 // test313 TP: test for thread graph output {{{1
7140 namespace  test313 {
7141 BlockingCounter *blocking_counter;
7142 int     GLOB = 0;
7143
7144 // Worker(N) will do 2^N increments of GLOB, each increment in a separate thread
7145 void 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 }
7156 void Run() {
7157   printf("test313: positive\n");
7158   Worker(4);
7159   printf("\tGLOB=%d\n", GLOB);
7160 }
7161 REGISTER_TEST2(Run, 313, RACE_DEMO)
7162 }  // namespace test313
7163
7164
7165
7166 // test400: Demo of a simple false positive. {{{1
7167 namespace test400 {
7168 static Mutex mu;
7169 static vector<int> *vec; // GUARDED_BY(mu);
7170
7171 void InitAllBeforeStartingThreads() {
7172   vec = new vector<int>;
7173   vec->push_back(1);
7174   vec->push_back(2);
7175 }
7176
7177 void Thread1() {
7178   MutexLock lock(&mu);
7179   vec->pop_back();
7180 }
7181
7182 void Thread2() {
7183   MutexLock lock(&mu);
7184   vec->pop_back();
7185 }
7186
7187 //---- Sub-optimal code ---------
7188 size_t NumberOfElementsLeft() {
7189   MutexLock lock(&mu);
7190   return vec->size(); 
7191 }
7192
7193 void 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
7210 bool NoElementsLeft(vector<int> *v) {
7211   return v->empty();
7212 }
7213
7214 void 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
7224 void Run() {
7225   MyThreadArray t(Thread1, Thread2);
7226   InitAllBeforeStartingThreads();
7227   t.Start();
7228   WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly();
7229 //  WaitForAllThreadsToFinish_Good();
7230   t.Join();
7231 }
7232 REGISTER_TEST2(Run, 400, RACE_DEMO)
7233 }  // namespace test400
7234
7235 // test401: Demo of false positive caused by reference counting. {{{1
7236 namespace 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
7241 static vector<int> *vec;
7242 static int ref_count;
7243
7244 void 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.
7251 int DecRef() {
7252   return AtomicIncrement(&ref_count, -1);
7253 }
7254
7255 // Correct and friendly to race detectors.
7256 int 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
7265 void 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
7275 void Run() {
7276   MyThreadArray t(ThreadWorker, ThreadWorker, ThreadWorker);
7277   InitAllBeforeStartingThreads(3 /*number of threads*/);
7278   t.Start();
7279   t.Join();
7280   CHECK(vec == 0);
7281 }
7282 REGISTER_TEST2(Run, 401, RACE_DEMO)
7283 }  // namespace test401
7284
7285 // test501: Manually call PRINT_* annotations {{{1
7286 namespace test501 {
7287 int  COUNTER = 0;
7288 int     GLOB = 0;
7289 Mutex muCounter, muGlob[65];
7290
7291 void 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
7305 void Worker_1() {
7306    MyThreadArray ta (Worker, Worker, Worker, Worker);
7307    ta.Start();
7308    usleep(500000);
7309    ta.Join ();   
7310 }
7311
7312 void Worker_2() {
7313    MyThreadArray ta (Worker_1, Worker_1, Worker_1, Worker_1);
7314    ta.Start();
7315    usleep(300000);
7316    ta.Join ();   
7317 }
7318
7319 void 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
7330 REGISTER_TEST2(Run, 501, FEATURE | EXCLUDE_FROM_ALL)
7331 }  // namespace test501
7332
7333 // test502: produce lots of segments without cross-thread relations {{{1
7334 namespace 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
7345 Mutex MU;
7346 int     GLOB = 0;
7347
7348 void TP() {
7349    for (int i = 0; i < 750000; i++) {
7350       MU.Lock();
7351       GLOB++;
7352       MU.Unlock();
7353    }
7354 }
7355
7356 void 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
7364 REGISTER_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%
7370 namespace test503 {
7371
7372 //  |- |  |  |  |  |
7373 //  | \|  |  |  |  |
7374 //  |  |- |  |  |  |
7375 //  |  | \|  |  |  |
7376 //  |  |  |- |  |  |
7377 //  |  |  | \|  |  |
7378 //  |  |  |  |- |  |
7379 //  |  |  |  | \|  |
7380 //  |  |  |  |  |- |
7381 //  |  |  |  |  | \|
7382 //  |  |  |  |  |  |----
7383 //->|  |  |  |  |  |
7384 //  |- |  |  |  |  |
7385 //  | \|  |  |  |  |
7386 //     ...
7387   
7388 const int N_threads = 32;
7389 const int ARRAY_SIZE = 128;
7390 int       GLOB[ARRAY_SIZE];
7391 ProducerConsumerQueue *Q[N_threads];
7392 int GLOB_limit = 100000;
7393 int count = -1;
7394
7395 void 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
7414 void 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
7432 REGISTER_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
7437 namespace test504 {
7438
7439 const 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 
7448 const int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
7449           ITERATIONS = 30;
7450 int array[ARRAY_SIZE];
7451
7452 int count = 0;
7453 Mutex count_mu;
7454
7455 void 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
7471 void Run() {
7472    printf("test504: force massive CacheLineZ fetch-wback\n");
7473    MyThreadArray t(Worker, Worker);
7474    t.Start();
7475    t.Join();
7476 }
7477
7478 REGISTER_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)
7484 namespace test505 {
7485
7486 const 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
7491 const int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
7492           ITERATIONS = 3;
7493 int64_t array[ARRAY_SIZE];
7494
7495 int count = 0;
7496 Mutex count_mu;
7497
7498 void 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
7522 void Run() {
7523    printf("test505: force massive CacheLineF fetch-wback\n");
7524    MyThreadArray t(Worker, Worker);
7525    t.Start();
7526    t.Join();
7527 }
7528
7529 REGISTER_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
7536 namespace test506 {
7537 #ifndef NO_BARRIER
7538 // Same as test17 but uses Barrier class (pthread_barrier_t). 
7539 int     GLOB = 0;
7540 const int N_threads = 64,
7541           ITERATIONS = 1000;
7542 Barrier *barrier[ITERATIONS];
7543 Mutex   MU; 
7544
7545 void Worker() {
7546   for (int i = 0; i < ITERATIONS; i++) {
7547      MU.Lock();
7548      GLOB++;
7549      MU.Unlock();
7550      barrier[i]->Block();
7551   }
7552 }
7553 void 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 }
7570 REGISTER_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
7576 namespace test507 {
7577 const int N_THREADS    = 1,
7578           BUFFER_SIZE  = 1,
7579           ITERATIONS   = 1 << 20;
7580
7581 void 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
7594 void Worker() {
7595   for (int j = 0; j < ITERATIONS; j++) {
7596     Foo();
7597   }
7598 }
7599
7600 void 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 }
7610 REGISTER_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
7615 namespace test508 {
7616 const int N_THREADS    = 1,
7617           BUFFER_SIZE  = 1 << 10,
7618           ITERATIONS   = 1 << 9;
7619
7620 void 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
7633 void Worker() {
7634   for (int j = 0; j < ITERATIONS; j++) {
7635     Foo();
7636   }
7637 }
7638
7639 void 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 }
7649 REGISTER_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
7654 namespace test509 {
7655 const int N_THREADS    = 16,
7656           ITERATIONS   = 1 << 8;
7657
7658 void 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
7672 void 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 }
7682 REGISTER_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
7687 namespace test510 {
7688 const int N_THREADS    = 16,
7689           ITERATIONS   = 1 << 10;
7690 int GLOB = 0;
7691
7692 void 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
7701 void 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 }
7712 REGISTER_TEST2(Run, 510, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7713 }  // namespace test510
7714
7715 // test511: Segment refcounting test ('1' refcounting) {{{1
7716 namespace test511 {
7717 int GLOB = 0;
7718
7719 void 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 }
7729 REGISTER_TEST2(Run, 511, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7730 }  // namespace test511
7731
7732 // test512: Segment refcounting test ('S' refcounting) {{{1
7733 namespace test512 {
7734 int GLOB = 0;
7735 sem_t SEM;
7736
7737 void 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 }
7749 REGISTER_TEST2(Run, 512, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7750 }  // namespace test512
7751
7752 // test513: --fast-mode benchmark {{{1
7753 namespace test513 {
7754
7755 const 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
7762 const int ITERATIONS = 1024;
7763 int array[N_THREADS][ARRAY_SIZE];
7764
7765 int count = 0;
7766 Mutex count_mu;
7767 Mutex mutex_arr[N_THREADS][MUTEX_ID_BITS];
7768
7769 void 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
7791 void 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
7802 REGISTER_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