[NFC][TSan] Move libdispatch tests into their own subfolder
authorJulian Lettner <jlettner@apple.com>
Thu, 14 Mar 2019 20:59:41 +0000 (20:59 +0000)
committerJulian Lettner <jlettner@apple.com>
Thu, 14 Mar 2019 20:59:41 +0000 (20:59 +0000)
Remove 'gcd' file prefix. GCD stands for Grand Central Dispatch, which
is another name for libdispatch.
https://apple.github.io/swift-corelibs-libdispatch/

Remove `REQUIRE: dispatch` from tests.

Also rename lit feature 'dispatch' -> 'libdispatch' to be more explicit
what this is about.

Reviewed By: kubamracek

Differential Revision: https://reviews.llvm.org/D59341

llvm-svn: 356202

26 files changed:
compiler-rt/test/lit.common.cfg
compiler-rt/test/tsan/gcd-apply-race.c [deleted file]
compiler-rt/test/tsan/gcd-apply.c [deleted file]
compiler-rt/test/tsan/gcd-data.c [deleted file]
compiler-rt/test/tsan/gcd-dispatch_main.c [deleted file]
compiler-rt/test/tsan/gcd-dispatch_once_deadlock.c [deleted file]
compiler-rt/test/tsan/gcd-groups-destructor.c [deleted file]
compiler-rt/test/tsan/gcd-groups-leave.c [deleted file]
compiler-rt/test/tsan/gcd-groups-stress.c [deleted file]
compiler-rt/test/tsan/gcd-once.c [deleted file]
compiler-rt/test/tsan/gcd-semaphore-norace.c [deleted file]
compiler-rt/test/tsan/gcd-source-serial.c [deleted file]
compiler-rt/test/tsan/gcd-suspend.c [deleted file]
compiler-rt/test/tsan/libdispatch/apply-race.c [new file with mode: 0644]
compiler-rt/test/tsan/libdispatch/apply.c [new file with mode: 0644]
compiler-rt/test/tsan/libdispatch/data.c [new file with mode: 0644]
compiler-rt/test/tsan/libdispatch/dispatch_main.c [new file with mode: 0644]
compiler-rt/test/tsan/libdispatch/dispatch_once_deadlock.c [new file with mode: 0644]
compiler-rt/test/tsan/libdispatch/groups-destructor.c [new file with mode: 0644]
compiler-rt/test/tsan/libdispatch/groups-leave.c [new file with mode: 0644]
compiler-rt/test/tsan/libdispatch/groups-stress.c [new file with mode: 0644]
compiler-rt/test/tsan/libdispatch/lit.local.cfg [new file with mode: 0644]
compiler-rt/test/tsan/libdispatch/once.c [new file with mode: 0644]
compiler-rt/test/tsan/libdispatch/semaphore-norace.c [new file with mode: 0644]
compiler-rt/test/tsan/libdispatch/source-serial.c [new file with mode: 0644]
compiler-rt/test/tsan/libdispatch/suspend.c [new file with mode: 0644]

index 1f67e5a2b0c9d9160cdf5e206265b0dade7a6698..37132c3d07cf70582785c9822c48b8c9c06a56a5 100644 (file)
@@ -222,9 +222,9 @@ compiler_rt_debug = getattr(config, 'compiler_rt_debug', False)
 if not compiler_rt_debug:
   config.available_features.add('compiler-rt-optimized')
 
-dispatch = getattr(config, 'compiler_rt_intercept_libdispatch')
-if dispatch:
-  config.available_features.add('dispatch')
+libdispatch = getattr(config, 'compiler_rt_intercept_libdispatch')
+if libdispatch:
+  config.available_features.add('libdispatch')
 
 sanitizer_can_use_cxxabi = getattr(config, 'sanitizer_can_use_cxxabi', True)
 if sanitizer_can_use_cxxabi:
diff --git a/compiler-rt/test/tsan/gcd-apply-race.c b/compiler-rt/test/tsan/gcd-apply-race.c
deleted file mode 100644 (file)
index bfdf998..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// RUN: %clang_tsan %s -o %t
-// RUN: %deflake %run %t 2>&1 | FileCheck %s
-
-// REQUIRES: dispatch
-
-#include <dispatch/dispatch.h>
-
-#include "test.h"
-
-long global;
-
-int main(int argc, const char *argv[]) {
-  barrier_init(&barrier, 2);
-  fprintf(stderr, "start\n");
-
-  // Warm up GCD (workaround for macOS Sierra where dispatch_apply might run single-threaded).
-  dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ });
-
-  dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT);
-  dispatch_apply(2, q, ^(size_t i) {
-    global = i;
-    barrier_wait(&barrier);
-  });
-
-  fprintf(stderr, "done\n");
-  return 0;
-}
-
-// CHECK: start
-// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK: Location is global 'global'
-// CHECK: done
diff --git a/compiler-rt/test/tsan/gcd-apply.c b/compiler-rt/test/tsan/gcd-apply.c
deleted file mode 100644 (file)
index 90dc359..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-// RUN: %clang_tsan %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
-
-// REQUIRES: dispatch
-
-// TODO(yln): Deadlocks while gcd-apply.mm does not. What's the difference
-//            between C and Obj-C compiler?
-// REQUIRES: disable
-
-#include <dispatch/dispatch.h>
-
-#include "test.h"
-
-long global;
-long array[2];
-
-void callback(void *context, size_t i) {
-  long n = global;
-  array[i] = n + i;
-  barrier_wait(&barrier);
-}
-
-int main(int argc, const char *argv[]) {
-  barrier_init(&barrier, 2);
-  fprintf(stderr, "start\n");
-
-  // Warm up GCD (workaround for macOS Sierra where dispatch_apply might run single-threaded).
-  dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ });
-
-  dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT);
-
-  global = 42;
-
-  dispatch_apply(100, q, ^(size_t i) {
-    long n = global;
-    array[i] = n + i;
-    barrier_wait(&barrier);
-  });
-
-  for (int i = 0; i < 100; i++) {
-    fprintf(stderr, "array[%d] = %ld\n", i, array[i]);
-  }
-
-  global = 43;
-
-  dispatch_apply_f(100, q, NULL, &callback);
-
-  fprintf(stderr, "done\n");
-  return 0;
-}
-
-// CHECK: start
-// CHECK: done
-// CHECK-NOT: WARNING: ThreadSanitizer
diff --git a/compiler-rt/test/tsan/gcd-data.c b/compiler-rt/test/tsan/gcd-data.c
deleted file mode 100644 (file)
index 87dd2d9..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// RUN: %clang_tsan %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
-
-// REQUIRES: dispatch
-
-// TODO(yln): fails on one of our bots, need to investigate
-// REQUIRES: disabled
-
-#include <dispatch/dispatch.h>
-
-#include <stdio.h>
-
-long global;
-
-int main(int argc, const char *argv[]) {
-  fprintf(stderr, "Hello world.\n");
-
-  dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_SERIAL);
-  dispatch_semaphore_t sem = dispatch_semaphore_create(0);
-
-  global = 44;
-  dispatch_data_t data = dispatch_data_create("buffer", 6, q, ^{
-    fprintf(stderr, "Data destructor.\n");
-    global++;
-
-    dispatch_semaphore_signal(sem);
-  });
-  dispatch_release(data);
-  data = NULL;
-
-  dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
-
-  data = dispatch_data_create("buffer", 6, q, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
-  dispatch_release(data);
-  data = NULL;
-
-  fprintf(stderr, "Done.\n");
-}
-
-// CHECK: Hello world.
-// CHECK: Data destructor.
-// CHECK-NOT: WARNING: ThreadSanitizer
-// CHECK: Done.
diff --git a/compiler-rt/test/tsan/gcd-dispatch_main.c b/compiler-rt/test/tsan/gcd-dispatch_main.c
deleted file mode 100644 (file)
index 2023ba0..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// Check that we don't crash when dispatch_main calls pthread_exit which
-// quits the main thread.
-
-// RUN: %clang_tsan %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
-
-// REQUIRES: dispatch
-
-#include <dispatch/dispatch.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-
-int main() {
-  fprintf(stderr,"Hello world");
-
-  dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_SERIAL);
-
-  dispatch_async(q, ^{
-    fprintf(stderr,"1");
-  });
-
-  dispatch_async(q, ^{
-    fprintf(stderr,"2");
-  });
-
-  dispatch_async(q, ^{
-    fprintf(stderr,"3");
-
-    dispatch_async(dispatch_get_main_queue(), ^{
-      fprintf(stderr,"Done.");
-      sleep(1);
-      exit(0);
-    });
-  });
-
-  dispatch_main();
-}
-
-// CHECK: Hello world
-// CHECK: Done.
-// CHECK-NOT: WARNING: ThreadSanitizer
-// CHECK-NOT: CHECK failed
diff --git a/compiler-rt/test/tsan/gcd-dispatch_once_deadlock.c b/compiler-rt/test/tsan/gcd-dispatch_once_deadlock.c
deleted file mode 100644 (file)
index fd2cdc5..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-// Check that calling dispatch_once from a report callback works.
-
-// RUN: %clang_tsan %s -o %t
-// RUN: not %run %t 2>&1 | FileCheck %s
-
-// REQUIRES: dispatch
-
-#include <dispatch/dispatch.h>
-
-#include <pthread.h>
-#include <stdio.h>
-
-long g = 0;
-long h = 0;
-void f() {
-  static dispatch_once_t onceToken;
-  dispatch_once(&onceToken, ^{
-    g++;
-  });
-  h++;
-}
-
-void __tsan_on_report() {
-  fprintf(stderr, "Report.\n");
-  f();
-}
-
-int main() {
-  fprintf(stderr, "Hello world.\n");
-
-  f();
-
-  pthread_mutex_t mutex = {0};
-  pthread_mutex_lock(&mutex);
-
-  fprintf(stderr, "g = %ld.\n", g);
-  fprintf(stderr, "h = %ld.\n", h);
-  fprintf(stderr, "Done.\n");
-}
-
-// CHECK: Hello world.
-// CHECK: Report.
-// CHECK: g = 1
-// CHECK: h = 2
-// CHECK: Done.
diff --git a/compiler-rt/test/tsan/gcd-groups-destructor.c b/compiler-rt/test/tsan/gcd-groups-destructor.c
deleted file mode 100644 (file)
index a2c7eac..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-// RUN: %clangxx_tsan %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
-
-// REQUIRES: dispatch
-
-#include <dispatch/dispatch.h>
-
-#import <memory>
-#import <stdatomic.h>
-
-_Atomic(long) destructor_counter = 0;
-
-struct MyStruct {
-  virtual ~MyStruct() {
-    usleep(10000);
-    atomic_fetch_add_explicit(&destructor_counter, 1, memory_order_relaxed);
-  }
-};
-
-int main(int argc, const char *argv[]) {
-  fprintf(stderr, "Hello world.\n");
-
-  dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
-  dispatch_group_t g = dispatch_group_create();
-
-  for (int i = 0; i < 100; i++) {
-    std::shared_ptr<MyStruct> shared(new MyStruct());
-
-    dispatch_group_async(g, q, ^{
-      shared.get(); // just to make sure the object is captured by the block
-    });
-  }
-
-  dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
-
-  if (destructor_counter != 100) {
-    abort();
-  }
-
-  fprintf(stderr, "Done.\n");
-}
-
-// CHECK: Hello world.
-// CHECK-NOT: WARNING: ThreadSanitizer
-// CHECK: Done.
diff --git a/compiler-rt/test/tsan/gcd-groups-leave.c b/compiler-rt/test/tsan/gcd-groups-leave.c
deleted file mode 100644 (file)
index d51edcf..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-// RUN: %clang_tsan %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
-
-// REQUIRES: dispatch
-
-#include <dispatch/dispatch.h>
-
-#include "test.h"
-
-dispatch_semaphore_t sem;
-
-long global;
-long global2;
-
-void callback(void *context) {
-  global2 = 48;
-  barrier_wait(&barrier);
-
-  dispatch_semaphore_signal(sem);
-}
-
-int main() {
-  fprintf(stderr, "Hello world.\n");
-  barrier_init(&barrier, 2);
-
-  dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT);
-  dispatch_group_t g = dispatch_group_create();
-  sem = dispatch_semaphore_create(0);
-
-  dispatch_group_enter(g);
-  dispatch_async(q, ^{
-    global = 47;
-    dispatch_group_leave(g);
-    barrier_wait(&barrier);
-  });
-  dispatch_group_notify(g, q, ^{
-    global = 48;
-    barrier_wait(&barrier);
-
-    dispatch_semaphore_signal(sem);
-  });
-  dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
-
-  dispatch_group_enter(g);
-  dispatch_async(q, ^{
-    global2 = 47;
-    dispatch_group_leave(g);
-    barrier_wait(&barrier);
-  });
-  dispatch_group_notify_f(g, q, NULL, &callback);
-  dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
-
-  fprintf(stderr, "Done.\n");
-}
-
-// CHECK: Hello world.
-// CHECK-NOT: WARNING: ThreadSanitizer
-// CHECK: Done.
diff --git a/compiler-rt/test/tsan/gcd-groups-stress.c b/compiler-rt/test/tsan/gcd-groups-stress.c
deleted file mode 100644 (file)
index 0ae373c..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// RUN: %clang_tsan %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
-
-// REQUIRES: dispatch
-
-#include <dispatch/dispatch.h>
-
-#include <stdio.h>
-
-void notify_callback(void *context) {
-  // Do nothing.
-}
-
-int main() {
-  fprintf(stderr, "Hello world.");
-
-  dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
-
-  for (int i = 0; i < 300000; i++) {
-    dispatch_group_t g = dispatch_group_create();
-    dispatch_group_enter(g);
-    dispatch_async(q, ^{
-      dispatch_group_leave(g);
-    });
-    dispatch_group_notify(g, q, ^{
-      // Do nothing.
-    });
-    dispatch_release(g);
-  }
-
-  for (int i = 0; i < 300000; i++) {
-    dispatch_group_t g = dispatch_group_create();
-    dispatch_group_enter(g);
-    dispatch_async(q, ^{
-      dispatch_group_leave(g);
-    });
-    dispatch_group_notify_f(g, q, NULL, &notify_callback);
-    dispatch_release(g);
-  }
-
-  fprintf(stderr, "Done.");
-}
-
-// CHECK: Hello world.
-// CHECK: Done.
-// CHECK-NOT: WARNING: ThreadSanitizer
-// CHECK-NOT: CHECK failed
diff --git a/compiler-rt/test/tsan/gcd-once.c b/compiler-rt/test/tsan/gcd-once.c
deleted file mode 100644 (file)
index 5a62c42..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// RUN: %clang_tsan %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
-
-// REQUIRES: dispatch
-
-#include <dispatch/dispatch.h>
-
-#include "test.h"
-
-static const long kNumThreads = 4;
-
-long global;
-long global2;
-
-static dispatch_once_t once_token;
-static dispatch_once_t once_token2;
-
-void f(void *a) {
-  global2 = 42;
-  usleep(100000);
-}
-
-void *Thread(void *a) {
-  barrier_wait(&barrier);
-
-  dispatch_once(&once_token, ^{
-    global = 42;
-    usleep(100000);
-  });
-  long x = global;
-
-  dispatch_once_f(&once_token2, NULL, f);
-  long x2 = global2;
-
-  fprintf(stderr, "global = %ld\n", x);
-  fprintf(stderr, "global2 = %ld\n", x2);
-  return 0;
-}
-
-int main() {
-  fprintf(stderr, "Hello world.\n");
-  barrier_init(&barrier, kNumThreads);
-
-  pthread_t t[kNumThreads];
-  for (int i = 0; i < kNumThreads; i++) {
-    pthread_create(&t[i], 0, Thread, 0);
-  }
-  for (int i = 0; i < kNumThreads; i++) {
-    pthread_join(t[i], 0);
-  }
-
-  fprintf(stderr, "Done.\n");
-}
-
-// CHECK: Hello world.
-// CHECK: Done.
-// CHECK-NOT: WARNING: ThreadSanitizer
diff --git a/compiler-rt/test/tsan/gcd-semaphore-norace.c b/compiler-rt/test/tsan/gcd-semaphore-norace.c
deleted file mode 100644 (file)
index 85792f6..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// RUN: %clang_tsan %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
-
-// REQUIRES: dispatch
-
-#include <dispatch/dispatch.h>
-
-#include <stdio.h>
-
-long global;
-
-int main() {
-    fprintf(stderr, "Hello world.");
-
-    global = 42;
-
-    dispatch_semaphore_t sem = dispatch_semaphore_create(0);
-    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-
-        global = 43;
-        dispatch_semaphore_signal(sem);
-    });
-
-    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
-    global = 44;
-
-    fprintf(stderr, "Done.");
-    return 0;
-}
-
-// CHECK: Hello world.
-// CHECK: Done.
-// CHECK-NOT: WARNING: ThreadSanitizer
diff --git a/compiler-rt/test/tsan/gcd-source-serial.c b/compiler-rt/test/tsan/gcd-source-serial.c
deleted file mode 100644 (file)
index 7ce52bb..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// RUN: %clang_tsan %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
-
-// REQUIRES: dispatch
-
-// TODO(yln): fails on one of our bots, need to investigate
-// REQUIRES: disabled
-
-#include <dispatch/dispatch.h>
-
-#include <stdio.h>
-
-long global;
-
-int main(int argc, const char *argv[]) {
-  fprintf(stderr, "Hello world.\n");
-
-  dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_SERIAL);
-  dispatch_semaphore_t sem = dispatch_semaphore_create(0);
-  dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, q);
-  long long interval_ms = 10;
-  dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, 0), interval_ms * NSEC_PER_MSEC, 0);
-  dispatch_source_set_event_handler(timer, ^{
-    fprintf(stderr, "timer\n");
-    global++;
-
-    if (global > 50) {
-      dispatch_semaphore_signal(sem);
-    }
-  });
-  dispatch_resume(timer);
-
-  dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
-
-  fprintf(stderr, "Done.\n");
-}
-
-// CHECK: Hello world.
-// CHECK-NOT: WARNING: ThreadSanitizer
-// CHECK: Done.
diff --git a/compiler-rt/test/tsan/gcd-suspend.c b/compiler-rt/test/tsan/gcd-suspend.c
deleted file mode 100644 (file)
index ebca4c1..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// RUN: %clang_tsan %s -o %t
-// RUN: %run %t 2>&1 | FileCheck %s
-
-// REQUIRES: dispatch
-
-#include <dispatch/dispatch.h>
-
-#include <stdio.h>
-
-long my_global = 0;
-
-int main(int argc, const char *argv[]) {
-  fprintf(stderr, "Hello world.\n");
-
-  dispatch_queue_t q1 = dispatch_queue_create("queue1", NULL);
-  dispatch_queue_t q2 = dispatch_queue_create("queue2", NULL);
-  dispatch_group_t g = dispatch_group_create();
-
-  dispatch_sync(q1, ^{
-    dispatch_suspend(q1);
-    dispatch_async(q2, ^{
-      my_global++;
-      dispatch_resume(q1);
-    });
-  });
-
-  dispatch_sync(q1, ^{
-    my_global++;
-  });
-
-  dispatch_sync(q1, ^{
-    dispatch_suspend(q1);
-    dispatch_group_enter(g);
-    dispatch_async(q1,^{ my_global++; });
-    dispatch_async(q1,^{ my_global++; });
-    dispatch_async(q1,^{ my_global++; dispatch_group_leave(g); });
-    my_global++;
-    dispatch_resume(q1);
-  });
-
-  dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
-
-  fprintf(stderr, "Done.\n");
-  return 0;
-}
-
-// CHECK: Hello world.
-// CHECK-NOT: WARNING: ThreadSanitizer
-// CHECK: Done.
diff --git a/compiler-rt/test/tsan/libdispatch/apply-race.c b/compiler-rt/test/tsan/libdispatch/apply-race.c
new file mode 100644 (file)
index 0000000..10e954c
--- /dev/null
@@ -0,0 +1,30 @@
+// RUN: %clang_tsan %s -o %t
+// RUN: %deflake %run %t 2>&1 | FileCheck %s
+
+#include <dispatch/dispatch.h>
+
+#include "../test.h"
+
+long global;
+
+int main(int argc, const char *argv[]) {
+  barrier_init(&barrier, 2);
+  fprintf(stderr, "start\n");
+
+  // Warm up GCD (workaround for macOS Sierra where dispatch_apply might run single-threaded).
+  dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ });
+
+  dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT);
+  dispatch_apply(2, q, ^(size_t i) {
+    global = i;
+    barrier_wait(&barrier);
+  });
+
+  fprintf(stderr, "done\n");
+  return 0;
+}
+
+// CHECK: start
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Location is global 'global'
+// CHECK: done
diff --git a/compiler-rt/test/tsan/libdispatch/apply.c b/compiler-rt/test/tsan/libdispatch/apply.c
new file mode 100644 (file)
index 0000000..d5c991f
--- /dev/null
@@ -0,0 +1,52 @@
+// RUN: %clang_tsan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+// TODO(yln): Deadlocks while gcd-apply.mm does not. What's the difference
+//            between C and Obj-C compiler?
+// REQUIRES: disable
+
+#include <dispatch/dispatch.h>
+
+#include "../test.h"
+
+long global;
+long array[2];
+
+void callback(void *context, size_t i) {
+  long n = global;
+  array[i] = n + i;
+  barrier_wait(&barrier);
+}
+
+int main(int argc, const char *argv[]) {
+  barrier_init(&barrier, 2);
+  fprintf(stderr, "start\n");
+
+  // Warm up GCD (workaround for macOS Sierra where dispatch_apply might run single-threaded).
+  dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ });
+
+  dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT);
+
+  global = 42;
+
+  dispatch_apply(100, q, ^(size_t i) {
+    long n = global;
+    array[i] = n + i;
+    barrier_wait(&barrier);
+  });
+
+  for (int i = 0; i < 100; i++) {
+    fprintf(stderr, "array[%d] = %ld\n", i, array[i]);
+  }
+
+  global = 43;
+
+  dispatch_apply_f(100, q, NULL, &callback);
+
+  fprintf(stderr, "done\n");
+  return 0;
+}
+
+// CHECK: start
+// CHECK: done
+// CHECK-NOT: WARNING: ThreadSanitizer
diff --git a/compiler-rt/test/tsan/libdispatch/data.c b/compiler-rt/test/tsan/libdispatch/data.c
new file mode 100644 (file)
index 0000000..7a6975b
--- /dev/null
@@ -0,0 +1,41 @@
+// RUN: %clang_tsan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+// TODO(yln): fails on one of our bots, need to investigate
+// REQUIRES: disabled
+
+#include <dispatch/dispatch.h>
+
+#include <stdio.h>
+
+long global;
+
+int main(int argc, const char *argv[]) {
+  fprintf(stderr, "Hello world.\n");
+
+  dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_SERIAL);
+  dispatch_semaphore_t sem = dispatch_semaphore_create(0);
+
+  global = 44;
+  dispatch_data_t data = dispatch_data_create("buffer", 6, q, ^{
+    fprintf(stderr, "Data destructor.\n");
+    global++;
+
+    dispatch_semaphore_signal(sem);
+  });
+  dispatch_release(data);
+  data = NULL;
+
+  dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+
+  data = dispatch_data_create("buffer", 6, q, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
+  dispatch_release(data);
+  data = NULL;
+
+  fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK: Data destructor.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.
diff --git a/compiler-rt/test/tsan/libdispatch/dispatch_main.c b/compiler-rt/test/tsan/libdispatch/dispatch_main.c
new file mode 100644 (file)
index 0000000..43b0d08
--- /dev/null
@@ -0,0 +1,41 @@
+// Check that we don't crash when dispatch_main calls pthread_exit which
+// quits the main thread.
+
+// RUN: %clang_tsan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <dispatch/dispatch.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+  fprintf(stderr,"Hello world");
+
+  dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_SERIAL);
+
+  dispatch_async(q, ^{
+    fprintf(stderr,"1");
+  });
+
+  dispatch_async(q, ^{
+    fprintf(stderr,"2");
+  });
+
+  dispatch_async(q, ^{
+    fprintf(stderr,"3");
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+      fprintf(stderr,"Done.");
+      sleep(1);
+      exit(0);
+    });
+  });
+
+  dispatch_main();
+}
+
+// CHECK: Hello world
+// CHECK: Done.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK-NOT: CHECK failed
diff --git a/compiler-rt/test/tsan/libdispatch/dispatch_once_deadlock.c b/compiler-rt/test/tsan/libdispatch/dispatch_once_deadlock.c
new file mode 100644 (file)
index 0000000..1e9e7d1
--- /dev/null
@@ -0,0 +1,43 @@
+// Check that calling dispatch_once from a report callback works.
+
+// RUN: %clang_tsan %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <dispatch/dispatch.h>
+
+#include <pthread.h>
+#include <stdio.h>
+
+long g = 0;
+long h = 0;
+void f() {
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    g++;
+  });
+  h++;
+}
+
+void __tsan_on_report() {
+  fprintf(stderr, "Report.\n");
+  f();
+}
+
+int main() {
+  fprintf(stderr, "Hello world.\n");
+
+  f();
+
+  pthread_mutex_t mutex = {0};
+  pthread_mutex_lock(&mutex);
+
+  fprintf(stderr, "g = %ld.\n", g);
+  fprintf(stderr, "h = %ld.\n", h);
+  fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK: Report.
+// CHECK: g = 1
+// CHECK: h = 2
+// CHECK: Done.
diff --git a/compiler-rt/test/tsan/libdispatch/groups-destructor.c b/compiler-rt/test/tsan/libdispatch/groups-destructor.c
new file mode 100644 (file)
index 0000000..100f6fc
--- /dev/null
@@ -0,0 +1,43 @@
+// RUN: %clangxx_tsan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <dispatch/dispatch.h>
+
+#import <memory>
+#import <stdatomic.h>
+
+_Atomic(long) destructor_counter = 0;
+
+struct MyStruct {
+  virtual ~MyStruct() {
+    usleep(10000);
+    atomic_fetch_add_explicit(&destructor_counter, 1, memory_order_relaxed);
+  }
+};
+
+int main(int argc, const char *argv[]) {
+  fprintf(stderr, "Hello world.\n");
+
+  dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+  dispatch_group_t g = dispatch_group_create();
+
+  for (int i = 0; i < 100; i++) {
+    std::shared_ptr<MyStruct> shared(new MyStruct());
+
+    dispatch_group_async(g, q, ^{
+      shared.get(); // just to make sure the object is captured by the block
+    });
+  }
+
+  dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
+
+  if (destructor_counter != 100) {
+    abort();
+  }
+
+  fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.
diff --git a/compiler-rt/test/tsan/libdispatch/groups-leave.c b/compiler-rt/test/tsan/libdispatch/groups-leave.c
new file mode 100644 (file)
index 0000000..0e48787
--- /dev/null
@@ -0,0 +1,56 @@
+// RUN: %clang_tsan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <dispatch/dispatch.h>
+
+#include "../test.h"
+
+dispatch_semaphore_t sem;
+
+long global;
+long global2;
+
+void callback(void *context) {
+  global2 = 48;
+  barrier_wait(&barrier);
+
+  dispatch_semaphore_signal(sem);
+}
+
+int main() {
+  fprintf(stderr, "Hello world.\n");
+  barrier_init(&barrier, 2);
+
+  dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT);
+  dispatch_group_t g = dispatch_group_create();
+  sem = dispatch_semaphore_create(0);
+
+  dispatch_group_enter(g);
+  dispatch_async(q, ^{
+    global = 47;
+    dispatch_group_leave(g);
+    barrier_wait(&barrier);
+  });
+  dispatch_group_notify(g, q, ^{
+    global = 48;
+    barrier_wait(&barrier);
+
+    dispatch_semaphore_signal(sem);
+  });
+  dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+
+  dispatch_group_enter(g);
+  dispatch_async(q, ^{
+    global2 = 47;
+    dispatch_group_leave(g);
+    barrier_wait(&barrier);
+  });
+  dispatch_group_notify_f(g, q, NULL, &callback);
+  dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+
+  fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.
diff --git a/compiler-rt/test/tsan/libdispatch/groups-stress.c b/compiler-rt/test/tsan/libdispatch/groups-stress.c
new file mode 100644 (file)
index 0000000..0fdaac0
--- /dev/null
@@ -0,0 +1,45 @@
+// RUN: %clang_tsan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <dispatch/dispatch.h>
+
+#include <stdio.h>
+
+void notify_callback(void *context) {
+  // Do nothing.
+}
+
+int main() {
+  fprintf(stderr, "Hello world.");
+
+  dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+
+  for (int i = 0; i < 300000; i++) {
+    dispatch_group_t g = dispatch_group_create();
+    dispatch_group_enter(g);
+    dispatch_async(q, ^{
+      dispatch_group_leave(g);
+    });
+    dispatch_group_notify(g, q, ^{
+      // Do nothing.
+    });
+    dispatch_release(g);
+  }
+
+  for (int i = 0; i < 300000; i++) {
+    dispatch_group_t g = dispatch_group_create();
+    dispatch_group_enter(g);
+    dispatch_async(q, ^{
+      dispatch_group_leave(g);
+    });
+    dispatch_group_notify_f(g, q, NULL, &notify_callback);
+    dispatch_release(g);
+  }
+
+  fprintf(stderr, "Done.");
+}
+
+// CHECK: Hello world.
+// CHECK: Done.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK-NOT: CHECK failed
diff --git a/compiler-rt/test/tsan/libdispatch/lit.local.cfg b/compiler-rt/test/tsan/libdispatch/lit.local.cfg
new file mode 100644 (file)
index 0000000..b312a3a
--- /dev/null
@@ -0,0 +1,11 @@
+def getRoot(config):
+  if not config.parent:
+    return config
+  return getRoot(config.parent)
+
+root = getRoot(config)
+
+if 'libdispatch' not in root.available_features:
+  config.unsupported = True
+
+config.target_cflags += ' -fblocks'
diff --git a/compiler-rt/test/tsan/libdispatch/once.c b/compiler-rt/test/tsan/libdispatch/once.c
new file mode 100644 (file)
index 0000000..00227b8
--- /dev/null
@@ -0,0 +1,55 @@
+// RUN: %clang_tsan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <dispatch/dispatch.h>
+
+#include "../test.h"
+
+static const long kNumThreads = 4;
+
+long global;
+long global2;
+
+static dispatch_once_t once_token;
+static dispatch_once_t once_token2;
+
+void f(void *a) {
+  global2 = 42;
+  usleep(100000);
+}
+
+void *Thread(void *a) {
+  barrier_wait(&barrier);
+
+  dispatch_once(&once_token, ^{
+    global = 42;
+    usleep(100000);
+  });
+  long x = global;
+
+  dispatch_once_f(&once_token2, NULL, f);
+  long x2 = global2;
+
+  fprintf(stderr, "global = %ld\n", x);
+  fprintf(stderr, "global2 = %ld\n", x2);
+  return 0;
+}
+
+int main() {
+  fprintf(stderr, "Hello world.\n");
+  barrier_init(&barrier, kNumThreads);
+
+  pthread_t t[kNumThreads];
+  for (int i = 0; i < kNumThreads; i++) {
+    pthread_create(&t[i], 0, Thread, 0);
+  }
+  for (int i = 0; i < kNumThreads; i++) {
+    pthread_join(t[i], 0);
+  }
+
+  fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK: Done.
+// CHECK-NOT: WARNING: ThreadSanitizer
diff --git a/compiler-rt/test/tsan/libdispatch/semaphore-norace.c b/compiler-rt/test/tsan/libdispatch/semaphore-norace.c
new file mode 100644 (file)
index 0000000..ce94a3c
--- /dev/null
@@ -0,0 +1,31 @@
+// RUN: %clang_tsan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <dispatch/dispatch.h>
+
+#include <stdio.h>
+
+long global;
+
+int main() {
+    fprintf(stderr, "Hello world.");
+
+    global = 42;
+
+    dispatch_semaphore_t sem = dispatch_semaphore_create(0);
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+
+        global = 43;
+        dispatch_semaphore_signal(sem);
+    });
+
+    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+    global = 44;
+
+    fprintf(stderr, "Done.");
+    return 0;
+}
+
+// CHECK: Hello world.
+// CHECK: Done.
+// CHECK-NOT: WARNING: ThreadSanitizer
diff --git a/compiler-rt/test/tsan/libdispatch/source-serial.c b/compiler-rt/test/tsan/libdispatch/source-serial.c
new file mode 100644 (file)
index 0000000..79dc1af
--- /dev/null
@@ -0,0 +1,38 @@
+// RUN: %clang_tsan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+// TODO(yln): fails on one of our bots, need to investigate
+// REQUIRES: disabled
+
+#include <dispatch/dispatch.h>
+
+#include <stdio.h>
+
+long global;
+
+int main(int argc, const char *argv[]) {
+  fprintf(stderr, "Hello world.\n");
+
+  dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_SERIAL);
+  dispatch_semaphore_t sem = dispatch_semaphore_create(0);
+  dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, q);
+  long long interval_ms = 10;
+  dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, 0), interval_ms * NSEC_PER_MSEC, 0);
+  dispatch_source_set_event_handler(timer, ^{
+    fprintf(stderr, "timer\n");
+    global++;
+
+    if (global > 50) {
+      dispatch_semaphore_signal(sem);
+    }
+  });
+  dispatch_resume(timer);
+
+  dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+
+  fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.
diff --git a/compiler-rt/test/tsan/libdispatch/suspend.c b/compiler-rt/test/tsan/libdispatch/suspend.c
new file mode 100644 (file)
index 0000000..5566faf
--- /dev/null
@@ -0,0 +1,47 @@
+// RUN: %clang_tsan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <dispatch/dispatch.h>
+
+#include <stdio.h>
+
+long my_global = 0;
+
+int main(int argc, const char *argv[]) {
+  fprintf(stderr, "Hello world.\n");
+
+  dispatch_queue_t q1 = dispatch_queue_create("queue1", NULL);
+  dispatch_queue_t q2 = dispatch_queue_create("queue2", NULL);
+  dispatch_group_t g = dispatch_group_create();
+
+  dispatch_sync(q1, ^{
+    dispatch_suspend(q1);
+    dispatch_async(q2, ^{
+      my_global++;
+      dispatch_resume(q1);
+    });
+  });
+
+  dispatch_sync(q1, ^{
+    my_global++;
+  });
+
+  dispatch_sync(q1, ^{
+    dispatch_suspend(q1);
+    dispatch_group_enter(g);
+    dispatch_async(q1,^{ my_global++; });
+    dispatch_async(q1,^{ my_global++; });
+    dispatch_async(q1,^{ my_global++; dispatch_group_leave(g); });
+    my_global++;
+    dispatch_resume(q1);
+  });
+
+  dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
+
+  fprintf(stderr, "Done.\n");
+  return 0;
+}
+
+// CHECK: Hello world.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.