2 This file is part of Valgrind, a dynamic binary instrumentation
5 Copyright (C) 2008-2008 Google Inc
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.
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.
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
23 The GNU General Public License is contained in the file COPYING.
26 // Author: Konstantin Serebryany <opensource@google.com>
28 // This file contains a set of unit tests for a data race detection tool.
32 // This test can be compiled with pthreads (default) or
33 // with any other library that supports threads, locks, cond vars, etc.
35 // To compile with pthreads:
36 // g++ racecheck_unittest.cc dynamic_annotations.cc
37 // -lpthread -g -DDYNAMIC_ANNOTATIONS=1
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.
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"
51 #include THREAD_WRAPPERS
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
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)
65 #ifndef ANNOTATE_PRINT_STATS
66 #define ANNOTATE_PRINT_STATS() do { } while(0)
68 #ifndef ANNOTATE_PRINT_MEMORY_USAGE
69 #define ANNOTATE_PRINT_MEMORY_USAGE(a) do { } while(0)
73 // A function that allows to suppress gcc's warnings about
74 // unused return values in a portable way.
76 static inline void IGNORE_RETURN_VALUE(T v)
84 #include <cstring> // strlen(), index(), rindex()
87 #include <sys/types.h>
90 #include <sys/mman.h> // mmap
92 #include <stdint.h> // uintptr_t
101 // - Stability tests (marked STAB)
102 // - Performance tests (marked PERF)
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.
109 // The feature tests are marked according to the behavior of helgrind 3.3.0.
111 // TP and FP tests are annotated with ANNOTATE_EXPECT_RACE,
112 // so, no error reports should be seen when running under helgrind.
114 // When some of the FP cases are fixed in helgrind we'll need
115 // to update this test.
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.
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.
126 // Globals and utilities used by several tests. {{{1
131 typedef void (*void_func_void_t)(void);
135 PERFORMANCE = 1 << 2,
136 EXCLUDE_FROM_ALL = 1 << 3,
137 NEEDS_ANNOTATIONS = 1 << 4,
139 MEMORY_USAGE = 1 << 6,
143 // Put everything into stderr.
145 #define printf(args...) \
148 fprintf(stderr, args);\
149 printf_mu.Unlock(); \
154 gettimeofday(&tv, NULL);
155 return (tv.tv_sec * 1000L) + (tv.tv_usec / 1000L);
161 Test(void_func_void_t f, int flags)
165 Test() : f_(0), flags_(0) {}
167 ANNOTATE_RESET_STATS();
168 if (flags_ & PERFORMANCE) {
169 long start = GetTimeInMs();
171 long end = GetTimeInMs();
172 printf ("Time: %4ldms\n", end-start);
175 if (flags_ & PRINT_STATS)
176 ANNOTATE_PRINT_STATS();
177 if (flags_ & MEMORY_USAGE)
178 ANNOTATE_PRINT_MEMORY_USAGE(0);
181 std::map<int, Test> TheMapOfTests;
183 #define NOINLINE __attribute__ ((noinline))
184 extern "C" void NOINLINE AnnotateSetVerbosity(const char *, int, int) {};
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);
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);
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; };
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); \
214 #define ANNOTATE_EXPECT_RACE_FOR_TSAN(mem, descr) \
215 ANNOTATE_EXPECT_RACE_FOR_MACHINE(mem, descr, "MSM_THREAD_SANITIZER")
217 inline bool Tsan_PureHappensBefore() {
221 inline bool Tsan_FastMode() {
222 return getenv("TSAN_FAST_MODE") != NULL;
225 // Initialize *(mem) to 0 if Tsan_FastMode.
226 #define FAST_MODE_INIT(mem) do { if (Tsan_FastMode()) { *(mem) = 0; } } while(0)
228 #ifndef MAIN_INIT_ACTION
229 #define MAIN_INIT_ACTION
234 int main(int argc, char** argv) { // {{{1
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;
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;
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();
257 bool run_tests_with_annotations = false;
258 if (getenv("DRT_ALLOW_ANNOTATIONS")) {
259 run_tests_with_annotations = true;
261 for (std::map<int,Test>::iterator it = TheMapOfTests.begin();
262 it != TheMapOfTests.end();
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;
273 #ifdef THREAD_WRAPPERS_PTHREAD_H
277 // An array of threads. Create/start/join all elements at once. {{{1
278 class MyThreadArray {
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;
290 for(int i = 0; i < kSize; i++) {
299 for(int i = 0; i < kSize; i++) {
307 for(int i = 0; i < kSize; i++) {
312 MyThread *ar_[kSize];
321 printf("test00: negative\n");
322 printf("\tGLOB=%d\n", GLOB);
324 REGISTER_TEST(Run, 00)
325 } // namespace test00
328 // test01: TP. Simple race (write vs write). {{{1
342 FAST_MODE_INIT(&GLOB);
343 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test01. TP.");
344 ANNOTATE_TRACE_MEMORY(&GLOB);
345 printf("test01: positive\n");
347 const int tmp = GLOB;
348 printf("\tGLOB=%d\n", tmp);
350 REGISTER_TEST(Run, 1);
351 } // namespace test01
354 // test02: TN. Synchronization via CondVar. {{{1
357 // Two write accesses to GLOB are synchronized because
358 // the pair of CV.Signal() and CV.Wait() establish happens-before relation.
363 // 3. MU.Lock() a. write(GLOB)
366 // /--- d. CV.Signal()
367 // 4. while(COND) / e. MU.Unlock()
374 usleep(100000); // Make sure the waiter blocks.
387 pool.Add(NewCallback(Waker));
395 printf("test02: negative\n");
397 printf("\tGLOB=%d\n", GLOB);
399 REGISTER_TEST(Run, 2);
400 } // namespace test02
403 // test03: TN. Synchronization via LockWhen, signaller gets there first. {{{1
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)!
415 // /--- d. MU.Unlock()
416 // 3. MU.LockWhen(COND==1) <---/
422 usleep(100000); // Make sure the waiter blocks.
426 COND = 1; // We are done! Tell the Waiter.
427 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
433 pool.Add(NewCallback(Waker));
434 MU.LockWhen(Condition(&ArgIsOne, &COND)); // calls ANNOTATE_CONDVAR_WAIT
435 MU.Unlock(); // Waker is done!
440 printf("test03: negative\n");
442 printf("\tGLOB=%d\n", GLOB);
444 REGISTER_TEST2(Run, 3, FEATURE|NEEDS_ANNOTATIONS);
445 } // namespace test03
447 // test04: TN. Synchronization via PCQ. {{{1
450 ProducerConsumerQueue Q(INT_MAX);
451 // Two write accesses to GLOB are separated by PCQ Put/Get.
455 // 2. Q.Put() ---------\ .
456 // \-------> a. Q.Get()
471 printf("test04: negative\n");
472 MyThreadArray t(Putter, Getter);
475 printf("\tGLOB=%d\n", GLOB);
477 REGISTER_TEST(Run, 4);
478 } // namespace test04
481 // test05: FP. Synchronization via CondVar, but waiter does not block. {{{1
482 // Since CondVar::Wait() is not called, we get a false positive.
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.
493 // 3. MU.Lock() a. write(GLOB)
497 // 4. while(COND) e. MU.Unlock()
498 // CV.Wait(MU) <<< not called
515 pool.Add(NewCallback(Waker));
516 usleep(100000); // Make sure the signaller gets first.
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");
529 printf("\tGLOB=%d\n", GLOB);
531 REGISTER_TEST(Run, 5);
532 } // namespace test05
535 // test06: TN. Synchronization via CondVar, but Waker gets there first. {{{1
538 // Same as test05 but we annotated the Wait() loop.
543 // 3. MU.Lock() a. write(GLOB)
546 // /------- d. CV.Signal()
547 // 4. while(COND) / e. MU.Unlock()
548 // CV.Wait(MU) <<< not called /
549 // 6. ANNOTATE_CONDVAR_WAIT(CV, MU) <----/
567 pool.Add(NewCallback(Waker));
568 usleep(100000); // Make sure the signaller gets first.
572 ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
578 printf("test06: negative\n");
580 printf("\tGLOB=%d\n", GLOB);
582 REGISTER_TEST2(Run, 6, FEATURE|NEEDS_ANNOTATIONS);
583 } // namespace test06
586 // test07: TN. Synchronization via LockWhen(), Signaller is observed first. {{{1
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().
594 // Waiter: Signaller:
596 // 2. Start(Signaller)
600 // /--- d. MU.Unlock calls ANNOTATE_CONDVAR_SIGNAL
601 // 3. MU.LockWhen(COND==1) <---/
609 COND = true; // We are done! Tell the Waiter.
610 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
614 MyThread t(Signaller);
616 usleep(100000); // Make sure the signaller gets there first.
618 MU.LockWhen(Condition(&ArgIsTrue, &COND)); // calls ANNOTATE_CONDVAR_WAIT
619 MU.Unlock(); // Signaller is done!
621 GLOB = 2; // If LockWhen didn't catch the signal, a race may be reported here.
625 printf("test07: negative\n");
627 printf("\tGLOB=%d\n", GLOB);
629 REGISTER_TEST2(Run, 7, FEATURE|NEEDS_ANNOTATIONS);
630 } // namespace test07
632 // test08: TN. Synchronization via thread start/join. {{{1
635 // Three accesses to GLOB are separated by thread start/join.
639 // 2. Start(Worker) ------------>
641 // 3. Join(Worker) <------------
655 printf("test08: negative\n");
657 printf("\tGLOB=%d\n", GLOB);
659 REGISTER_TEST(Run, 8);
660 } // namespace test08
663 // test09: TP. Simple race (read vs write). {{{1
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.
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);
685 printf("\tGLOB=%d\n", GLOB);
687 REGISTER_TEST(Run, 9);
688 } // namespace test09
691 // test10: FN. Simple race (write vs read). {{{1
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.
699 // 1. write(GLOB) a. sleep(long enough so that GLOB
700 // is most likely initialized by Writer)
704 // Eraser algorithm does not detect the race here,
705 // see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html.
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);
722 printf("\tGLOB=%d\n", GLOB);
724 REGISTER_TEST(Run, 10);
725 } // namespace test10
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.
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()
756 MyThreadArray t(Worker, Worker);
771 // ANNOTATE_EXPECT_RACE(&GLOB, "test11. FP. Fixed by MSMProp1.");
772 printf("test11: negative\n");
774 printf("\tGLOB=%d\n", GLOB);
776 REGISTER_TEST(Run, 11);
777 } // namespace test11
780 // test12: FP. Synchronization via Mutex, then via PCQ. {{{1
783 // This test is properly synchronized, but currently (Dec 2007)
784 // helgrind reports a false positive.
786 // First, we write to GLOB under MU, then we synchronize via PCQ,
787 // which is essentially a semaphore.
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()
796 ProducerConsumerQueue Q(INT_MAX);
817 // ANNOTATE_EXPECT_RACE(&GLOB, "test12. FP. Fixed by MSMProp1.");
818 printf("test12: negative\n");
819 MyThreadArray t(Putter, Getter);
822 printf("\tGLOB=%d\n", GLOB);
824 REGISTER_TEST(Run, 12);
825 } // namespace test12
828 // test13: FP. Synchronization via Mutex, then via LockWhen. {{{1
831 // This test is essentially the same as test12, but uses LockWhen
835 // 1. MU.Lock() a. MU.Lock()
836 // 2. write(GLOB) <---------- MU ----------> b. write(GLOB)
837 // 3. MU.Unlock() c. MU.Unlock()
840 // 6. ANNOTATE_CONDVAR_SIGNAL -------\ .
841 // 7. MU.Unlock() \ .
842 // \----> d. MU.LockWhen(COND == 1)
854 ANNOTATE_CONDVAR_SIGNAL(&MU);
863 MU.LockWhen(Condition(&ArgIsOne, &COND));
869 // ANNOTATE_EXPECT_RACE(&GLOB, "test13. FP. Fixed by MSMProp1.");
870 printf("test13: negative\n");
873 MyThreadArray t(Waker, Waiter);
877 printf("\tGLOB=%d\n", GLOB);
879 REGISTER_TEST2(Run, 13, FEATURE|NEEDS_ANNOTATIONS);
880 } // namespace test13
883 // test14: FP. Synchronization via PCQ, reads, 2 workers. {{{1
886 // This test is properly synchronized, but currently (Dec 2007)
887 // helgrind reports a false positive.
889 // This test is similar to test11, but uses PCQ (semaphore).
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()
897 ProducerConsumerQueue Q1(INT_MAX), Q2(INT_MAX);
913 // ANNOTATE_EXPECT_RACE(&GLOB, "test14. FP. Fixed by MSMProp1.");
914 printf("test14: negative\n");
915 MyThreadArray t(Getter, Putter1, Putter2);
918 printf("\tGLOB=%d\n", GLOB);
920 REGISTER_TEST(Run, 14);
921 } // namespace test14
924 // test15: TN. Synchronization via LockWhen. One waker and 2 waiters. {{{1
926 // Waker: Waiter1, Waiter2:
930 // 4. ANNOTATE_CONDVAR_SIGNAL ------------> a. MU.LockWhen(COND == 1)
931 // 5. MU.Unlock() b. MU.Unlock()
942 ANNOTATE_CONDVAR_SIGNAL(&MU);
947 MU.LockWhen(Condition(&ArgIsOne, &COND));
955 printf("test15: negative\n");
956 MyThreadArray t(Waker, Waiter, Waiter);
959 printf("\tGLOB=%d\n", GLOB);
961 REGISTER_TEST(Run, 15);
962 } // namespace test15
965 // test16: FP. Barrier (emulated by CV), 2 threads. {{{1
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()
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.
997 ANNOTATE_CONDVAR_SIGNAL(&MU2);
998 MU2.Await(Condition(&ArgIsZero, &COND));
1005 // ANNOTATE_EXPECT_RACE(&GLOB, "test16. FP. Fixed by MSMProp1 + Barrier support.");
1007 printf("test16: negative\n");
1008 MyThreadArray t(Worker, Worker);
1011 printf("\tGLOB=%d\n", GLOB);
1013 REGISTER_TEST2(Run, 16, FEATURE|NEEDS_ANNOTATIONS);
1014 } // namespace test16
1017 // test17: FP. Barrier (emulated by CV), 3 threads. {{{1
1019 // Same as test16, but with 3 threads.
1031 ANNOTATE_CONDVAR_SIGNAL(&MU2);
1032 MU2.Await(Condition(&ArgIsZero, &COND));
1039 // ANNOTATE_EXPECT_RACE(&GLOB, "test17. FP. Fixed by MSMProp1 + Barrier support.");
1041 printf("test17: negative\n");
1042 MyThreadArray t(Worker, Worker, Worker);
1045 printf("\tGLOB=%d\n", GLOB);
1047 REGISTER_TEST2(Run, 17, FEATURE|NEEDS_ANNOTATIONS);
1048 } // namespace test17
1051 // test18: TN. Synchronization via Await(), signaller gets there first. {{{1
1055 // Same as test03, but uses Mutex::Await() instead of Mutex::LockWhen().
1058 usleep(100000); // Make sure the waiter blocks.
1062 COND = 1; // We are done! Tell the Waiter.
1063 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
1067 pool.StartWorkers();
1069 pool.Add(NewCallback(Waker));
1072 MU.Await(Condition(&ArgIsOne, &COND)); // calls ANNOTATE_CONDVAR_WAIT
1073 MU.Unlock(); // Waker is done!
1078 printf("test18: negative\n");
1080 printf("\tGLOB=%d\n", GLOB);
1082 REGISTER_TEST2(Run, 18, FEATURE|NEEDS_ANNOTATIONS);
1083 } // namespace test18
1085 // test19: TN. Synchronization via AwaitWithTimeout(). {{{1
1088 // Same as test18, but with AwaitWithTimeout. Do not timeout.
1091 usleep(100000); // Make sure the waiter blocks.
1095 COND = 1; // We are done! Tell the Waiter.
1096 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
1100 pool.StartWorkers();
1102 pool.Add(NewCallback(Waker));
1105 CHECK(MU.AwaitWithTimeout(Condition(&ArgIsOne, &COND), INT_MAX));
1111 printf("test19: negative\n");
1113 printf("\tGLOB=%d\n", GLOB);
1115 REGISTER_TEST2(Run, 19, FEATURE|NEEDS_ANNOTATIONS);
1116 } // namespace test19
1118 // test20: TP. Incorrect synchronization via AwaitWhen(), timeout. {{{1
1122 // True race. We timeout in AwaitWhen.
1129 pool.StartWorkers();
1131 pool.Add(NewCallback(Waker));
1134 CHECK(!MU.AwaitWithTimeout(Condition(&ArgIsOne, &COND), 100));
1140 FAST_MODE_INIT(&GLOB);
1141 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test20. TP.");
1142 printf("test20: positive\n");
1144 printf("\tGLOB=%d\n", GLOB);
1146 REGISTER_TEST2(Run, 20, FEATURE|NEEDS_ANNOTATIONS);
1147 } // namespace test20
1149 // test21: TP. Incorrect synchronization via LockWhenWithTimeout(). {{{1
1152 // True race. We timeout in LockWhenWithTimeout().
1160 pool.StartWorkers();
1162 pool.Add(NewCallback(Waker));
1164 CHECK(!MU.LockWhenWithTimeout(Condition(&ArgIsOne, &COND), 100));
1170 FAST_MODE_INIT(&GLOB);
1171 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test21. TP.");
1172 printf("test21: positive\n");
1174 printf("\tGLOB=%d\n", GLOB);
1176 REGISTER_TEST2(Run, 21, FEATURE|NEEDS_ANNOTATIONS);
1177 } // namespace test21
1179 // test22: TP. Incorrect synchronization via CondVar::WaitWithTimeout(). {{{1
1183 // True race. We timeout in CondVar::WaitWithTimeout().
1190 pool.StartWorkers();
1192 pool.Add(NewCallback(Waker));
1194 int64_t ms_left_to_wait = 100;
1195 int64_t deadline_ms = GetCurrentTimeMillis() + ms_left_to_wait;
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();
1206 FAST_MODE_INIT(&GLOB);
1207 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test22. TP.");
1208 printf("test22: positive\n");
1210 printf("\tGLOB=%d\n", GLOB);
1212 REGISTER_TEST(Run, 22);
1213 } // namespace test22
1215 // test23: TN. TryLock, ReaderLock, ReaderTryLock. {{{1
1217 // Correct synchronization with TryLock, Lock, ReaderTryLock, ReaderLock.
1220 void Worker_TryLock() {
1221 for (int i = 0; i < 20; i++) {
1233 void Worker_ReaderTryLock() {
1234 for (int i = 0; i < 20; i++) {
1236 if (MU.ReaderTryLock()) {
1246 void Worker_ReaderLock() {
1247 for (int i = 0; i < 20; i++) {
1255 void Worker_Lock() {
1256 for (int i = 0; i < 20; i++) {
1265 printf("test23: negative\n");
1266 MyThreadArray t(Worker_TryLock,
1267 Worker_ReaderTryLock,
1273 printf("\tGLOB=%d\n", GLOB);
1275 REGISTER_TEST(Run, 23);
1276 } // namespace test23
1278 // test24: TN. Synchronization via ReaderLockWhen(). {{{1
1282 // Same as test03, but uses ReaderLockWhen().
1285 usleep(100000); // Make sure the waiter blocks.
1289 COND = 1; // We are done! Tell the Waiter.
1290 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
1294 pool.StartWorkers();
1296 pool.Add(NewCallback(Waker));
1297 MU.ReaderLockWhen(Condition(&ArgIsOne, &COND));
1303 printf("test24: negative\n");
1305 printf("\tGLOB=%d\n", GLOB);
1307 REGISTER_TEST2(Run, 24, FEATURE|NEEDS_ANNOTATIONS);
1308 } // namespace test24
1310 // test25: TN. Synchronization via ReaderLockWhenWithTimeout(). {{{1
1314 // Same as test24, but uses ReaderLockWhenWithTimeout().
1315 // We do not timeout.
1318 usleep(100000); // Make sure the waiter blocks.
1322 COND = 1; // We are done! Tell the Waiter.
1323 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
1327 pool.StartWorkers();
1329 pool.Add(NewCallback(Waker));
1330 CHECK(MU.ReaderLockWhenWithTimeout(Condition(&ArgIsOne, &COND), INT_MAX));
1336 printf("test25: negative\n");
1338 printf("\tGLOB=%d\n", GLOB);
1340 REGISTER_TEST2(Run, 25, FEATURE|NEEDS_ANNOTATIONS);
1341 } // namespace test25
1343 // test26: TP. Incorrect synchronization via ReaderLockWhenWithTimeout(). {{{1
1347 // Same as test25, but we timeout and incorrectly assume happens-before.
1355 pool.StartWorkers();
1357 pool.Add(NewCallback(Waker));
1358 CHECK(!MU.ReaderLockWhenWithTimeout(Condition(&ArgIsOne, &COND), 100));
1364 FAST_MODE_INIT(&GLOB);
1365 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test26. TP");
1366 printf("test26: positive\n");
1368 printf("\tGLOB=%d\n", GLOB);
1370 REGISTER_TEST2(Run, 26, FEATURE|NEEDS_ANNOTATIONS);
1371 } // namespace test26
1374 // test27: TN. Simple synchronization via SpinLock. {{{1
1387 printf("test27: negative\n");
1388 MyThreadArray t(Worker, Worker, Worker, Worker);
1391 printf("\tGLOB=%d\n", GLOB);
1393 REGISTER_TEST2(Run, 27, FEATURE|NEEDS_ANNOTATIONS);
1394 #endif // NO_SPINLOCK
1395 } // namespace test27
1398 // test28: TN. Synchronization via Mutex, then PCQ. 3 threads {{{1
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()
1409 ProducerConsumerQueue Q(INT_MAX);
1433 printf("test28: negative\n");
1434 MyThreadArray t(Getter, Putter, Putter);
1437 printf("\tGLOB=%d\n", GLOB);
1439 REGISTER_TEST(Run, 28);
1440 } // namespace test28
1443 // test29: TN. Synchronization via Mutex, then PCQ. 4 threads. {{{1
1445 // Similar to test28, but has two Getters and two PCQs.
1446 ProducerConsumerQueue *Q1, *Q2;
1450 void Putter(ProducerConsumerQueue *q) {
1464 void Putter1() { Putter(Q1); }
1465 void Putter2() { Putter(Q2); }
1472 usleep(48000); // TODO: remove this when FP in test32 is fixed.
1476 printf("test29: negative\n");
1477 Q1 = new ProducerConsumerQueue(INT_MAX);
1478 Q2 = new ProducerConsumerQueue(INT_MAX);
1479 MyThreadArray t(Getter, Getter, Putter1, Putter2);
1482 printf("\tGLOB=%d\n", GLOB);
1486 REGISTER_TEST(Run, 29);
1487 } // namespace test29
1490 // test30: TN. Synchronization via 'safe' race. Writer vs multiple Readers. {{{1
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.
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)
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.
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...
1514 volatile int BOUNDARY = 0;
1517 for (int i = 0; i < N; i++) {
1518 CHECK(BOUNDARY == i);
1519 for (int j = i; j < N; j++) {
1522 ANNOTATE_HAPPENS_BEFORE(reinterpret_cast<void*>(BOUNDARY+1));
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);
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);
1548 printf("\tGLOB=%d\n", GLOB[N-1]);
1550 REGISTER_TEST2(Run, 30, FEATURE|NEEDS_ANNOTATIONS);
1551 } // namespace test30
1554 // test31: TN. Synchronization via 'safe' race. Writer vs Writer. {{{1
1556 // This test is similar to test30, but
1557 // it has one Writer instead of mulitple Readers.
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)
1567 volatile int BOUNDARY = 0;
1570 for (int i = 0; i < N; i++) {
1571 CHECK(BOUNDARY == i);
1572 for (int j = i; j < N; j++) {
1575 ANNOTATE_HAPPENS_BEFORE(reinterpret_cast<void*>(BOUNDARY+1));
1585 if (n == 0) continue;
1586 ANNOTATE_HAPPENS_AFTER(reinterpret_cast<void*>(n));
1587 for (int i = 0; i < n; i++) {
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);
1603 printf("\tGLOB=%d\n", GLOB[N-1]);
1605 REGISTER_TEST2(Run, 31, FEATURE|NEEDS_ANNOTATIONS);
1606 } // namespace test31
1609 // test32: FP. Synchronization via thread create/join. W/R. {{{1
1611 // This test is well synchronized but helgrind 3.3.0 reports a race.
1613 // Parent: Writer: Reader:
1614 // 1. Start(Reader) -----------------------\ .
1616 // 2. Start(Writer) ---\ \ .
1617 // \---> a. MU.Lock() \--> A. sleep(long enough)
1619 // /---- c. MU.Unlock()
1620 // 3. Join(Writer) <---/
1623 // /------------ D. MU.Unlock()
1624 // 4. Join(Reader) <----------------/
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.
1653 w.Join(); // 'w' joins first.
1660 // ANNOTATE_EXPECT_RACE(&GLOB, "test32. FP. Fixed by MSMProp1.");
1661 printf("test32: negative\n");
1663 printf("\tGLOB=%d\n", GLOB);
1666 REGISTER_TEST(Run, 32);
1667 } // namespace test32
1670 // test33: STAB. Stress test for the number of thread sets (TSETs). {{{1
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;
1688 for (int i = 0; i < N; i++) {
1689 // ARR[i] is accessed by threads from i-th subset
1697 printf("test33:\n");
1699 std::vector<MyThread*> vec(Nlog);
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);
1706 for (int i = 0; i < Nlog; i++) {
1709 // Join all threads.
1710 for (int i = 0; i < Nlog; i++) {
1714 printf("------------------\n");
1717 printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n",
1718 GLOB, ARR[1], ARR[7], ARR[N-1]);
1720 REGISTER_TEST2(Run, 33, STABILITY|EXCLUDE_FROM_ALL);
1721 } // namespace test33
1724 // test34: STAB. Stress test for the number of locks sets (LSETs). {{{1
1726 // Similar to test33, but for lock sets.
1728 const int N_iter = 48;
1729 const int Nlog = 10;
1730 const int N = 1 << Nlog;
1732 static Mutex *MUs[Nlog];
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();
1739 for (int j = 0; j < Nlog; j++) if (i & (1 << j)) MUs[j]->Unlock();
1744 printf("test34:\n");
1745 for (int iter = 0; iter < N_iter; iter++) {
1746 for (int i = 0; i < Nlog; i++) {
1749 MyThreadArray t(Worker, Worker);
1752 for (int i = 0; i < Nlog; i++) {
1755 printf("------------------\n");
1757 printf("\tGLOB=%d\n", GLOB);
1759 REGISTER_TEST2(Run, 34, STABILITY|EXCLUDE_FROM_ALL);
1760 } // namespace test34
1763 // test35: PERF. Lots of mutexes and lots of call to free(). {{{1
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).
1769 // TODO: need to figure out the best way for performance testing.
1771 const int N_mu = 25000;
1772 const int N_free = 48000;
1775 for (int i = 0; i < N_free; i++)
1776 CHECK(777 == *ARR[i]);
1780 printf("test35:\n");
1781 std::vector<Mutex*> mus;
1783 ARR = new int *[N_free];
1784 for (int i = 0; i < N_free; i++) {
1785 const int c = N_free / N_mu;
1787 mus.push_back(new Mutex);
1789 mus.back()->Unlock();
1791 ARR[i] = new int(777);
1794 // Need to put all ARR[i] into shared state in order
1795 // to trigger the performance bug.
1796 MyThreadArray t(Worker, Worker);
1800 for (int i = 0; i < N_free; i++) delete ARR[i];
1803 for (size_t i = 0; i < mus.size(); i++) {
1807 REGISTER_TEST2(Run, 35, PERFORMANCE|EXCLUDE_FROM_ALL);
1808 } // namespace test35
1811 // test36: TN. Synchronization via Mutex, then PCQ. 3 threads. W/W {{{1
1813 // variation of test28 (W/W instead of W/R)
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()
1828 ProducerConsumerQueue Q(INT_MAX);
1856 printf("test36: negative \n");
1857 MyThreadArray t(Getter, Putter, Putter);
1860 printf("\tGLOB=%d\n", GLOB);
1862 REGISTER_TEST(Run, 36);
1863 } // namespace test36
1866 // test37: TN. Simple synchronization (write vs read). {{{1
1870 // Similar to test10, but properly locked.
1887 CHECK(GLOB != -777);
1892 printf("test37: negative\n");
1893 MyThreadArray t(Writer, Reader);
1896 printf("\tGLOB=%d\n", GLOB);
1898 REGISTER_TEST(Run, 37);
1899 } // namespace test37
1902 // test38: TN. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1
1904 // Fusion of test29 and test36.
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()
1925 ProducerConsumerQueue *Q1, *Q2;
1929 void Putter(ProducerConsumerQueue *q) {
1945 void Putter1() { Putter(Q1); }
1946 void Putter2() { Putter(Q2); }
1957 usleep(48000); // TODO: remove this when FP in test32 is fixed.
1961 printf("test38: negative\n");
1962 Q1 = new ProducerConsumerQueue(INT_MAX);
1963 Q2 = new ProducerConsumerQueue(INT_MAX);
1964 MyThreadArray t(Getter, Getter, Putter1, Putter2);
1967 printf("\tGLOB=%d\n", GLOB);
1971 REGISTER_TEST(Run, 38);
1972 } // namespace test38
1974 // test39: FP. Barrier. {{{1
1977 // Same as test17 but uses Barrier class (pthread_barrier_t).
1979 const int N_threads = 3;
1980 Barrier barrier(N_threads);
1988 CHECK(GLOB == N_threads);
1991 ANNOTATE_TRACE_MEMORY(&GLOB);
1992 // ANNOTATE_EXPECT_RACE(&GLOB, "test39. FP. Fixed by MSMProp1. Barrier.");
1993 printf("test39: negative\n");
1995 ThreadPool pool(N_threads);
1996 pool.StartWorkers();
1997 for (int i = 0; i < N_threads; i++) {
1998 pool.Add(NewCallback(Worker));
2000 } // all folks are joined here.
2001 printf("\tGLOB=%d\n", GLOB);
2003 REGISTER_TEST(Run, 39);
2004 #endif // NO_BARRIER
2005 } // namespace test39
2008 // test40: FP. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1
2010 // Similar to test38 but with different order of events (due to sleep).
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()
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()
2031 ProducerConsumerQueue *Q1, *Q2;
2035 void Putter(ProducerConsumerQueue *q) {
2052 void Putter1() { Putter(Q1); }
2053 void Putter2() { Putter(Q2); }
2063 usleep(48000); // TODO: remove this when FP in test32 is fixed.
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);
2074 printf("\tGLOB=%d\n", GLOB);
2078 REGISTER_TEST(Run, 40);
2079 } // namespace test40
2081 // test41: TN. Test for race that appears when loading a dynamic symbol. {{{1
2084 ANNOTATE_NO_OP(NULL); // An empty function, loaded from dll.
2087 printf("test41: negative\n");
2088 MyThreadArray t(Worker, Worker, Worker);
2092 REGISTER_TEST2(Run, 41, FEATURE|NEEDS_ANNOTATIONS);
2093 } // namespace test41
2096 // test42: TN. Using the same cond var several times. {{{1
2114 ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2126 ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2139 // ANNOTATE_EXPECT_RACE(&GLOB, "test42. TN. debugging.");
2140 printf("test42: negative\n");
2141 MyThreadArray t(Worker1, Worker2);
2144 printf("\tGLOB=%d\n", GLOB);
2146 REGISTER_TEST2(Run, 42, FEATURE|NEEDS_ANNOTATIONS);
2147 } // namespace test42
2157 // 3. read \--> a. Q.Get()
2160 ProducerConsumerQueue Q(INT_MAX);
2172 printf("test43: negative\n");
2173 MyThreadArray t(Putter, Getter);
2176 printf("\tGLOB=%d\n", GLOB);
2178 REGISTER_TEST(Run, 43)
2179 } // namespace test43
2188 // 3. MU.Lock() \--> a. Q.Get()
2196 ProducerConsumerQueue Q(INT_MAX);
2212 // ANNOTATE_EXPECT_RACE(&GLOB, "test44. FP. Fixed by MSMProp1.");
2213 printf("test44: negative\n");
2214 MyThreadArray t(Putter, Getter);
2217 printf("\tGLOB=%d\n", GLOB);
2219 REGISTER_TEST(Run, 44)
2220 } // namespace test44
2229 // 3. MU.Lock() \--> a. Q.Get()
2237 ProducerConsumerQueue Q(INT_MAX);
2253 printf("test45: negative\n");
2254 MyThreadArray t(Putter, Getter);
2257 printf("\tGLOB=%d\n", GLOB);
2259 REGISTER_TEST(Run, 45)
2260 } // namespace test45
2270 // 4. MU.Unlock() (sleep)
2289 // If we move it to Run() we will get report in MSMHelgrind
2290 // due to its false positive (test32).
2292 printf("\tGLOB=%d\n", GLOB);
2296 ANNOTATE_TRACE_MEMORY(&GLOB);
2297 MyThreadArray t(First, Second);
2301 REGISTER_TEST(Run, 46)
2302 } // namespace test46
2305 // test47: TP. Not detected by pure happens-before detectors. {{{1
2307 // A true race that can not be detected by a pure happens-before
2313 // 3. MU.Unlock() (sleep)
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);
2338 printf("\tGLOB=%d\n", GLOB);
2340 REGISTER_TEST(Run, 47)
2341 } // namespace test47
2344 // test48: FN. Simple race (single write vs multiple reads). {{{1
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)),
2353 // 1. write(GLOB) a. sleep(long enough so that GLOB
2354 // is most likely initialized by Writer)
2358 // Eraser algorithm does not detect the race here,
2359 // see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html.
2366 CHECK(GLOB != -777);
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);
2376 printf("\tGLOB=%d\n", GLOB);
2378 REGISTER_TEST(Run, 48)
2379 } // namespace test48
2382 // test49: FN. Simple race (single write vs multiple reads). {{{1
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)),
2390 // 1. write(GLOB) a. sleep(long enough so that GLOB
2391 // is most likely initialized by Writer)
2398 // Eraser algorithm does not detect the race here,
2399 // see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html.
2406 CHECK(GLOB != -777);
2407 CHECK(GLOB != -777);
2408 CHECK(GLOB != -777);
2409 CHECK(GLOB != -777);
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);
2419 printf("\tGLOB=%d\n", GLOB);
2421 REGISTER_TEST(Run, 49);
2422 } // namespace test49
2425 // test50: TP. Synchronization via CondVar. {{{1
2429 // Two last write accesses to GLOB are not synchronized
2434 // 3. MU.Lock() a. write(GLOB)
2437 // /--- d. CV.Signal()
2438 // 4. while(COND != 1) / e. MU.Unlock()
2439 // CV.Wait(MU) <---/
2441 // 6. write(GLOB) f. MU.Lock()
2447 usleep(100000); // Make sure the waiter blocks.
2464 pool.StartWorkers();
2466 pool.Add(NewCallback(Waker));
2471 ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2477 FAST_MODE_INIT(&GLOB);
2478 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test50. TP.");
2479 printf("test50: positive\n");
2481 printf("\tGLOB=%d\n", GLOB);
2483 REGISTER_TEST2(Run, 50, FEATURE|NEEDS_ANNOTATIONS);
2484 } // namespace test50
2487 // test51: TP. Synchronization via CondVar: problem with several signals. {{{1
2494 // scheduler dependent results because of several signals
2495 // second signal will be lost
2502 // 4. MU.Unlock() \ .
2503 // 5. write(GLOB) \ a. write(GLOB)
2506 // \--- d. CV.Signal()
2513 // LOST<---- i. CV.Signal()
2518 usleep(10000); // Make sure the waiter blocks.
2527 usleep(10000); // Make sure the waiter is signalled.
2533 CV.Signal(); //Lost Signal
2540 pool.StartWorkers();
2541 pool.Add(NewCallback(Waker));
2552 FAST_MODE_INIT(&GLOB);
2553 ANNOTATE_EXPECT_RACE(&GLOB, "test51. TP.");
2554 printf("test51: positive\n");
2556 printf("\tGLOB=%d\n", GLOB);
2558 REGISTER_TEST(Run, 51);
2559 } // namespace test51
2562 // test52: TP. Synchronization via CondVar: problem with several signals. {{{1
2568 // same as test51 but the first signal will be lost
2569 // scheduler dependent results because of several signals
2576 // LOST<---- d. CV.Signal()
2582 // 4. MU.Unlock() \ f. write(GLOB)
2583 // 5. write(GLOB) \ .
2586 // \--- i. CV.Signal()
2595 CV.Signal(); //lost signal
2598 usleep(20000); // Make sure the waiter blocks
2610 pool.StartWorkers();
2611 pool.Add(NewCallback(Waker));
2613 usleep(10000); // Make sure the first signal will be lost
2623 FAST_MODE_INIT(&GLOB);
2624 ANNOTATE_EXPECT_RACE(&GLOB, "test52. TP.");
2625 printf("test52: positive\n");
2627 printf("\tGLOB=%d\n", GLOB);
2629 REGISTER_TEST(Run, 52);
2630 } // namespace test52
2633 // test53: FP. Synchronization via implicit semaphore. {{{1
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.
2642 // Initializer: Users
2650 // d. if (!f) goto a.
2660 void Initializer() {
2665 usleep(100000); // just in case
2676 // at this point Initializer will not access GLOB again
2678 CHECK(GLOB >= 1000);
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);
2691 printf("\tGLOB=%d\n", GLOB);
2693 REGISTER_TEST(Run, 53)
2694 } // namespace test53
2697 // test54: TN. Synchronization via implicit semaphore. Annotated {{{1
2699 // Same as test53, but annotated.
2704 void Initializer() {
2708 ANNOTATE_CONDVAR_SIGNAL(&GLOB);
2710 usleep(100000); // just in case
2721 // at this point Initializer will not access GLOB again
2722 ANNOTATE_CONDVAR_WAIT(&GLOB);
2724 CHECK(GLOB >= 1000);
2730 printf("test54: negative\n");
2731 MyThreadArray t(Initializer, User, User);
2734 printf("\tGLOB=%d\n", GLOB);
2736 REGISTER_TEST2(Run, 54, FEATURE|NEEDS_ANNOTATIONS)
2737 } // namespace test54
2740 // test55: FP. Synchronization with TryLock. Not easy for race detectors {{{1
2742 // "Correct" synchronization with TryLock and Lock.
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).
2750 void Worker_Lock() {
2755 void Worker_TryLock() {
2757 if (!MU.TryLock()) {
2769 printf("test55:\n");
2770 MyThreadArray t(Worker_Lock, Worker_TryLock);
2773 printf("\tGLOB=%d\n", GLOB);
2775 REGISTER_TEST2(Run, 55, FEATURE|EXCLUDE_FROM_ALL);
2776 } // namespace test55
2780 // test56: TP. Use of ANNOTATE_BENIGN_RACE. {{{1
2782 // For whatever reason the user wants to treat
2783 // a race on GLOB as a benign race.
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);
2798 printf("\tGLOB=%d\n", GLOB);
2800 REGISTER_TEST2(Run, 56, FEATURE|NEEDS_ANNOTATIONS)
2801 } // namespace test56
2804 // test57: TN: Correct use of atomics. {{{1
2808 for (int i = 0; i < 10; i++) {
2809 AtomicIncrement(&GLOB, 1);
2814 while (GLOB < 20) usleep(1000);
2817 printf("test57: negative\n");
2818 MyThreadArray t(Writer, Writer, Reader, Reader);
2822 printf("\tGLOB=%d\n", GLOB);
2824 REGISTER_TEST(Run, 57)
2825 } // namespace test57
2828 // test58: TN. User defined synchronization. {{{1
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??).
2857 printf("test58:\n");
2858 MyThreadArray t(Worker1, Worker2);
2861 printf("\tGLOB1=%d\n", GLOB1);
2862 printf("\tGLOB2=%d\n", GLOB2);
2864 REGISTER_TEST2(Run, 58, FEATURE|EXCLUDE_FROM_ALL)
2865 } // namespace test58
2869 // test59: TN. User defined synchronization. Annotated {{{1
2877 // same as test 58 but annotated
2881 ANNOTATE_CONDVAR_SIGNAL(&COND2);
2882 while(!FLAG2) usleep(1);
2883 ANNOTATE_CONDVAR_WAIT(&COND1);
2889 ANNOTATE_CONDVAR_SIGNAL(&COND1);
2890 while(!FLAG1) usleep(1);
2891 ANNOTATE_CONDVAR_WAIT(&COND2);
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);
2902 printf("\tGLOB1=%d\n", GLOB1);
2903 printf("\tGLOB2=%d\n", GLOB2);
2905 REGISTER_TEST2(Run, 59, FEATURE|NEEDS_ANNOTATIONS)
2906 } // namespace test59
2909 // test60: TN. Correct synchronization using signal-wait {{{1
2918 // same as test 59 but synchronized with signal-wait.
2931 ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2948 ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2955 printf("test60: negative\n");
2956 MyThreadArray t(Worker1, Worker2);
2959 printf("\tGLOB1=%d\n", GLOB1);
2960 printf("\tGLOB2=%d\n", GLOB2);
2962 REGISTER_TEST2(Run, 60, FEATURE|NEEDS_ANNOTATIONS)
2963 } // namespace test60
2966 // test61: TN. Synchronization via Mutex as in happens-before, annotated. {{{1
2970 int *P1 = NULL, *P2 = NULL;
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.
2977 ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
3002 printf("test61: negative\n");
3003 MyThreadArray t(Putter, Getter);
3006 printf("\tGLOB=%d\n", GLOB);
3008 REGISTER_TEST2(Run, 61, FEATURE|NEEDS_ANNOTATIONS)
3009 } // namespace test61
3012 // test62: STAB. Create as many segments as possible. {{{1
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;
3020 for (int i = 0; i < N; i++){
3021 if ((i % (N / 8)) == 0) {
3022 printf("i=%d\n", i);
3029 for (int i = 0; i < N; i++)
3034 printf("test62:\n");
3035 MyThreadArray t(Putter, Getter);
3039 REGISTER_TEST2(Run, 62, STABILITY|EXCLUDE_FROM_ALL)
3040 } // namespace test62
3043 // test63: STAB. Create as many segments as possible and do it fast. {{{1
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;
3051 for (int i = 0; i < N; i++){
3052 if ((i % (N / 8)) == 0) {
3053 printf("i=%d\n", i);
3055 ANNOTATE_CONDVAR_SIGNAL(&C);
3063 printf("test63:\n");
3064 MyThreadArray t(Putter, Getter);
3068 REGISTER_TEST2(Run, 63, STABILITY|EXCLUDE_FROM_ALL)
3069 } // namespace test63
3072 // test64: TP. T2 happens-before T3, but T1 is independent. Reads in T1/T2. {{{1
3074 // True race between T1 and T3:
3077 // 1. read(GLOB) (sleep)
3079 // b. Q.Put() -----> A. Q.Get()
3085 ProducerConsumerQueue Q(INT_MAX);
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);
3110 printf("\tGLOB=%d\n", GLOB);
3112 REGISTER_TEST(Run, 64)
3113 } // namespace test64
3116 // test65: TP. T2 happens-before T3, but T1 is independent. Writes in T1/T2. {{{1
3118 // Similar to test64.
3119 // True race between T1 and T3:
3124 // 3. MU.Unlock() (sleep)
3128 // d. Q.Put() -----> A. Q.Get()
3135 ProducerConsumerQueue Q(INT_MAX);
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);
3165 printf("\tGLOB=%d\n", GLOB);
3167 REGISTER_TEST(Run, 65)
3168 } // namespace test65
3171 // test66: TN. Two separate pairs of signaller/waiter using the same CV. {{{1
3198 while (C1 != 1) CV.Wait(&MU);
3199 ANNOTATE_CONDVAR_WAIT(&CV);
3206 while (C2 != 1) CV.Wait(&MU);
3207 ANNOTATE_CONDVAR_WAIT(&CV);
3213 printf("test66: negative\n");
3214 MyThreadArray t(Signaller1, Signaller2, Waiter1, Waiter2);
3217 printf("\tGLOB=%d/%d\n", GLOB1, GLOB2);
3219 REGISTER_TEST2(Run, 66, FEATURE|NEEDS_ANNOTATIONS)
3220 } // namespace test66
3223 // test67: FN. Race between Signaller1 and Waiter2 {{{1
3225 // Similar to test66, but there is a real race here.
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.
3253 while (C1 != 1) CV.Wait(&MU);
3254 ANNOTATE_CONDVAR_WAIT(&CV);
3260 while (C2 != 1) CV.Wait(&MU);
3261 ANNOTATE_CONDVAR_WAIT(&CV);
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);
3273 printf("\tGLOB=%d\n", GLOB);
3275 REGISTER_TEST2(Run, 67, FEATURE|NEEDS_ANNOTATIONS|EXCLUDE_FROM_ALL)
3276 } // namespace test67
3279 // test68: TP. Writes are protected by MU, reads are not. {{{1
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.
3288 const int N_writers = 3;
3292 for (int i = 0; i < 100; i++) {
3311 if (COND == N_writers)
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);
3325 printf("\tGLOB=%d\n", GLOB);
3327 REGISTER_TEST(Run, 68)
3328 } // namespace test68
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.
3340 const int N_writers = 3;
3345 for (int i = 0; i < 10; i++) {
3360 ANNOTATE_IGNORE_READS_BEGIN();
3362 ANNOTATE_IGNORE_READS_END();
3366 if (COND == N_writers)
3374 printf("test69: negative\n");
3375 MyThreadArray t(Reader, Writer, Writer, Writer);
3378 printf("\tGLOB=%d\n", GLOB);
3380 REGISTER_TEST(Run, 69)
3381 } // namespace test69
3383 // test70: STAB. Check that TRACE_MEMORY works. {{{1
3387 printf("test70: negative\n");
3388 ANNOTATE_TRACE_MEMORY(&GLOB);
3390 printf("\tGLOB=%d\n", GLOB);
3392 REGISTER_TEST(Run, 70)
3393 } // namespace test70
3397 // test71: TN. strlen, index. {{{1
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.
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].
3408 // This can be fixed in Helgrind by intercepting strlen and replacing it
3409 // with a simpler implementation.
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);
3436 printf("test71: negative (strlen & index)\n");
3437 MyThread t1(WorkerY);
3438 MyThread t2(WorkerX);
3443 printf("\tstrX=%s; strY=%s\n", str, str+5);
3445 REGISTER_TEST(Run, 71)
3446 } // namespace test71
3449 // test72: STAB. Stress test for the number of segment sets (SSETs). {{{1
3452 // Variation of test33.
3453 // Instead of creating Nlog*N_iter threads,
3454 // we create Nlog threads and do N_iter barriers.
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];
3474 for (int it = 0; it < N_iter; it++) {
3476 //printf("Iter: %d; %ld %ld\n", it, clock() - t, clock() - t0);
3479 // Iterate N_iter times, block on barrier after each iteration.
3480 // This way Helgrind will create new segments after each barrier.
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
3490 CHECK(ARR1[i] == 0);
3491 CHECK(ARR2[N-1-i] == 0);
3495 barriers[it]->Block();
3501 printf("test72:\n");
3503 std::vector<MyThread*> vec(Nlog);
3505 for (int i = 0; i < N_iter; i++)
3506 barriers[i] = new Barrier(Nlog);
3508 // Create and start Nlog threads
3509 for (int i = 0; i < Nlog; i++) {
3510 vec[i] = new MyThread(Worker);
3514 // Join all threads.
3515 for (int i = 0; i < Nlog; i++) {
3519 for (int i = 0; i < N_iter; i++)
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]);*/
3525 REGISTER_TEST2(Run, 72, STABILITY|PERFORMANCE|EXCLUDE_FROM_ALL);
3526 #endif // NO_BARRIER
3527 } // namespace test72
3530 // test73: STAB. Stress test for the number of (SSETs), different access sizes. {{{1
3533 // Variation of test72.
3534 // We perform accesses of different sizes to the same location.
3536 const int N_iter = 2;
3537 const int Nlog = 16;
3538 const int N = 1 << Nlog;
3539 union uint64_union {
3545 static uint64_union ARR1[N];
3546 union uint32_union {
3551 static uint32_union ARR2[N];
3552 Barrier *barriers[N_iter];
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.
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
3570 for (int off = 0; off < (1 << x); off++) {
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;
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;
3586 barriers[it]->Block();
3593 printf("test73:\n");
3595 std::vector<MyThread*> vec(Nlog);
3597 for (int i = 0; i < N_iter; i++)
3598 barriers[i] = new Barrier(Nlog);
3600 // Create and start Nlog threads
3601 for (int i = 0; i < Nlog; i++) {
3602 vec[i] = new MyThread(Worker);
3606 // Join all threads.
3607 for (int i = 0; i < Nlog; i++) {
3611 for (int i = 0; i < N_iter; i++)
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]);*/
3617 REGISTER_TEST2(Run, 73, STABILITY|PERFORMANCE|EXCLUDE_FROM_ALL);
3618 #endif // NO_BARRIER
3619 } // namespace test73
3622 // test74: PERF. A lot of lock/unlock calls. {{{1
3624 const int N = 100000;
3627 printf("test74: perf\n");
3628 for (int i = 0; i < N; i++ ) {
3633 REGISTER_TEST(Run, 74)
3634 } // namespace test74
3637 // test75: TN. Test for sem_post, sem_wait, sem_trywait. {{{1
3654 sem_trywait(&sem[1]);
3660 sem_init(&sem[0], 0, 0);
3661 sem_init(&sem[1], 0, 0);
3663 printf("test75: negative\n");
3665 MyThreadArray t(Poster, Waiter);
3671 MyThreadArray t(Poster, TryWaiter);
3675 printf("\tGLOB=%d\n", GLOB);
3677 sem_destroy(&sem[0]);
3678 sem_destroy(&sem[1]);
3681 REGISTER_TEST(Run, 75)
3682 } // namespace test75
3684 // RefCountedClass {{{1
3685 struct RefCountedClass {
3688 annotate_unref_ = false;
3693 ~RefCountedClass() {
3694 CHECK(ref_ == 0); // race may be reported here
3695 int data_val = data_; // and here
3696 // if MU is not annotated
3699 printf("\tRefCountedClass::data_ = %d\n", data_val);
3719 bool do_delete = ref_ == 0;
3720 if (annotate_unref_) {
3721 ANNOTATE_CONDVAR_SIGNAL(this);
3725 if (annotate_unref_) {
3726 ANNOTATE_CONDVAR_WAIT(this);
3732 static void Annotate_MU() {
3733 ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
3735 void AnnotateUnref() {
3736 annotate_unref_ = true;
3738 void Annotate_Race() {
3739 ANNOTATE_BENIGN_RACE(&this->data_, "needs annotation");
3740 ANNOTATE_BENIGN_RACE(&this->ref_, "needs annotation");
3743 bool annotate_unref_;
3746 Mutex mu_; // protects data_
3749 static Mutex MU; // protects ref_
3752 Mutex RefCountedClass::MU;
3754 // test76: FP. Ref counting, no annotations. {{{1
3759 RefCountedClass *object = NULL;
3763 object->AccessData();
3767 printf("test76: false positive (ref counting)\n");
3768 object = new RefCountedClass;
3769 object->Annotate_Race();
3770 MyThreadArray t(Worker, Worker, Worker, Worker);
3774 REGISTER_TEST2(Run, 76, FEATURE)
3775 #endif // NO_BARRIER
3776 } // namespace test76
3780 // test77: TN. Ref counting, MU is annotated. {{{1
3783 // same as test76, but RefCountedClass::MU is annotated.
3786 RefCountedClass *object = NULL;
3790 object->AccessData();
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);
3801 REGISTER_TEST(Run, 77)
3802 #endif // NO_BARRIER
3803 } // namespace test77
3807 // test78: TN. Ref counting, Unref is annotated. {{{1
3810 // same as test76, but RefCountedClass::Unref is annotated.
3813 RefCountedClass *object = NULL;
3817 object->AccessData();
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);
3828 REGISTER_TEST(Run, 78)
3829 #endif // NO_BARRIER
3830 } // namespace test78
3834 // test79 TN. Swap. {{{1
3837 typedef __gnu_cxx::hash_map<int, int> map_t;
3839 typedef std::map<int, int> map_t;
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.
3851 // We swap the new empty map 'tmp' with 'MAP'.
3854 // tmp (which is the old version of MAP) is destroyed here.
3859 MAP[1]++; // Just update MAP under MU.
3863 void Worker3() { Worker1(); }
3864 void Worker4() { Worker2(); }
3867 ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
3868 printf("test79: negative\n");
3869 MyThreadArray t(Worker1, Worker2, Worker3, Worker4);
3873 REGISTER_TEST(Run, 79)
3874 } // namespace test79
3877 // AtomicRefCountedClass. {{{1
3878 // Same as RefCountedClass, but using atomic ops instead of mutex.
3879 struct AtomicRefCountedClass {
3881 AtomicRefCountedClass() {
3882 annotate_unref_ = false;
3887 ~AtomicRefCountedClass() {
3888 CHECK(ref_ == 0); // race may be reported here
3889 int data_val = data_; // and here
3892 printf("\tRefCountedClass::data_ = %d\n", data_val);
3902 AtomicIncrement(&ref_, 1);
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); }
3913 if (annotate_unref_) { ANNOTATE_CONDVAR_WAIT(this); }
3918 void AnnotateUnref() {
3919 annotate_unref_ = true;
3921 void Annotate_Race() {
3922 ANNOTATE_BENIGN_RACE(&this->data_, "needs annotation");
3925 bool annotate_unref_;
3928 int data_; // under mu_
3930 int ref_; // used in atomic ops.
3933 // test80: FP. Ref counting with atomics, no annotations. {{{1
3938 AtomicRefCountedClass *object = NULL;
3942 object->AccessData();
3943 object->Unref(); // All the tricky stuff is here.
3946 printf("test80: false positive (ref counting)\n");
3947 object = new AtomicRefCountedClass;
3948 object->Annotate_Race();
3949 MyThreadArray t(Worker, Worker, Worker, Worker);
3953 REGISTER_TEST2(Run, 80, FEATURE|EXCLUDE_FROM_ALL)
3954 #endif // NO_BARRIER
3955 } // namespace test80
3958 // test81: TN. Ref counting with atomics, Unref is annotated. {{{1
3961 // same as test80, but Unref is annotated.
3964 AtomicRefCountedClass *object = NULL;
3968 object->AccessData();
3969 object->Unref(); // All the tricky stuff is here.
3972 printf("test81: negative (annotated ref counting)\n");
3973 object = new AtomicRefCountedClass;
3974 object->AnnotateUnref();
3975 MyThreadArray t(Worker, Worker, Worker, Worker);
3979 REGISTER_TEST2(Run, 81, FEATURE|EXCLUDE_FROM_ALL)
3980 #endif // NO_BARRIER
3981 } // namespace test81
3984 // test82: Object published w/o synchronization. {{{1
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.
3990 // On Core 2 Duo this test will sometimes (quite rarely) fail in
3991 // the CHECK below, at least if compiled with -O2.
3993 // The sequence of events::
3994 // Thread1: Thread2:
3995 // a. arr_[...] = ...
3997 // A. ... = foo[i]; // non NULL
3998 // B. ... = arr_[...];
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.
4008 idx_ = rand() % 1024;
4010 // __asm__ __volatile__("" : : : "memory"); // this fixes!
4012 static void check(volatile FOO *foo) {
4013 CHECK(foo->arr_[foo->idx_] == 77777);
4020 const int N = 100000;
4021 static volatile FOO *foo[N];
4025 for (int i = 0; i < N; i++) {
4032 for (int i = 0; i < N; i++) {
4034 MU.Lock(); // this is NOT a synchronization,
4035 MU.Unlock(); // it just helps foo[i] to become visible in Reader.
4037 if ((i % 100) == 0) {
4038 printf("rd %d\n", i);
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.
4048 printf("test82: positive\n");
4049 MyThreadArray t(Writer, Reader);
4053 REGISTER_TEST2(Run, 82, FEATURE|EXCLUDE_FROM_ALL)
4054 } // namespace test82
4057 // test83: Object published w/o synchronization (simple version){{{1
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;
4071 MU.Lock(); // Not a synchronization!
4078 // printf("test83: positive\n");
4079 MyThreadArray t(Writer, Reader);
4083 REGISTER_TEST2(Run, 83, FEATURE|EXCLUDE_FROM_ALL)
4084 } // namespace test83
4087 // test84: TP. True race (regression test for a bug related to atomics){{{1
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.
4094 /* s_dummy[] ensures that s_x and s_y are not in the same cache line. */
4095 static char s_dummy[512] = {0};
4098 void thread_func_1()
4101 AtomicIncrement(&s_x, 1);
4104 void thread_func_2()
4106 while (AtomicIncrement(&s_x, 0) == 0)
4108 printf("y = %d\n", s_y);
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);
4121 REGISTER_TEST(Run, 84)
4122 } // namespace test84
4125 // test85: Test for RunningOnValgrind(). {{{1
4129 printf("test85: RunningOnValgrind() = %d\n", RunningOnValgrind());
4131 REGISTER_TEST(Run, 85)
4132 } // namespace test85
4135 // test86: Test for race inside DTOR: racey write to vptr. Benign. {{{1
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.
4154 // 2. Q.Put(a); ------------\ .
4155 // \--------------------> a. a = Q.Get();
4157 // /--------- c. flag_stopped = true;
4159 // waits untill flag_stopped <------/
4163 bool flag_stopped = false;
4166 ProducerConsumerQueue Q(INT_MAX); // Used to pass A* between threads.
4169 A() { printf("A::A()\n"); }
4170 virtual ~A() { printf("A::~A()\n"); }
4171 virtual void f() { }
4173 uintptr_t padding[15];
4174 } __attribute__ ((aligned (64)));
4177 B() { printf("B::B()\n"); }
4179 // The race is here. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
4180 printf("B::~B()\n");
4181 // wait until flag_stopped is true.
4182 mu.LockWhen(Condition(&ArgIsTrue, &flag_stopped));
4184 printf("B::~B() done\n");
4186 virtual void f() { }
4191 if (!Tsan_FastMode())
4192 ANNOTATE_EXPECT_RACE(a, "test86: expected race on a->vptr");
4193 printf("Waiter: B created\n");
4195 usleep(100000); // so that Worker calls a->f() first.
4196 printf("Waiter: deleting B\n");
4198 printf("Waiter: B deleted\n");
4200 printf("Waiter: done\n");
4204 A *a = reinterpret_cast<A*>(Q.Get());
4205 printf("Worker: got A\n");
4209 flag_stopped = true;
4212 printf("Worker: done\n");
4216 printf("test86: positive, race inside DTOR\n");
4217 MyThreadArray t(Waiter, Worker);
4221 REGISTER_TEST(Run, 86)
4222 } // namespace test86
4225 // test87: Test for race inside DTOR: racey write to vptr. Harmful.{{{1
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.
4236 bool flag_stopped = false;
4239 ProducerConsumerQueue Q(INT_MAX); // Used to pass A* between threads.
4242 A() { printf("A::A()\n"); }
4243 virtual ~A() { printf("A::~A()\n"); }
4244 virtual void f() = 0; // pure virtual.
4248 B() { printf("B::B()\n"); }
4250 // The race is here. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
4251 printf("B::~B()\n");
4252 // wait until flag_stopped is true.
4253 mu.LockWhen(Condition(&ArgIsTrue, &flag_stopped));
4255 printf("B::~B() done\n");
4257 virtual void f() = 0; // pure virtual.
4261 C() { printf("C::C()\n"); }
4262 virtual ~C() { printf("C::~C()\n"); }
4263 virtual void f() { }
4273 A *a = reinterpret_cast<A*>(Q.Get());
4277 flag_stopped = true;
4278 ANNOTATE_CONDVAR_SIGNAL(&mu);
4283 printf("test87: positive, race inside DTOR\n");
4284 MyThreadArray t(Waiter, Worker);
4288 REGISTER_TEST2(Run, 87, FEATURE|EXCLUDE_FROM_ALL)
4289 } // namespace test87
4292 // test88: Test for ANNOTATE_IGNORE_WRITES_*{{{1
4294 // a recey write annotated with ANNOTATE_IGNORE_WRITES_BEGIN/END.
4297 ANNOTATE_IGNORE_WRITES_BEGIN();
4299 ANNOTATE_IGNORE_WRITES_END();
4302 printf("test88: negative, test for ANNOTATE_IGNORE_WRITES_*\n");
4307 printf("\tGLOB=%d\n", GLOB);
4309 REGISTER_TEST(Run, 88)
4310 } // namespace test88
4313 // test89: Test for debug info. {{{1
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.
4325 ANNOTATE_TRACE_MEMORY(&a);
4334 B() { CHECK(a == 1); }
4335 virtual ~B() { CHECK(a == 3); }
4339 virtual ~C() { a = 3; }
4345 STRUCT *STACK_STRUCT;
4346 STRUCT *HEAP_STRUCT;
4352 STACK_STRUCT->b = 1;
4360 STRUCT stack_struct;
4361 STACK_STRUCT = &stack_struct;
4363 HEAP_STRUCT = new STRUCT;
4365 printf("test89: negative\n");
4366 MyThreadArray t(Worker, Worker);
4373 printf("Using 'a->a': %d\n", a->a);
4376 REGISTER_TEST2(Run, 89, FEATURE|EXCLUDE_FROM_ALL)
4377 } // namespace test89
4380 // test90: FP. Test for a safely-published pointer (read-only). {{{1
4382 // The Publisher creates an object and safely publishes it under a mutex.
4383 // Readers access the object read-only.
4386 // Without annotations Helgrind will issue a false positive in Reader().
4388 // Choices for annotations:
4389 // -- ANNOTATE_CONDVAR_SIGNAL/ANNOTATE_CONDVAR_WAIT
4390 // -- ANNOTATE_MUTEX_IS_USED_AS_CONDVAR
4391 // -- ANNOTATE_PUBLISH_MEMORY_RANGE.
4398 GLOB = (int*)memalign(64, sizeof(int));
4400 if (!Tsan_PureHappensBefore() && !Tsan_FastMode())
4401 ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test90. FP. This is a false positve");
4413 CHECK(*p == 777); // Race is reported here.
4420 printf("test90: false positive (safely published pointer).\n");
4421 MyThreadArray t(Publisher, Reader, Reader, Reader);
4424 printf("\t*GLOB=%d\n", *GLOB);
4427 REGISTER_TEST(Run, 90)
4428 } // namespace test90
4431 // test91: FP. Test for a safely-published pointer (read-write). {{{1
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.
4437 // Without annotations Helgrind will issue a false positive in Accessor().
4445 GLOB = (int*)memalign(64, sizeof(int));
4447 if (!Tsan_PureHappensBefore() && !Tsan_FastMode())
4448 ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test91. FP. This is a false positve");
4460 (*p)++; // Race is reported here.
4469 printf("test91: false positive (safely published pointer, read/write).\n");
4470 MyThreadArray t(Publisher, Accessor, Accessor, Accessor);
4473 printf("\t*GLOB=%d\n", *GLOB);
4476 REGISTER_TEST(Run, 91)
4477 } // namespace test91
4480 // test92: TN. Test for a safely-published pointer (read-write), annotated. {{{1
4482 // Similar to test91, but annotated with ANNOTATE_PUBLISH_MEMORY_RANGE.
4485 // Publisher: Accessors:
4489 // 3. ANNOTATE_PUBLISH_...(GLOB) -------\ .
4490 // 4. MU1.Unlock() \ .
4493 // \ c. MU1.Unlock()
4494 // \--> d. Access GLOB
4496 // A happens-before arc is created between ANNOTATE_PUBLISH_MEMORY_RANGE and
4497 // accesses to GLOB.
4509 for (int i = 0; i < 10; i++) {
4512 // This annotation should go right before the object is published.
4513 ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB, sizeof(*GLOB));
4517 void Accessor(int index) {
4524 p->arr[index]++; // W/o the annotations the race will be reported here.
4525 CHECK(p->arr[index] == 778);
4532 void Accessor0() { Accessor(0); }
4533 void Accessor5() { Accessor(5); }
4534 void Accessor9() { Accessor(9); }
4537 printf("test92: safely published pointer, read/write, annotated.\n");
4538 MyThreadArray t(Publisher, Accessor0, Accessor5, Accessor9);
4541 printf("\t*GLOB=%d\n", GLOB->arr[0]);
4543 REGISTER_TEST(Run, 92)
4544 } // namespace test92
4547 // test93: TP. Test for incorrect usage of ANNOTATE_PUBLISH_MEMORY_RANGE. {{{1
4557 // Incorrect, used after the memory has been accessed in another thread.
4558 ANNOTATE_PUBLISH_MEMORY_RANGE(&GLOB, sizeof(GLOB));
4562 printf("test93: positive, misuse of ANNOTATE_PUBLISH_MEMORY_RANGE\n");
4563 MyThreadArray t(Reader, Publisher);
4566 printf("\tGLOB=%d\n", GLOB);
4568 REGISTER_TEST2(Run, 93, FEATURE|EXCLUDE_FROM_ALL)
4569 } // namespace test93
4572 // test94: TP. Check do_cv_signal/fake segment logic {{{1
4582 usleep(10000); // Make sure the waiter blocks.
4592 usleep(1000*1000); // Make sure CV2.Signal() "happens after" CV.Signal()
4593 usleep(10000); // Make sure the waiter blocks.
4611 GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait !
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);
4620 printf("\tGLOB=%d\n", GLOB);
4622 REGISTER_TEST(Run, 94);
4623 } // namespace test94
4625 // test95: TP. Check do_cv_signal/fake segment logic {{{1
4635 usleep(1000*1000); // Make sure CV2.Signal() "happens before" CV.Signal()
4636 usleep(10000); // Make sure the waiter blocks.
4646 usleep(10000); // Make sure the waiter blocks.
4664 GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait !
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);
4673 printf("\tGLOB=%d\n", GLOB);
4675 REGISTER_TEST(Run, 95);
4676 } // namespace test95
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
4706 printf("test96: FP. tricky LockSet behaviour\n");
4707 ANNOTATE_TRACE_MEMORY(&GLOB);
4708 MyThreadArray mta(Thread1, Thread2, Thread3);
4712 printf("\tGLOB=%d\n", GLOB);
4714 REGISTER_TEST(Run, 96);
4715 } // namespace test96
4717 // test97: This test shows false negative with --fast-mode=yes {{{1
4719 const int HG_CACHELINE_SIZE = 64;
4723 const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4724 int array[ARRAY_SIZE];
4725 int * GLOB = &array[ARRAY_SIZE/2];
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
4733 CHECK(777 == *GLOB);
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");
4747 REGISTER_TEST2(Run, 97, FEATURE)
4748 } // namespace test97
4750 // test98: Synchronization via read/write (or send/recv). {{{1
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.
4759 // A race detector has to create a happens-before arcs for
4760 // {read,send}->{write,recv} even if the file descriptors are different.
4769 const char *str = "Hey there!\n";
4770 IGNORE_RETURN_VALUE(write(fd_out, str, strlen(str) + 1));
4775 while (read(fd_in, buff, 100) == 0)
4777 printf("read: %s\n", buff);
4782 printf("test98: negative, synchronization via I/O\n");
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);
4790 // symlink() is not supported on Darwin. Copy the output file name.
4791 strcpy(in_name, out_name);
4793 sprintf(in_name, "/tmp/racecheck_unittest_in.%d", getpid());
4794 IGNORE_RETURN_VALUE(symlink(out_name, in_name));
4796 fd_in = open(in_name, 0, O_RDONLY);
4799 MyThreadArray t(Writer, Reader);
4802 printf("\tGLOB=%d\n", GLOB);
4809 REGISTER_TEST(Run, 98)
4810 } // namespace test98
4813 // test99: TP. Unit test for a bug in LockWhen*. {{{1
4820 static void Thread1() {
4821 for (int i = 0; i < 100; i++) {
4822 mu.LockWhenWithTimeout(Condition(&ArgIsTrue, &GLOB), 5);
4829 static void Thread2() {
4830 for (int i = 0; i < 100; i++) {
4838 printf("test99: regression test for LockWhen*\n");
4839 MyThreadArray t(Thread1, Thread2);
4843 REGISTER_TEST(Run, 99);
4844 } // namespace test99
4847 // test100: Test for initialization bit. {{{1
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);
4884 REGISTER_TEST2(Run, 100, FEATURE|EXCLUDE_FROM_ALL)
4885 } // namespace test100
4888 // test101: TN. Two signals and two waits. {{{1
4932 printf("test101: negative\n");
4933 MyThreadArray t(Waiter, Signaller);
4936 printf("\tGLOB=%d\n", GLOB);
4938 REGISTER_TEST(Run, 101)
4939 } // namespace test101
4941 // test102: --fast-mode=yes vs. --initialization-bit=yes {{{1
4943 const int HG_CACHELINE_SIZE = 64;
4947 const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4948 int array[ARRAY_SIZE + 1];
4949 int * GLOB = &array[ARRAY_SIZE/2];
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
4957 CHECK(777 == GLOB[0]);
4959 CHECK(777 == GLOB[1]);
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");
4976 REGISTER_TEST2(Run, 102, FEATURE)
4977 } // namespace test102
4979 // test103: Access different memory locations with different LockSets {{{1
4981 const int N_MUTEXES = 6;
4982 const int LOCKSET_INTERSECTION_SIZE = 3;
4984 int data[1 << LOCKSET_INTERSECTION_SIZE] = {0};
4985 Mutex MU[N_MUTEXES];
4987 inline int LS_to_idx (int ls) {
4988 return (ls >> (N_MUTEXES - LOCKSET_INTERSECTION_SIZE))
4989 & ((1 << LOCKSET_INTERSECTION_SIZE) - 1);
4993 for (int ls = 0; ls < (1 << N_MUTEXES); ls++) {
4994 if (LS_to_idx(ls) == 0)
4996 for (int m = 0; m < N_MUTEXES; m++)
5000 data[LS_to_idx(ls)]++;
5002 for (int m = N_MUTEXES - 1; m >= 0; m--)
5009 printf("test103: Access different memory locations with different LockSets\n");
5010 MyThreadArray t(Worker, Worker, Worker, Worker);
5014 REGISTER_TEST2(Run, 103, FEATURE)
5015 } // namespace test103
5017 // test104: TP. Simple race (write vs write). Heap mem. {{{1
5032 GLOB = (int*)memalign(64, sizeof(int));
5034 ANNOTATE_EXPECT_RACE(GLOB, "test104. TP.");
5035 ANNOTATE_TRACE_MEMORY(GLOB);
5036 printf("test104: positive\n");
5038 printf("\tGLOB=%d\n", *GLOB);
5041 REGISTER_TEST(Run, 104);
5042 } // namespace test104
5045 // test105: Checks how stack grows. {{{1
5051 // ANNOTATE_TRACE_MEMORY(&ar[0]);
5052 // ANNOTATE_TRACE_MEMORY(&ar[31]);
5059 // ANNOTATE_TRACE_MEMORY(&ar[0]);
5060 // ANNOTATE_TRACE_MEMORY(&ar[31]);
5067 printf("test105: negative\n");
5072 printf("\tGLOB=%d\n", GLOB);
5074 REGISTER_TEST(Run, 105)
5075 } // namespace test105
5078 // test106: TN. pthread_once. {{{1
5081 static pthread_once_t once = PTHREAD_ONCE_INIT;
5084 ANNOTATE_TRACE_MEMORY(GLOB);
5089 pthread_once(&once, Init);
5093 pthread_once(&once, Init);
5094 CHECK(*GLOB == 777);
5099 printf("test106: negative\n");
5100 MyThreadArray t(Worker0, Worker1, Worker1, Worker1);
5103 printf("\tGLOB=%d\n", *GLOB);
5105 REGISTER_TEST2(Run, 106, FEATURE)
5106 } // namespace test106
5109 // test107: Test for ANNOTATE_EXPECT_RACE {{{1
5113 printf("test107: negative\n");
5114 ANNOTATE_EXPECT_RACE(&GLOB, "No race in fact. Just checking the tool.");
5115 printf("\tGLOB=%d\n", GLOB);
5117 REGISTER_TEST2(Run, 107, FEATURE|EXCLUDE_FROM_ALL)
5118 } // namespace test107
5121 // test108: TN. initialization of static object. {{{1
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.
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.
5134 ANNOTATE_TRACE_MEMORY(&a_);
5137 void Check() const { CHECK(a_ == 42); }
5142 const Foo *GetFoo() {
5143 static const Foo *foo = new Foo();
5152 const Foo *foo = GetFoo();
5158 printf("test108: negative, initialization of static object\n");
5159 MyThreadArray t(Worker0, Worker, Worker);
5163 REGISTER_TEST2(Run, 108, FEATURE)
5164 } // namespace test108
5167 // test109: TN. Checking happens before between parent and child threads. {{{1
5169 // Check that the detector correctly connects
5170 // pthread_create with the new thread
5172 // thread exit with pthread_join
5176 void Worker(void *a) {
5178 // printf("--Worker : %ld %p\n", (int*)a - GLOB, (void*)pthread_self());
5184 printf("test109: negative\n");
5186 for (int i = 0; i < N; i++) {
5187 t[i] = new MyThread(Worker, &GLOB[i]);
5189 for (int i = 0; i < N; i++) {
5190 ANNOTATE_TRACE_MEMORY(&GLOB[i]);
5193 // printf("--Started: %p\n", (void*)t[i]->tid());
5195 for (int i = 0; i < N; i++) {
5196 // printf("--Joining: %p\n", (void*)t[i]->tid());
5198 // printf("--Joined : %p\n", (void*)t[i]->tid());
5201 for (int i = 0; i < N; i++) delete t[i];
5203 printf("\tGLOB=%d\n", GLOB[13]);
5205 REGISTER_TEST(Run, 109)
5206 } // namespace test109
5209 // test110: TP. Simple races with stack, global and heap objects. {{{1
5222 union pi_pv_union { int* pi; void* pv; } POSIX_MEMALIGN;
5240 (*(POSIX_MEMALIGN.pi))++;
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);
5261 NEW_ARR = new int[10];
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");
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");
5292 MyThreadArray t(Worker, Worker, Worker);
5295 printf("test110: positive (race on a stack object)\n");
5296 printf("\tSTACK=%d\n", *STACK);
5306 free(POSIX_MEMALIGN.pv);
5307 munmap(MMAP, sizeof(int));
5311 REGISTER_TEST(Run, 110)
5312 } // namespace test110
5315 // test111: TN. Unit test for a bug related to stack handling. {{{1
5322 void write_to_p(char *p, int val) {
5323 for (int i = 0; i < N; i++)
5327 static bool ArgIsTrue(bool *arg) {
5328 // printf("ArgIsTrue: %d tid=%d\n", *arg, (int)pthread_self());
5329 return *arg == true;
5334 write_to_p(some_stack, 1);
5335 mu.LockWhen(Condition(&ArgIsTrue, &COND));
5341 char some_more_stack[N];
5342 write_to_p(some_stack, 2);
5343 write_to_p(some_more_stack, 2);
5362 printf("test111: regression test\n");
5363 MyThreadArray t(Worker1, Worker1, Worker2);
5364 // AnnotateSetVerbosity(__FILE__, __LINE__, 3);
5367 // AnnotateSetVerbosity(__FILE__, __LINE__, 1);
5369 REGISTER_TEST2(Run, 111, FEATURE)
5370 } // namespace test111
5372 // test112: STAB. Test for ANNOTATE_PUBLISH_MEMORY_RANGE{{{1
5375 const int N = 64 * 5;
5377 bool ready = false; // under mu
5378 int beg, end; // under mu
5384 bool is_ready = false;
5396 for (int i = b; i < e; i++) {
5402 void PublishRange(int b, int e) {
5403 MyThreadArray t(Worker, Worker);
5404 ready = false; // runs before other threads
5407 ANNOTATE_NEW_MEMORY(GLOB + b, e - b);
5408 ANNOTATE_TRACE_MEMORY(GLOB + b);
5409 for (int j = b; j < e; j++) {
5412 ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB + b, e - b);
5425 printf("test112: stability (ANNOTATE_PUBLISH_MEMORY_RANGE)\n");
5426 GLOB = new char [N];
5428 PublishRange(0, 10);
5431 PublishRange(12, 13);
5432 PublishRange(10, 14);
5434 PublishRange(15, 17);
5435 PublishRange(16, 18);
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;
5442 CHECK(begin + size <= N);
5443 PublishRange(begin, begin + size);
5446 printf("GLOB = %d\n", (int)GLOB[0]);
5448 REGISTER_TEST2(Run, 112, STABILITY)
5449 } // namespace test112
5452 // test113: PERF. A lot of lock/unlock calls. Many locks {{{1
5454 const int kNumIter = 100000;
5455 const int kNumLocks = 7;
5456 Mutex MU[kNumLocks];
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();
5463 for (int j = kNumLocks - 1; j >= 0; j--) {
5464 if (i & (1 << j)) MU[j].Unlock();
5468 REGISTER_TEST(Run, 113)
5469 } // namespace test113
5472 // test114: STAB. Recursive lock. {{{1
5479 static int foo = Bar();
5483 static int x = Foo();
5487 printf("test114: stab\n");
5488 MyThreadArray t(Worker, Worker);
5492 REGISTER_TEST(Run, 114)
5493 } // namespace test114
5496 // test115: TN. sem_open. {{{1
5500 const char *kSemName = "drt-test-sem";
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();
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();
5526 CHECK(sem != SEM_FAILED);
5527 CHECK(sem_wait(sem) == 0);
5535 printf("test115: stab (sem_open())\n");
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);
5544 // check that sem_open and sem_wait create a happens-before arc.
5545 MyThreadArray t(Worker, Worker, Worker);
5549 sem_unlink(kSemName);
5551 REGISTER_TEST(Run, 115)
5552 } // namespace test115
5555 // test116: TN. some operations with string<> objects. {{{1
5559 string A[10], B[10], C[10];
5560 for (int i = 0; i < 1000; i++) {
5561 for (int j = 0; j < 10; j++) {
5565 a = "sdl;fkjhasdflksj df";
5566 b = "sdf sdf;ljsd ";
5574 for (int j = 0; j < 10; j++) {
5586 printf("test116: negative (strings)\n");
5587 MyThreadArray t(Worker, Worker, Worker);
5591 REGISTER_TEST2(Run, 116, FEATURE|EXCLUDE_FROM_ALL)
5592 } // namespace test116
5594 // test117: TN. Many calls to function-scope static init. {{{1
5603 void Worker(void *a) {
5604 static int foo = Foo();
5609 printf("test117: negative\n");
5611 for (int i = 0; i < N; i++) {
5612 t[i] = new MyThread(Worker);
5614 for (int i = 0; i < N; i++) {
5617 for (int i = 0; i < N; i++) {
5620 for (int i = 0; i < N; i++) delete t[i];
5622 REGISTER_TEST(Run, 117)
5623 } // namespace test117
5627 // test118 PERF: One signal, multiple waits. {{{1
5630 const int kNumIter = 2000000;
5633 ANNOTATE_CONDVAR_SIGNAL(&GLOB);
5636 for (int i = 0; i < kNumIter; i++) {
5637 ANNOTATE_CONDVAR_WAIT(&GLOB);
5638 if (i == kNumIter / 2)
5643 printf("test118: perf\n");
5644 MyThreadArray t(Signaller, Waiter, Signaller, Waiter);
5647 printf("\tGLOB=%d\n", GLOB);
5649 REGISTER_TEST(Run, 118)
5650 } // namespace test118
5653 // test119: TP. Testing that malloc does not introduce any HB arc. {{{1
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);
5673 printf("\tGLOB=%d\n", GLOB);
5675 REGISTER_TEST(Run, 119)
5676 } // namespace test119
5679 // test120: TP. Thread1: write then read. Thread2: read. {{{1
5685 CHECK(GLOB); // read
5690 CHECK(GLOB >= 0); // read
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);
5701 printf("\tGLOB=%d\n", GLOB);
5703 REGISTER_TEST(Run, 120)
5704 } // namespace test120
5707 // test121: TP. Example of double-checked-locking {{{1
5711 } __attribute__ ((aligned (64)));
5718 MutexLock lock(&mu);
5720 ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo, "test121. Double-checked locking (ptr)");
5722 if (!Tsan_FastMode())
5723 ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo->a, "test121. Double-checked locking (obj)");
5731 CHECK(foo && foo->a == 42);
5734 void Worker1() { UseMe(); }
5735 void Worker2() { UseMe(); }
5736 void Worker3() { UseMe(); }
5740 FAST_MODE_INIT(&foo);
5741 printf("test121: TP. Example of double-checked-locking\n");
5742 MyThreadArray t1(Worker1, Worker2, Worker3);
5747 REGISTER_TEST(Run, 121)
5748 } // namespace test121
5750 // test122 TP: Simple test with RWLock {{{1
5756 void WriteWhileHoldingReaderLock(int *p) {
5758 ReaderLockScoped lock(&mu); // Reader lock for writing. -- bug.
5762 void CorrectWrite(int *p) {
5763 WriterLockScoped lock(&mu);
5767 void Thread1() { WriteWhileHoldingReaderLock(&VAR1); }
5768 void Thread2() { CorrectWrite(&VAR1); }
5769 void Thread3() { CorrectWrite(&VAR2); }
5770 void Thread4() { WriteWhileHoldingReaderLock(&VAR2); }
5774 printf("test122: positive (rw-lock)\n");
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");
5783 MyThreadArray t(Thread1, Thread2, Thread3, Thread4);
5787 REGISTER_TEST(Run, 122)
5788 } // namespace test122
5791 // test123 TP: accesses of different sizes. {{{1
5803 // Q. Hey dude, why so many functions?
5804 // A. I need different stack traces for different accesses.
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; }
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; }
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; }
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; }
5886 void W00() { WriteAll64(); }
5887 void W01() { WriteAll64(); }
5888 void W02() { WriteAll64(); }
5890 void W10() { WriteAll32(); }
5891 void W11() { WriteAll32(); }
5892 void W12() { WriteAll32(); }
5894 void W20() { WriteAll16(); }
5895 void W21() { WriteAll16(); }
5896 void W22() { WriteAll16(); }
5898 void W30() { WriteAll8(); }
5899 void W31() { WriteAll8(); }
5900 void W32() { WriteAll8(); }
5902 typedef void (*F)(void);
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);
5912 ANNOTATE_NEW_MEMORY(&MEM, sizeof(MEM));
5913 memset(&MEM, 0, sizeof(MEM));
5914 MyThreadArray t2(f2, f1);
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);
5929 REGISTER_TEST2(Run, 123, FEATURE|EXCLUDE_FROM_ALL)
5930 } // namespace test123
5933 // test124: What happens if we delete an unlocked lock? {{{1
5935 // This test does not worg with pthreads (you can't call
5936 // pthread_mutex_destroy on a locked lock).
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();
5945 delete []a_large_local_array_of_mutexes;
5950 printf("test124: negative\n");
5951 MyThreadArray t(Worker, Worker, Worker);
5954 printf("\tGLOB=%d\n", GLOB);
5956 REGISTER_TEST2(Run, 124, FEATURE|EXCLUDE_FROM_ALL)
5957 } // namespace test124
5960 // test125 TN: Backwards lock (annotated). {{{1
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.
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).
5972 const int n_threads = 3;
5974 int GLOB[n_threads];
5976 int adder_num; // updated atomically.
5979 int my_num = AtomicIncrement(&adder_num, 1);
5981 ReaderLockScoped lock(&mu);
5988 WriterLockScoped lock(&mu);
5989 for (int i = 0; i < n_threads; i++) {
5993 printf("sum=%d\n", sum);
5997 printf("test125: negative\n");
5999 ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu);
6001 // run Adders, then Aggregator
6003 MyThreadArray t(Adder, Adder, Adder, Aggregator);
6008 // Run Aggregator first.
6011 MyThreadArray t(Aggregator, Adder, Adder, Adder);
6017 REGISTER_TEST(Run, 125)
6018 } // namespace test125
6020 // test126 TN: test for BlockingCounter {{{1
6022 BlockingCounter *blocking_counter;
6025 CHECK(blocking_counter);
6027 blocking_counter->DecrementCount();
6030 printf("test126: negative\n");
6031 MyThreadArray t(Worker, Worker, Worker);
6032 blocking_counter = new BlockingCounter(3);
6034 blocking_counter->Wait();
6037 printf("\tGLOB=%d\n", GLOB);
6039 REGISTER_TEST(Run, 126)
6040 } // namespace test126
6043 // test127. Bad code: unlocking a mutex locked by another thread. {{{1
6054 printf("test127: unlocking a mutex locked by another thread.\n");
6055 MyThreadArray t(Thread1, Thread2);
6059 REGISTER_TEST(Run, 127)
6060 } // namespace test127
6062 // test128. Suppressed code in concurrent accesses {{{1
6063 // Please use --suppressions=unittest.supp flag when running this test.
6073 void ThisFunctionShouldBeSuppressed() {
6077 printf("test128: Suppressed code in concurrent accesses.\n");
6078 MyThreadArray t(Worker, ThisFunctionShouldBeSuppressed);
6082 REGISTER_TEST2(Run, 128, FEATURE | EXCLUDE_FROM_ALL)
6083 } // namespace test128
6085 // test129: TN. Synchronization via ReaderLockWhen(). {{{1
6089 bool WeirdCondition(int* param) {
6090 *param = GLOB; // a write into Waiter's memory
6095 MU.ReaderLockWhen(Condition(WeirdCondition, ¶m));
6101 usleep(100000); // Make sure the waiter blocks.
6104 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
6107 printf("test129: Synchronization via ReaderLockWhen()\n");
6108 MyThread mt(Waiter, NULL, "Waiter Thread");
6112 printf("\tGLOB=%d\n", GLOB);
6114 REGISTER_TEST2(Run, 129, FEATURE);
6115 } // namespace test129
6117 // test130: TN. Per-thread. {{{1
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:
6124 // - Thread1 touches per_thread_global
6126 // - Thread2 starts (and there is no happens-before relation between it and
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.
6133 // test131 does the same for stack.
6135 static __thread int per_thread_global[10] = {0};
6137 void RealWorker() { // Touch per_thread_global.
6138 per_thread_global[1]++;
6142 void Worker() { // Spawn few threads that touch per_thread_global.
6143 MyThreadArray t(RealWorker, RealWorker);
6147 void Worker0() { sleep(0); Worker(); }
6148 void Worker1() { sleep(1); Worker(); }
6149 void Worker2() { sleep(2); Worker(); }
6150 void Worker3() { sleep(3); Worker(); }
6153 printf("test130: Per-thread\n");
6154 MyThreadArray t1(Worker0, Worker1, Worker2, Worker3);
6157 printf("\tper_thread_global=%d\n", per_thread_global[1]);
6159 REGISTER_TEST(Run, 130)
6161 } // namespace test130
6164 // test131: TN. Stack. {{{1
6166 // Same as test130, but for stack.
6168 void RealWorker() { // Touch stack.
6173 void Worker() { // Spawn few threads that touch stack.
6174 MyThreadArray t(RealWorker, RealWorker);
6178 void Worker0() { sleep(0); Worker(); }
6179 void Worker1() { sleep(1); Worker(); }
6180 void Worker2() { sleep(2); Worker(); }
6181 void Worker3() { sleep(3); Worker(); }
6184 printf("test131: stack\n");
6185 MyThreadArray t(Worker0, Worker1, Worker2, Worker3);
6189 REGISTER_TEST(Run, 131)
6190 } // namespace test131
6193 // test132: TP. Simple race (write vs write). Works in fast-mode. {{{1
6196 void Worker() { GLOB = 1; }
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);
6204 MyThreadArray t(Worker, Worker);
6212 REGISTER_TEST(Run, 132);
6213 } // namespace test132
6216 // test133: TP. Simple race (write vs write). Works in fast mode. {{{1
6218 // Same as test132, but everything is run from a separate thread spawned from
6221 void Worker() { GLOB = 1; }
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);
6229 MyThreadArray t(Worker, Worker);
6238 REGISTER_TEST(Run, 133);
6239 } // namespace test133
6242 // test134 TN. Swap. Variant of test79. {{{1
6245 typedef __gnu_cxx::hash_map<int, int> map_t;
6247 typedef std::map<int, int> map_t;
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.
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.
6264 MutexLock lock(&mu);
6265 ANNOTATE_HAPPENS_AFTER(&map);
6266 // We swap the new empty map 'tmp' with 'map'.
6268 ANNOTATE_HAPPENS_BEFORE(&map);
6269 // tmp (which is the old version of map) is destroyed here.
6273 MutexLock lock(&mu);
6274 ANNOTATE_HAPPENS_AFTER(&map);
6276 ANNOTATE_HAPPENS_BEFORE(&map);
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);
6287 REGISTER_TEST(Run, 134)
6288 } // namespace test134
6290 // test135 TN. Swap. Variant of test79. {{{1
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);
6304 MyThreadArray t(SubWorker, SubWorker, SubWorker, SubWorker);
6310 printf("test135: negative (mmap)\n");
6311 MyThreadArray t(Worker, Worker, Worker, Worker);
6315 REGISTER_TEST(Run, 135)
6316 } // namespace test135
6318 // test136. Unlock twice. {{{1
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));
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);
6337 REGISTER_TEST(Run, 136)
6338 } // namespace test136
6340 // test137 TP. Races on stack variables. {{{1
6343 ProducerConsumerQueue q(10);
6347 int *tmp = (int*)q.Get();
6349 int *racey = &stack;
6353 // We may miss the races if we sleep less due to die_memory events...
6358 printf("test137: TP. Races on stack variables.\n");
6360 MyThreadArray t(Worker, Worker, Worker, Worker);
6366 REGISTER_TEST2(Run, 137, FEATURE | EXCLUDE_FROM_ALL)
6367 } // namespace test137
6369 // test138 FN. Two closures hit the same thread in ThreadPool. {{{1
6379 FAST_MODE_INIT(&GLOB);
6380 printf("test138: FN. Two closures hit the same thread in ThreadPool.\n");
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).
6390 tp.Add(NewCallback(Worker));
6391 tp.Add(NewCallback(Worker));
6394 REGISTER_TEST2(Run, 138, FEATURE)
6395 } // namespace test138
6397 // test139: FN. A true race hidden by reference counting annotation. {{{1
6400 RefCountedClass *obj;
6403 GLOB++; // First access.
6410 GLOB++; // Second access.
6414 FAST_MODE_INIT(&GLOB);
6415 printf("test139: FN. A true race hidden by reference counting annotation.\n");
6417 obj = new RefCountedClass;
6418 obj->AnnotateUnref();
6421 MyThreadArray mt(Worker1, Worker2);
6426 REGISTER_TEST2(Run, 139, FEATURE)
6427 } // namespace test139
6429 // test140 TN. Swap. Variant of test79 and test134. {{{1
6432 typedef __gnu_cxx::hash_map<int, int> Container;
6434 typedef std::map<int,int> Container;
6437 static Container container;
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.
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.
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.
6452 // We want to be able to annotate swapper so that we don't need to annotate
6456 tmp[1] = tmp[2] = tmp[3] = 0;
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));
6467 // tmp (which is the old version of container) is destroyed here.
6471 MutexLock lock(&mu);
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);
6484 printf("test140: negative (swap) %p\n", &container);
6485 MyThreadArray t(Worker, Worker, Swapper, Worker, Worker);
6489 REGISTER_TEST(Run, 140)
6490 } // namespace test140
6492 // test141 FP. unlink/fopen, rmdir/opendir. {{{1
6496 char *dir_name = NULL,
6502 // unlink deletes a file 'filename'
6503 // which exits spin-loop in Waiter1().
6504 printf(" Deleting file...\n");
6505 CHECK(unlink(filename) == 0);
6510 while ((tmp = fopen(filename, "r")) != NULL) {
6514 printf(" ...file has been deleted\n");
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);
6529 while ((tmp = opendir(dir_name)) != NULL) {
6533 printf(" ...directory has been deleted\n");
6538 FAST_MODE_INIT(&GLOB1);
6539 FAST_MODE_INIT(&GLOB2);
6540 printf("test141: FP. unlink/fopen, rmdir/opendir.\n");
6542 dir_name = strdup("/tmp/tsan-XXXXXX");
6543 IGNORE_RETURN_VALUE(mkdtemp(dir_name));
6545 filename = strdup((std::string() + dir_name + "/XXXXXX").c_str());
6546 const int fd = mkstemp(filename);
6550 MyThreadArray mta1(Waker1, Waiter1);
6554 MyThreadArray mta2(Waker2, Waiter2);
6562 REGISTER_TEST(Run, 141)
6563 } // namespace test141
6566 // Simple FIFO queue annotated with PCQ annotations. {{{1
6567 class FifoMessageQueue {
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) {
6574 MutexLock lock(&mu_);
6575 ANNOTATE_PCQ_PUT(this);
6578 // Return the message from the queue and pop it
6579 // or return 0 if there are no messages.
6581 MutexLock lock(&mu_);
6582 if (q_.empty()) return 0;
6583 int res = q_.front();
6585 ANNOTATE_PCQ_GET(this);
6594 // test142: TN. Check PCQ_* annotations. {{{1
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.
6606 for (int i = 1; i <= N; i++) {
6614 int non_zero_received = 0;
6615 for (int i = 1; i <= N; i++) {
6618 CHECK(array[res] = res * res);
6619 non_zero_received++;
6623 printf("T=%d: non_zero_received=%d\n",
6624 (int)pthread_self(), non_zero_received);
6628 printf("test142: tests PCQ annotations\n");
6629 MyThreadArray t(Putter, Getter, Getter);
6633 REGISTER_TEST(Run, 142)
6634 } // namespace test142
6637 // test143: TP. Check PCQ_* annotations. {{{1
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
6644 // PCQ_* annotations do not hide this race.
6657 CHECK(GLOB == 1); // Race here
6662 if (!Tsan_PureHappensBefore()) {
6663 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "true races");
6665 printf("test143: tests PCQ annotations (true positive)\n");
6666 MyThreadArray t(Putter, Getter, Getter);
6670 REGISTER_TEST(Run, 143);
6671 } // namespace test143
6681 REGISTER_TEST2(Run, 300, RACE_DEMO)
6682 } // namespace test300
6684 // test301: Simple race. {{{1
6686 Mutex mu1; // This Mutex guards var.
6687 Mutex mu2; // This Mutex is not related to var.
6688 int var; // GUARDED_BY(mu1)
6690 void Thread1() { // Runs in thread named 'test-thread-1'.
6691 MutexLock lock(&mu1); // Correct Mutex.
6695 void Thread2() { // Runs in thread named 'test-thread-2'.
6696 MutexLock lock(&mu2); // Wrong Mutex.
6702 printf("test301: simple race.\n");
6703 MyThread t1(Thread1, NULL, "test-thread-1");
6704 MyThread t2(Thread2, NULL, "test-thread-2");
6710 REGISTER_TEST2(Run, 301, RACE_DEMO)
6711 } // namespace test301
6713 // test302: Complex race which happens at least twice. {{{1
6715 // In this test we have many different accesses to GLOB and only one access
6716 // is not synchronized properly.
6722 for(int i = 0; i < 100; i++) {
6725 // This read is protected correctly.
6726 MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock();
6729 // Here we used the wrong lock! The reason of the race is here.
6730 MU2.Lock(); CHECK(GLOB >= 0); MU2.Unlock();
6733 // This read is protected correctly.
6734 MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock();
6737 // This write is protected correctly.
6738 MU1.Lock(); GLOB++; MU1.Unlock();
6741 // sleep a bit so that the threads interleave
6742 // and the race happens at least twice.
6748 printf("test302: Complex race that happens twice.\n");
6749 MyThread t1(Worker), t2(Worker);
6752 t1.Join(); t2.Join();
6754 REGISTER_TEST2(Run, 302, RACE_DEMO)
6755 } // namespace test302
6758 // test303: Need to trace the memory to understand the report. {{{1
6763 void Worker1() { CHECK(GLOB >= 0); }
6764 void Worker2() { MU.Lock(); GLOB=1; MU.Unlock();}
6767 printf("test303: a race that needs annotations.\n");
6768 ANNOTATE_TRACE_MEMORY(&GLOB);
6769 MyThreadArray t(Worker1, Worker2);
6773 REGISTER_TEST2(Run, 303, RACE_DEMO)
6774 } // namespace test303
6778 // test304: Can not trace the memory, since it is a library object. {{{1
6785 ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6786 MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
6790 ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6791 CHECK(STR->length() >= 4); // Unprotected!
6795 ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6796 MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
6800 ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6801 MU.Lock(); *STR += " + a very very long string"; MU.Unlock();
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);
6811 printf("%s\n", STR->c_str());
6814 REGISTER_TEST2(Run, 304, RACE_DEMO)
6815 } // namespace test304
6819 // test305: A bit more tricky: two locks used inconsistenly. {{{1
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}
6830 // The guilty access is either Worker2() or Worker4(), depending on
6831 // which mutex is supposed to protect GLOB.
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(); }
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();
6849 REGISTER_TEST2(Run, 305, RACE_DEMO)
6850 } // namespace test305
6852 // test306: Two locks are used to protect a var. {{{1
6855 // Thread1 and Thread2 access the var under two locks.
6856 // Thread3 uses no locks.
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; }
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();
6873 REGISTER_TEST2(Run, 306, RACE_DEMO)
6874 } // namespace test306
6876 // test307: Simple race, code with control flow {{{1
6879 volatile /*to fake the compiler*/ bool some_condition = true;
6884 int FunctionWithControlFlow() {
6885 int unrelated_stuff = 0;
6887 SomeFunc(); // "--keep-history=1" will point somewhere here.
6888 if (some_condition) { // Or here
6889 if (some_condition) {
6890 unrelated_stuff++; // Or here.
6892 (*GLOB)++; // "--keep-history=2" will point here (experimental).
6896 return unrelated_stuff;
6899 void Worker1() { FunctionWithControlFlow(); }
6900 void Worker2() { Worker1(); }
6901 void Worker3() { Worker2(); }
6902 void Worker4() { Worker3(); }
6907 printf("test307: simple race, code with control flow\n");
6908 MyThreadArray t1(Worker1, Worker2, Worker3, Worker4);
6912 REGISTER_TEST2(Run, 307, RACE_DEMO)
6913 } // namespace test307
6915 // test308: Example of double-checked-locking {{{1
6921 static int is_inited = 0;
6939 CHECK(foo && foo->a == 42);
6942 void Worker1() { UseMe(); }
6943 void Worker2() { UseMe(); }
6944 void Worker3() { UseMe(); }
6948 ANNOTATE_TRACE_MEMORY(&is_inited);
6949 printf("test308: Example of double-checked-locking\n");
6950 MyThreadArray t1(Worker1, Worker2, Worker3);
6954 REGISTER_TEST2(Run, 308, RACE_DEMO)
6955 } // namespace test308
6957 // test309: Simple race on an STL object. {{{1
6966 GLOB="Booooooooooo";
6970 printf("test309: simple race on an STL object.\n");
6971 MyThread t1(Worker1), t2(Worker2);
6974 t1.Join(); t2.Join();
6976 REGISTER_TEST2(Run, 309, RACE_DEMO)
6977 } // namespace test309
6979 // test310: One more simple race. {{{1
6981 int *PTR = NULL; // GUARDED_BY(mu1)
6983 Mutex mu1; // Protects PTR.
6984 Mutex mu2; // Unrelated to PTR.
6985 Mutex mu3; // Unrelated to PTR.
6988 MutexLock lock3(&mu3); // This lock is unrelated to PTR.
6989 MutexLock lock1(&mu1); // Protect PTR.
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++;
7004 MutexLock lock2(&mu2); // Oh, gosh, this is a wrong mutex!
7008 // Some functions to make the stack trace non-trivial.
7009 void DoWrite1() { Writer1(); }
7010 void Thread1() { DoWrite1(); }
7012 void DoWrite2() { Writer2(); }
7013 void Thread2() { DoWrite2(); }
7015 void DoRead() { Reader(); }
7016 void Thread3() { DoRead(); }
7019 printf("test310: simple race.\n");
7021 ANNOTATE_TRACE_MEMORY(PTR);
7023 MyThread t1(Thread1, NULL, "writer1"),
7024 t2(Thread2, NULL, "writer2"),
7025 t3(Thread3, NULL, "buggy reader");
7028 usleep(100000); // Let the writers go first.
7035 REGISTER_TEST2(Run, 310, RACE_DEMO)
7036 } // namespace test310
7038 // test311: Yet another simple race. {{{1
7040 int *PTR = NULL; // GUARDED_BY(mu1)
7042 Mutex mu1; // Protects PTR.
7043 Mutex mu2; // Unrelated to PTR.
7044 Mutex mu3; // Unrelated to PTR.
7046 void GoodWriter1() {
7047 MutexLock lock3(&mu3); // This lock is unrelated to PTR.
7048 MutexLock lock1(&mu1); // Protect PTR.
7052 void GoodWriter2() {
7053 MutexLock lock2(&mu2); // This lock is unrelated to PTR.
7054 MutexLock lock1(&mu1); // Protect PTR.
7059 MutexLock lock1(&mu1); // Protect PTR.
7063 void BuggyWriter() {
7064 MutexLock lock2(&mu2); // Wrong mutex!
7068 // Some functions to make the stack trace non-trivial.
7069 void DoWrite1() { GoodWriter1(); }
7070 void Thread1() { DoWrite1(); }
7072 void DoWrite2() { GoodWriter2(); }
7073 void Thread2() { DoWrite2(); }
7075 void DoGoodRead() { GoodReader(); }
7076 void Thread3() { DoGoodRead(); }
7078 void DoBadWrite() { BuggyWriter(); }
7079 void Thread4() { DoBadWrite(); }
7082 printf("test311: simple race.\n");
7084 ANNOTATE_TRACE_MEMORY(PTR);
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");
7092 // t2 goes after t3. This way a pure happens-before detector has no chance.
7095 usleep(100000); // Let the good folks go first.
7103 REGISTER_TEST2(Run, 311, RACE_DEMO)
7104 } // namespace test311
7106 // test312: A test with a very deep stack. {{{1
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(); }
7131 printf("test312: simple race with deep stack.\n");
7132 MyThreadArray t(Worker, Worker, Worker);
7136 REGISTER_TEST2(Run, 312, RACE_DEMO)
7137 } // namespace test312
7139 // test313 TP: test for thread graph output {{{1
7141 BlockingCounter *blocking_counter;
7144 // Worker(N) will do 2^N increments of GLOB, each increment in a separate thread
7145 void Worker(int depth) {
7149 pool.StartWorkers();
7150 pool.Add(NewCallback(Worker, depth-1));
7151 pool.Add(NewCallback(Worker, depth-1));
7153 GLOB++; // Race here
7157 printf("test313: positive\n");
7159 printf("\tGLOB=%d\n", GLOB);
7161 REGISTER_TEST2(Run, 313, RACE_DEMO)
7162 } // namespace test313
7166 // test400: Demo of a simple false positive. {{{1
7169 static vector<int> *vec; // GUARDED_BY(mu);
7171 void InitAllBeforeStartingThreads() {
7172 vec = new vector<int>;
7178 MutexLock lock(&mu);
7183 MutexLock lock(&mu);
7187 //---- Sub-optimal code ---------
7188 size_t NumberOfElementsLeft() {
7189 MutexLock lock(&mu);
7193 void WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly() {
7194 while(NumberOfElementsLeft()) {
7195 ; // sleep or print or do nothing.
7197 // It is now safe to access vec w/o lock.
7198 // But a hybrid detector (like ThreadSanitizer) can't see it.
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());
7208 //----- Better code -----------
7210 bool NoElementsLeft(vector<int> *v) {
7214 void WaitForAllThreadsToFinish_Good() {
7215 mu.LockWhen(Condition(NoElementsLeft, vec));
7218 // It is now safe to access vec w/o lock.
7219 CHECK(vec->empty());
7225 MyThreadArray t(Thread1, Thread2);
7226 InitAllBeforeStartingThreads();
7228 WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly();
7229 // WaitForAllThreadsToFinish_Good();
7232 REGISTER_TEST2(Run, 400, RACE_DEMO)
7233 } // namespace test400
7235 // test401: Demo of false positive caused by reference counting. {{{1
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.
7241 static vector<int> *vec;
7242 static int ref_count;
7244 void InitAllBeforeStartingThreads(int number_of_threads) {
7245 vec = new vector<int>;
7247 ref_count = number_of_threads;
7250 // Correct, but unfriendly to race detectors.
7252 return AtomicIncrement(&ref_count, -1);
7255 // Correct and friendly to race detectors.
7256 int DecRefAnnotated() {
7257 ANNOTATE_CONDVAR_SIGNAL(&ref_count);
7258 int res = AtomicIncrement(&ref_count, -1);
7260 ANNOTATE_CONDVAR_WAIT(&ref_count);
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.
7276 MyThreadArray t(ThreadWorker, ThreadWorker, ThreadWorker);
7277 InitAllBeforeStartingThreads(3 /*number of threads*/);
7282 REGISTER_TEST2(Run, 401, RACE_DEMO)
7283 } // namespace test401
7285 // test501: Manually call PRINT_* annotations {{{1
7289 Mutex muCounter, muGlob[65];
7293 int myId = ++COUNTER;
7298 muGlob[myId].Lock();
7302 muGlob[myId].Unlock();
7306 MyThreadArray ta (Worker, Worker, Worker, Worker);
7313 MyThreadArray ta (Worker_1, Worker_1, Worker_1, Worker_1);
7320 ANNOTATE_RESET_STATS();
7321 printf("test501: Manually call PRINT_* annotations.\n");
7322 MyThreadArray ta (Worker_2, Worker_2, Worker_2, Worker_2);
7326 ANNOTATE_PRINT_MEMORY_USAGE(0);
7327 ANNOTATE_PRINT_STATS();
7330 REGISTER_TEST2(Run, 501, FEATURE | EXCLUDE_FROM_ALL)
7331 } // namespace test501
7333 // test502: produce lots of segments without cross-thread relations {{{1
7337 * This test produces ~1Gb of memory usage when run with the following options:
7340 * --trace-after-race=0
7349 for (int i = 0; i < 750000; i++) {
7357 MyThreadArray t(TP, TP);
7358 printf("test502: produce lots of segments without cross-thread relations\n");
7364 REGISTER_TEST2(Run, 502, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL
7366 } // namespace test502
7368 // test503: produce lots of segments with simple HB-relations {{{1
7369 // HB cache-miss rate is ~55%
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;
7396 int myId = AtomicIncrement(&count, 1);
7398 ProducerConsumerQueue &myQ = *Q[myId], &nextQ = *Q[(myId+1) % N_threads];
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++)
7405 if (myId == 0 && GLOB[0] > GLOB_limit) {
7407 for (int i = 0; i < N_threads; i++)
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);
7421 ThreadPool pool(N_threads);
7422 pool.StartWorkers();
7423 for (int i = 0; i < N_threads; i++) {
7424 pool.Add(NewCallback(Worker));
7426 } // all folks are joined here.
7428 for (int i = 0; i < N_threads; i++)
7432 REGISTER_TEST2(Run, 503, MEMORY_USAGE | PRINT_STATS
7433 | PERFORMANCE | EXCLUDE_FROM_ALL)
7434 } // namespace test503
7436 // test504: force massive cache fetch-wback (50% misses, mostly CacheLineZ) {{{1
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;
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,
7450 int array[ARRAY_SIZE];
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
7472 printf("test504: force massive CacheLineZ fetch-wback\n");
7473 MyThreadArray t(Worker, Worker);
7478 REGISTER_TEST2(Run, 504, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7479 } // namespace test504
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)
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;
7491 const int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
7493 int64_t array[ARRAY_SIZE];
7499 const int N_MUTEXES = 5;
7500 Mutex mu[N_MUTEXES];
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];
7513 for (int i = lower_bound + mutex_id, cnt = 0;
7515 i += HG_CACHELINE_SIZE / sizeof(array[0]), cnt++) {
7516 array[i] = i; // each array-write generates a cache miss
7523 printf("test505: force massive CacheLineF fetch-wback\n");
7524 MyThreadArray t(Worker, Worker);
7529 REGISTER_TEST2(Run, 505, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7530 } // namespace test505
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
7538 // Same as test17 but uses Barrier class (pthread_barrier_t).
7540 const int N_threads = 64,
7542 Barrier *barrier[ITERATIONS];
7546 for (int i = 0; i < ITERATIONS; i++) {
7550 barrier[i]->Block();
7554 printf("test506: massive HB's using Barriers\n");
7555 for (int i = 0; i < ITERATIONS; i++) {
7556 barrier[i] = new Barrier(N_threads);
7559 ThreadPool pool(N_threads);
7560 pool.StartWorkers();
7561 for (int i = 0; i < N_threads; i++) {
7562 pool.Add(NewCallback(Worker));
7564 } // all folks are joined here.
7565 CHECK(GLOB == N_threads * ITERATIONS);
7566 for (int i = 0; i < ITERATIONS; i++) {
7570 REGISTER_TEST2(Run, 506, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL);
7571 #endif // NO_BARRIER
7572 } // namespace test506
7574 // test507: vgHelgrind_initIterAtFM/stackClear benchmark {{{1
7575 // vgHelgrind_initIterAtFM/stackClear consume ~8.5%/5.5% CPU
7577 const int N_THREADS = 1,
7579 ITERATIONS = 1 << 20;
7585 ANNOTATE_RWLOCK_CREATE(&temp);
7588 ANNOTATE_RWLOCK_DESTROY(&temp);
7595 for (int j = 0; j < ITERATIONS; j++) {
7601 printf("test507: vgHelgrind_initIterAtFM/stackClear benchmark\n");
7603 ThreadPool pool(N_THREADS);
7604 pool.StartWorkers();
7605 for (int i = 0; i < N_THREADS; i++) {
7606 pool.Add(NewCallback(Worker));
7608 } // all folks are joined here.
7610 REGISTER_TEST2(Run, 507, EXCLUDE_FROM_ALL);
7611 } // namespace test507
7613 // test508: cmp_WordVecs_for_FM benchmark {{{1
7614 // 50+% of CPU consumption by cmp_WordVecs_for_FM
7616 const int N_THREADS = 1,
7617 BUFFER_SIZE = 1 << 10,
7618 ITERATIONS = 1 << 9;
7624 ANNOTATE_RWLOCK_CREATE(&temp);
7627 ANNOTATE_RWLOCK_DESTROY(&temp);
7634 for (int j = 0; j < ITERATIONS; j++) {
7640 printf("test508: cmp_WordVecs_for_FM benchmark\n");
7642 ThreadPool pool(N_THREADS);
7643 pool.StartWorkers();
7644 for (int i = 0; i < N_THREADS; i++) {
7645 pool.Add(NewCallback(Worker));
7647 } // all folks are joined here.
7649 REGISTER_TEST2(Run, 508, EXCLUDE_FROM_ALL);
7650 } // namespace test508
7652 // test509: avl_find_node benchmark {{{1
7653 // 10+% of CPU consumption by avl_find_node
7655 const int N_THREADS = 16,
7656 ITERATIONS = 1 << 8;
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);
7665 for (int i = ITERATIONS - 1; i >= 0; i--) {
7666 Mutex * mu = mu_list[i];
7673 printf("test509: avl_find_node benchmark\n");
7675 ThreadPool pool(N_THREADS);
7676 pool.StartWorkers();
7677 for (int i = 0; i < N_THREADS; i++) {
7678 pool.Add(NewCallback(Worker));
7680 } // all folks are joined here.
7682 REGISTER_TEST2(Run, 509, EXCLUDE_FROM_ALL);
7683 } // namespace test509
7685 // test510: SS-recycle test {{{1
7686 // this tests shows the case where only ~1% of SS are recycled
7688 const int N_THREADS = 16,
7689 ITERATIONS = 1 << 10;
7694 for (int i = 0; i < ITERATIONS; i++) {
7695 ANNOTATE_CONDVAR_SIGNAL((void*)0xDeadBeef);
7702 //ANNOTATE_BENIGN_RACE(&GLOB, "Test");
7703 printf("test510: SS-recycle test\n");
7705 ThreadPool pool(N_THREADS);
7706 pool.StartWorkers();
7707 for (int i = 0; i < N_THREADS; i++) {
7708 pool.Add(NewCallback(Worker));
7710 } // all folks are joined here.
7712 REGISTER_TEST2(Run, 510, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7713 } // namespace test510
7715 // test511: Segment refcounting test ('1' refcounting) {{{1
7720 for (int i = 0; i < 300; i++) {
7721 ANNOTATE_CONDVAR_SIGNAL(&GLOB);
7724 ANNOTATE_CONDVAR_WAIT(&GLOB);
7726 ANNOTATE_PRINT_MEMORY_USAGE(0);
7729 REGISTER_TEST2(Run, 511, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7730 } // namespace test511
7732 // test512: Segment refcounting test ('S' refcounting) {{{1
7738 sem_init(&SEM, 0, 0);
7739 for (int i = 0; i < 300; i++) {
7745 ANNOTATE_PRINT_MEMORY_USAGE(0);*/
7749 REGISTER_TEST2(Run, 512, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7750 } // namespace test512
7752 // test513: --fast-mode benchmark {{{1
7755 const int N_THREADS = 2,
7756 HG_CACHELINE_SIZE = 1 << 6,
7757 ARRAY_SIZE = HG_CACHELINE_SIZE * 512,
7759 MUTEX_ID_MASK = (1 << MUTEX_ID_BITS) - 1;
7761 // Each thread has its own cacheline and tackles with it intensively
7762 const int ITERATIONS = 1024;
7763 int array[N_THREADS][ARRAY_SIZE];
7767 Mutex mutex_arr[N_THREADS][MUTEX_ID_BITS];
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();
7781 for (int i = 0; i < ARRAY_SIZE; i++) {
7785 for (int m = 0; m < MUTEX_ID_BITS; m++)
7786 if (mutex_mask & (1 << m))
7787 mutex_arr[myId][m].Unlock();
7792 printf("test513: --fast-mode benchmark\n");
7794 ThreadPool pool(N_THREADS);
7795 pool.StartWorkers();
7796 for (int i = 0; i < N_THREADS; i++) {
7797 pool.Add(NewCallback(Worker));
7799 } // all folks are joined here.
7802 REGISTER_TEST2(Run, 513, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7803 } // namespace test513
7806 // vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker