tsan_barrier.h: New.
authorBernd Edlinger <bernd.edlinger@hotmail.de>
Thu, 8 Jan 2015 22:17:49 +0000 (22:17 +0000)
committerBernd Edlinger <edlinger@gcc.gnu.org>
Thu, 8 Jan 2015 22:17:49 +0000 (22:17 +0000)
2015-01-08  Bernd Edlinger  <bernd.edlinger@hotmail.de>

        * c-c++-common/tsan/tsan_barrier.h: New.
        * c-c++-common/tsan/atomic_stack.c: Reworked to not depend on sleep.
        * c-c++-common/tsan/bitfield_race.c: Likewise.
        * c-c++-common/tsan/fd_pipe_race.c: Likewise.
        * c-c++-common/tsan/mutexset1.c: Likewise.
        * c-c++-common/tsan/race_on_barrier.c: Likewise.
        * c-c++-common/tsan/race_on_mutex.c: Likewise.
        * c-c++-common/tsan/race_on_mutex2.c: Likewise.
        * c-c++-common/tsan/simple_race.c: Likewise.
        * c-c++-common/tsan/simple_stack.c: Likewise.
        * c-c++-common/tsan/sleep_sync.c: Likewise.
        * c-c++-common/tsan/tiny_race.c: Likewise.
        * c-c++-common/tsan/tls_race.c: Likewise.
        * c-c++-common/tsan/write_in_reader_lock.c: Likewise.
        * g++.dg/tsan/aligned_vs_unaligned_race.C: Likewise.
        * g++.dg/tsan/atomic_free.C: Likewise.
        * g++.dg/tsan/atomic_free2.C: Likewise.
        * g++.dg/tsan/cond_race.C: Likewise.
        * g++.dg/tsan/tsan_barrier.h: Copied from c-c++-common/tsan.

From-SVN: r219367

20 files changed:
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/tsan/atomic_stack.c
gcc/testsuite/c-c++-common/tsan/bitfield_race.c
gcc/testsuite/c-c++-common/tsan/fd_pipe_race.c
gcc/testsuite/c-c++-common/tsan/mutexset1.c
gcc/testsuite/c-c++-common/tsan/race_on_barrier.c
gcc/testsuite/c-c++-common/tsan/race_on_mutex.c
gcc/testsuite/c-c++-common/tsan/race_on_mutex2.c
gcc/testsuite/c-c++-common/tsan/simple_race.c
gcc/testsuite/c-c++-common/tsan/simple_stack.c
gcc/testsuite/c-c++-common/tsan/sleep_sync.c
gcc/testsuite/c-c++-common/tsan/tiny_race.c
gcc/testsuite/c-c++-common/tsan/tls_race.c
gcc/testsuite/c-c++-common/tsan/tsan_barrier.h [new file with mode: 0644]
gcc/testsuite/c-c++-common/tsan/write_in_reader_lock.c
gcc/testsuite/g++.dg/tsan/aligned_vs_unaligned_race.C
gcc/testsuite/g++.dg/tsan/atomic_free.C
gcc/testsuite/g++.dg/tsan/atomic_free2.C
gcc/testsuite/g++.dg/tsan/cond_race.C
gcc/testsuite/g++.dg/tsan/tsan_barrier.h [new file with mode: 0644]

index d7d9ac8c7f662bc6f00032d5e248db2f4e0759a2..bc1c52cd2d680345813926a2e80a6479a64fb72c 100644 (file)
@@ -1,3 +1,25 @@
+2015-01-08  Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       * c-c++-common/tsan/tsan_barrier.h: New.
+       * c-c++-common/tsan/atomic_stack.c: Reworked to not depend on sleep.
+       * c-c++-common/tsan/bitfield_race.c: Likewise.
+       * c-c++-common/tsan/fd_pipe_race.c: Likewise.
+       * c-c++-common/tsan/mutexset1.c: Likewise.
+       * c-c++-common/tsan/race_on_barrier.c: Likewise.
+       * c-c++-common/tsan/race_on_mutex.c: Likewise.
+       * c-c++-common/tsan/race_on_mutex2.c: Likewise.
+       * c-c++-common/tsan/simple_race.c: Likewise.
+       * c-c++-common/tsan/simple_stack.c: Likewise.
+       * c-c++-common/tsan/sleep_sync.c: Likewise.
+       * c-c++-common/tsan/tiny_race.c: Likewise.
+       * c-c++-common/tsan/tls_race.c: Likewise.
+       * c-c++-common/tsan/write_in_reader_lock.c: Likewise.
+       * g++.dg/tsan/aligned_vs_unaligned_race.C: Likewise.
+       * g++.dg/tsan/atomic_free.C: Likewise.
+       * g++.dg/tsan/atomic_free2.C: Likewise.
+       * g++.dg/tsan/cond_race.C: Likewise.
+       * g++.dg/tsan/tsan_barrier.h: Copied from c-c++-common/tsan. 
+
 2015-01-08  Hans-Peter Nilsson  <hp@axis.com>
 
        PR testsuite/62250
index 6a37951201015a086354415af667b387d349fce1..746afa7b4664a07d84e70d6eac107246c7d3fba0 100644 (file)
@@ -1,22 +1,26 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <unistd.h>
+#include "tsan_barrier.h"
 
+static pthread_barrier_t barrier;
 int Global;
 
 void *Thread1(void *x) {
-  sleep(1);
+  barrier_wait(&barrier);
   __atomic_fetch_add(&Global, 1, __ATOMIC_RELAXED);
   return NULL;
 }
 
 void *Thread2(void *x) {
   Global++;
+  barrier_wait(&barrier);
   return NULL;
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   pthread_t t[2];
   pthread_create(&t[0], NULL, Thread1, NULL);
   pthread_create(&t[1], NULL, Thread2, NULL);
index e8de09727a93995ceef22117aca3610831f9e912..42681157799a5a4571c687bed91acf0531a036f7 100644 (file)
@@ -1,8 +1,10 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <unistd.h>
+#include "tsan_barrier.h"
 
+static pthread_barrier_t barrier;
 struct bitfield
 {
   int a:10;
@@ -10,15 +12,17 @@ struct bitfield
 } Global;
 
 void *Thread1(void *x) {
-  sleep(1);
+  barrier_wait(&barrier);
   Global.a = 42;
   return x;
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   pthread_t t;
   pthread_create(&t, 0, Thread1, 0);
   Global.b = 43;
+  barrier_wait(&barrier);
   pthread_join(t, 0);
   return Global.a;
 }
index 28cd630d2c1a1ee2ad1be9db16144fb030aea8a0..e2176da4b628dee2704b07239b49a8d9453a8cec 100644 (file)
@@ -1,30 +1,35 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <stdio.h>
 #include <unistd.h>
+#include "tsan_barrier.h"
 
+static pthread_barrier_t barrier;
 int fds[2];
 
 void *Thread1(void *x) {
   write(fds[1], "a", 1);
+  barrier_wait(&barrier);
   return NULL;
 }
 
 void *Thread2(void *x) {
-  sleep(1);
+  barrier_wait(&barrier);
   close(fds[0]);
   close(fds[1]);
   return NULL;
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   pipe(fds);
   pthread_t t[2];
   pthread_create(&t[0], NULL, Thread1, NULL);
   pthread_create(&t[1], NULL, Thread2, NULL);
   pthread_join(t[0], NULL);
   pthread_join(t[1], NULL);
+  return 0;
 }
 
 /* { dg-output "WARNING: ThreadSanitizer: data race.*\n" } */
index d27f7c817cbd4225f52a35b8a4da1d8b349b7cd4..3462ec457d6184ab44e317a715cfc60c7e3e0e42 100644 (file)
@@ -1,14 +1,15 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <stdio.h>
-#include <unistd.h>
+#include "tsan_barrier.h"
 
+static pthread_barrier_t barrier;
 int Global;
 pthread_mutex_t mtx;
 
 void *Thread1(void *x) {
-  sleep(1);
+  barrier_wait(&barrier);
   pthread_mutex_lock(&mtx);
   Global++;
   pthread_mutex_unlock(&mtx);
@@ -17,11 +18,13 @@ void *Thread1(void *x) {
 
 void *Thread2(void *x) {
   Global--;
+  barrier_wait(&barrier);
   return NULL;/* { dg-output ".*" } */
 
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   pthread_mutex_init(&mtx, 0);
   pthread_t t[2];
   pthread_create(&t[0], NULL, Thread1, NULL);
index 0a0e5faba02612d633cc0d53b0a111f98e46b219..3de3ff2257fa0d0f500de42998e382c1009a63b1 100644 (file)
@@ -1,26 +1,28 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <unistd.h>
+#include "tsan_barrier.h"
 
+static pthread_barrier_t barrier;
 pthread_barrier_t B;
 int Global;
 
 void *Thread1(void *x) {
   pthread_barrier_init(&B, 0, 2);
+  barrier_wait(&barrier);
   pthread_barrier_wait(&B);
   return NULL;
 }
 
 void *Thread2(void *x) {
-  sleep(1);
+  barrier_wait(&barrier);
   pthread_barrier_wait(&B);
   return NULL;
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   pthread_t t;
   pthread_create(&t, NULL, Thread1, NULL);
   Thread2(0);
index 5dad345d85b46608d1387be267bd11699bc55c5b..ae30d053c92a95cee8ef48fd9689e241d597598f 100644 (file)
@@ -1,10 +1,10 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <unistd.h>
+#include "tsan_barrier.h"
 
+static pthread_barrier_t barrier;
 pthread_mutex_t Mtx;
 int Global;
 
@@ -13,11 +13,12 @@ void *Thread1(void *x) {
   pthread_mutex_lock(&Mtx);
   Global = 42;
   pthread_mutex_unlock(&Mtx);
+  barrier_wait(&barrier);
   return NULL;
 }
 
 void *Thread2(void *x) {
-  sleep(1);
+  barrier_wait(&barrier);
   pthread_mutex_lock(&Mtx);
   Global = 43;
   pthread_mutex_unlock(&Mtx);
@@ -25,6 +26,7 @@ void *Thread2(void *x) {
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   pthread_t t[2];
   pthread_create(&t[0], NULL, Thread1, NULL);
   pthread_create(&t[1], NULL, Thread2, NULL);
@@ -37,7 +39,7 @@ int main() {
 /* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */
 /* { dg-output "  Atomic read of size 1 at .* by thread T2:(\n|\r\n|\r)" } */
 /* { dg-output "    #0 pthread_mutex_lock.*" } */
-/* { dg-output "    #1 Thread2.* .*(race_on_mutex.c:21|\\?{2}:0) (.*)" } */
+/* { dg-output "    #1 Thread2.* .*(race_on_mutex.c:22|\\?{2}:0) (.*)" } */
 /* { dg-output "  Previous write of size 1 at .* by thread T1:(\n|\r\n|\r)" } */
 /* { dg-output "    #0 pthread_mutex_init .* (.)*" } */
 /* { dg-output "    #1 Thread1.* .*(race_on_mutex.c:12|\\?{2}:0) .*" } */
index 80a6fb6c0eba5822eda578c7ea3bc78814eada8f..57d7e21e76a53ccc1dde57ecac7744620cb7ecea 100644 (file)
@@ -1,22 +1,25 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <unistd.h>
+#include "tsan_barrier.h"
+
+static pthread_barrier_t barrier;
 
 void *Thread(void *x) {
   pthread_mutex_lock((pthread_mutex_t*)x);
   pthread_mutex_unlock((pthread_mutex_t*)x);
+  barrier_wait(&barrier);
   return 0;
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   pthread_mutex_t Mtx;
   pthread_mutex_init(&Mtx, 0);
   pthread_t t;
   pthread_create(&t, 0, Thread, &Mtx);
-  sleep(1);
+  barrier_wait(&barrier);
   pthread_mutex_destroy(&Mtx);
   pthread_join(t, 0);
   return 0;
index a40accd40a25e826b31807ceb964ffe75b7a6a8c..c1a369b459071a8fdd5254033e81ba2523613841 100644 (file)
@@ -1,13 +1,15 @@
 /* { dg-set-target-env-var TSAN_OPTIONS "halt_on_error=1" } */
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <stdio.h>
 #include <unistd.h>
+#include "tsan_barrier.h"
 
-#define MAX_ITERATIONS_NUMBER 100
-#define SLEEP_STEP 128000 
+#define MAX_ITERATIONS_NUMBER 1
+#define SLEEP_STEP 128000
 
+static pthread_barrier_t barrier;
 unsigned int delay_time = 1000;
 
 static inline void delay () {
@@ -17,6 +19,7 @@ static inline void delay () {
 extern int main_1();
 
 int main() {
+  barrier_init(&barrier, 2);
   int i;
   for (i = 0; i < MAX_ITERATIONS_NUMBER; i++) {
     main_1();
@@ -28,6 +31,7 @@ int main() {
 int Global;
 
 void *Thread1(void *x) {
+  barrier_wait(&barrier);
   delay();
   Global = 42;
   return NULL;
@@ -35,6 +39,7 @@ void *Thread1(void *x) {
 
 void *Thread2(void *x) {
   Global = 43;
+  barrier_wait(&barrier);
   return NULL;
 }
 
index b66a67085ca6547fa0eb3abc30e11c4b0036c921..a4d0aba69287572bfe170e2618d1f779cadeb244 100644 (file)
@@ -1,9 +1,10 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <stdio.h>
-#include <unistd.h>
+#include "tsan_barrier.h"
 
+static pthread_barrier_t barrier;
 int Global;
 
 void __attribute__((noinline)) foo1() {
@@ -25,13 +26,14 @@ void __attribute__((noinline)) bar2() {
 }
 
 void *Thread1(void *x) {
-  sleep(1);
+  barrier_wait(&barrier);
   bar1();
   return NULL;
 }
 
 void *Thread2(void *x) {
   bar2();
+  barrier_wait(&barrier);
   return NULL;
 }
 
@@ -40,6 +42,7 @@ void StartThread(pthread_t *t, void *(*f)(void*)) {
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   pthread_t t[2];
   StartThread(&t[0], Thread1);
   StartThread(&t[1], Thread2);
@@ -50,16 +53,16 @@ int main() {
 
 /* { dg-output "WARNING: ThreadSanitizer: data race.*" } */
 /* { dg-output "  Write of size 4 at .* by thread T1:(\n|\r\n|\r)" } */
-/* { dg-output "    #0 foo1.* .*(simple_stack.c:10|\\?{2}:0) (.*)" } */
-/* { dg-output "    #1 bar1.* .*(simple_stack.c:15|\\?{2}:0) (.*)" } */
-/* { dg-output "    #2 Thread1.* .*(simple_stack.c:29|\\?{2}:0) (.*)" } */
+/* { dg-output "    #0 foo1.* .*(simple_stack.c:11|\\?{2}:0) (.*)" } */
+/* { dg-output "    #1 bar1.* .*(simple_stack.c:16|\\?{2}:0) (.*)" } */
+/* { dg-output "    #2 Thread1.* .*(simple_stack.c:30|\\?{2}:0) (.*)" } */
 /* { dg-output "  Previous read of size 4 at .* by thread T2:(\n|\r\n|\r)" } */
-/* { dg-output "    #0 foo2.* .*(simple_stack.c:19|\\?{2}:0) (.*)" } */
-/* { dg-output "    #1 bar2.* .*(simple_stack.c:24|\\?{2}:0) (.*)" } */
-/* { dg-output "    #2 Thread2.* .*(simple_stack.c:34|\\?{2}:0) (.*)" } */
+/* { dg-output "    #0 foo2.* .*(simple_stack.c:20|\\?{2}:0) (.*)" } */
+/* { dg-output "    #1 bar2.* .*(simple_stack.c:25|\\?{2}:0) (.*)" } */
+/* { dg-output "    #2 Thread2.* .*(simple_stack.c:35|\\?{2}:0) (.*)" } */
 /* { dg-output "  Thread T1 \\(tid=.*, running\\) created by main thread at:(\n|\r\n|\r)" } */
 /* { dg-output "    #0 pthread_create .* (.*)" } */
-/* { dg-output "    #1 StartThread.* .*(simple_stack.c:39|\\?{2}:0) (.*)" } */
+/* { dg-output "    #1 StartThread.* .*(simple_stack.c:41|\\?{2}:0) (.*)" } */
 /* { dg-output "  Thread T2 (.*) created by main thread at:(\n|\r\n|\r)" } */
 /* { dg-output "    #0 pthread_create .* (.*)" } */
-/* { dg-output "    #1 StartThread.* .*(simple_stack.c:39|\\?{2}:0) (.*)" } */
+/* { dg-output "    #1 StartThread.* .*(simple_stack.c:41|\\?{2}:0) (.*)" } */
index 44d44554c2ec74eb4abc5d026164c2cb424dfa87..c681dcef1bfd41612127674350992bd671ec2294 100644 (file)
@@ -1,8 +1,11 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
 #include <unistd.h>
+#include "tsan_barrier.h"
 
+static pthread_barrier_t barrier;
 int X = 0;
 
 void MySleep() {
@@ -10,15 +13,18 @@ void MySleep() {
 }
 
 void *Thread(void *p) {
+  barrier_wait(&barrier);
   MySleep();  // Assume the main thread has done the write.
   X = 42;
   return 0;
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   pthread_t t;
   pthread_create(&t, 0, Thread, 0);
   X = 43;
+  barrier_wait(&barrier);
   pthread_join(t, 0);
   return 0;
 }
index 962497b2821e0c99c928e8a3b57db92acf0ae21f..10a3feb9b334eeb553a45f9ebe6bd9c5e117e5df 100644 (file)
@@ -1,20 +1,24 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <unistd.h>
+#include "tsan_barrier.h"
 
+static pthread_barrier_t barrier;
 int Global;
 
 void *Thread1(void *x) {
-  sleep(1);
+  barrier_wait(&barrier);
   Global = 42;
   return x;
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   pthread_t t;
   pthread_create(&t, 0, Thread1, 0);
   Global = 43;
+  barrier_wait(&barrier);
   pthread_join(t, 0);
   return Global;
 }
index 423867e382d1305ae46a7fb9d681fa30422e9724..4dd6506043e17a0f2bf8d9708051357bddccd426 100644 (file)
@@ -1,18 +1,24 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <stddef.h>
+#include "tsan_barrier.h"
+
+static pthread_barrier_t barrier;
 
 void *Thread(void *a) {
+  barrier_wait(&barrier);
   *(int*)a = 43;
   return 0;
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   static __thread int Var = 42;
   pthread_t t;
   pthread_create(&t, 0, Thread, &Var);
   Var = 43;
+  barrier_wait(&barrier);
   pthread_join(t, 0);
 }
 
diff --git a/gcc/testsuite/c-c++-common/tsan/tsan_barrier.h b/gcc/testsuite/c-c++-common/tsan/tsan_barrier.h
new file mode 100644 (file)
index 0000000..5d37a64
--- /dev/null
@@ -0,0 +1,14 @@
+/* TSAN-invisible barriers.  Link with -ldl.  */
+#include <pthread.h>
+#include <dlfcn.h>
+
+static __typeof(pthread_barrier_wait) *barrier_wait;
+
+static
+void barrier_init (pthread_barrier_t *barrier, unsigned count)
+{
+  void *h = dlopen ("libpthread.so.0", RTLD_LAZY);
+  barrier_wait = (__typeof (pthread_barrier_wait) *)
+                dlsym (h, "pthread_barrier_wait");
+  pthread_barrier_init (barrier, NULL, count);
+}
index 898d23d50b74c8dccc7e80f1c3a227766b202731..df32632bfeaa291a7e0898a882b52efdb1f24433 100644 (file)
@@ -1,8 +1,10 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <unistd.h>
+#include "tsan_barrier.h"
 
+static pthread_barrier_t barrier;
 pthread_rwlock_t rwlock;
 int GLOB;
 
@@ -10,13 +12,14 @@ void *Thread1(void *p) {
  (void)p;
   pthread_rwlock_rdlock(&rwlock);
   // Write under reader lock.
-  sleep(1);
+  barrier_wait(&barrier);
   GLOB++;
   pthread_rwlock_unlock(&rwlock);
   return 0;
 }
 
 int main(int argc, char *argv[]) {
+  barrier_init(&barrier, 2);
   pthread_rwlock_init(&rwlock, NULL);
   pthread_rwlock_rdlock(&rwlock);
   pthread_t t;
@@ -24,6 +27,7 @@ int main(int argc, char *argv[]) {
   volatile int x = GLOB;
  (void)x;
   pthread_rwlock_unlock(&rwlock);
+  barrier_wait(&barrier);
   pthread_join(t, 0);
   pthread_rwlock_destroy(&rwlock);
   return 0;
index e547e0ce2d2d9169f42335515df7811e3c8364d0..1facadc87dd1f34f9ba5ae59e4d2a69bfe2a4366 100644 (file)
@@ -1,11 +1,16 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
+
 #include <pthread.h>
 #include <stdio.h>
 #include <stdint.h>
+#include "tsan_barrier.h"
 
+static pthread_barrier_t barrier;
 uint64_t Global[2];
 
 void *Thread1(void *x) {
+  barrier_wait(&barrier);
   Global[1]++;
   return NULL;
 }
@@ -15,10 +20,12 @@ void *Thread2(void *x) {
   struct __attribute__((packed, aligned(1))) u_uint64_t { uint64_t val; };
   u_uint64_t *p4 = reinterpret_cast<u_uint64_t *>(p1 + 1);
   (*p4).val++;
+  barrier_wait(&barrier);
   return NULL;
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   pthread_t t[2];
   pthread_create(&t[0], NULL, Thread1, NULL);
   pthread_create(&t[1], NULL, Thread2, NULL);
index 26d01ae3fddc0d31d331a71d91fe30500d1ac613..20429f159b870b04514c41258f43205cfe2e9688 100644 (file)
@@ -1,18 +1,23 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <unistd.h>
+#include "tsan_barrier.h"
+
+static pthread_barrier_t barrier;
 
 void *Thread(void *a) {
   __atomic_fetch_add((int*)a, 1, __ATOMIC_SEQ_CST);
+  barrier_wait(&barrier);
   return 0;
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   int *a = new int(0);
   pthread_t t;
   pthread_create(&t, 0, Thread, a);
-  sleep(1);
+  barrier_wait(&barrier);
   delete a;
   pthread_join(t, 0);
 }
index 1fe512cde93cea22ebaaba3fdc740fc548e7b255..3b6a8e3af9966c85ea04d762f5d36e68edfecd2e 100644 (file)
@@ -1,19 +1,24 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 
 #include <pthread.h>
-#include <unistd.h>
+#include "tsan_barrier.h"
+
+static pthread_barrier_t barrier;
 
 void *Thread(void *a) {
-  sleep(1);
+  barrier_wait(&barrier);
   __atomic_fetch_add((int*)a, 1, __ATOMIC_SEQ_CST);
   return 0;
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   int *a = new int(0);
   pthread_t t;
   pthread_create(&t, 0, Thread, a);
   delete a;
+  barrier_wait(&barrier);
   pthread_join(t, 0);
 }
 
index a9376147763b422610749df423c625e3a9bffbdf..d72d0fb54f60f87a34d9fe2645f597163bf5a79b 100644 (file)
@@ -1,10 +1,12 @@
 /* { dg-shouldfail "tsan" } */
+/* { dg-additional-options "-ldl" } */
 /* { dg-output "ThreadSanitizer: data race.*" } */
 /* { dg-output "pthread_cond_signal.*" } */
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <pthread.h>
+#include "tsan_barrier.h"
+
+static pthread_barrier_t barrier;
 
 struct Ctx {
   pthread_mutex_t m;
@@ -18,10 +20,12 @@ void *thr(void *p) {
   c->done = true;
   pthread_mutex_unlock(&c->m);
   pthread_cond_signal(&c->c);
+  barrier_wait(&barrier);
   return 0;
 }
 
 int main() {
+  barrier_init(&barrier, 2);
   Ctx *c = new Ctx();
   pthread_mutex_init(&c->m, 0);
   pthread_cond_init(&c->c, 0);
@@ -31,6 +35,7 @@ int main() {
   while (!c->done)
     pthread_cond_wait(&c->c, &c->m);
   pthread_mutex_unlock(&c->m);
+  barrier_wait(&barrier);
   delete c;
   pthread_join(th, 0);
 }
diff --git a/gcc/testsuite/g++.dg/tsan/tsan_barrier.h b/gcc/testsuite/g++.dg/tsan/tsan_barrier.h
new file mode 100644 (file)
index 0000000..5d37a64
--- /dev/null
@@ -0,0 +1,14 @@
+/* TSAN-invisible barriers.  Link with -ldl.  */
+#include <pthread.h>
+#include <dlfcn.h>
+
+static __typeof(pthread_barrier_wait) *barrier_wait;
+
+static
+void barrier_init (pthread_barrier_t *barrier, unsigned count)
+{
+  void *h = dlopen ("libpthread.so.0", RTLD_LAZY);
+  barrier_wait = (__typeof (pthread_barrier_wait) *)
+                dlsym (h, "pthread_barrier_wait");
+  pthread_barrier_init (barrier, NULL, count);
+}