Index: compiler-rt/trunk/test/lit.common.cfg =================================================================== --- compiler-rt/trunk/test/lit.common.cfg +++ compiler-rt/trunk/test/lit.common.cfg @@ -222,9 +222,9 @@ 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: Index: compiler-rt/trunk/test/tsan/gcd-apply-race.c =================================================================== --- compiler-rt/trunk/test/tsan/gcd-apply-race.c +++ compiler-rt/trunk/test/tsan/gcd-apply-race.c @@ -1,32 +0,0 @@ -// RUN: %clang_tsan %s -o %t -// RUN: %deflake %run %t 2>&1 | FileCheck %s - -// REQUIRES: dispatch - -#include - -#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 Index: compiler-rt/trunk/test/tsan/gcd-apply.c =================================================================== --- compiler-rt/trunk/test/tsan/gcd-apply.c +++ compiler-rt/trunk/test/tsan/gcd-apply.c @@ -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 - -#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 Index: compiler-rt/trunk/test/tsan/gcd-data.c =================================================================== --- compiler-rt/trunk/test/tsan/gcd-data.c +++ compiler-rt/trunk/test/tsan/gcd-data.c @@ -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 - -#include - -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. Index: compiler-rt/trunk/test/tsan/gcd-dispatch_main.c =================================================================== --- compiler-rt/trunk/test/tsan/gcd-dispatch_main.c +++ compiler-rt/trunk/test/tsan/gcd-dispatch_main.c @@ -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 - -#include -#include - -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 Index: compiler-rt/trunk/test/tsan/gcd-dispatch_once_deadlock.c =================================================================== --- compiler-rt/trunk/test/tsan/gcd-dispatch_once_deadlock.c +++ compiler-rt/trunk/test/tsan/gcd-dispatch_once_deadlock.c @@ -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 - -#include -#include - -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. Index: compiler-rt/trunk/test/tsan/gcd-groups-destructor.c =================================================================== --- compiler-rt/trunk/test/tsan/gcd-groups-destructor.c +++ compiler-rt/trunk/test/tsan/gcd-groups-destructor.c @@ -1,45 +0,0 @@ -// RUN: %clangxx_tsan %s -o %t -// RUN: %run %t 2>&1 | FileCheck %s - -// REQUIRES: dispatch - -#include - -#import -#import - -_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 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. Index: compiler-rt/trunk/test/tsan/gcd-groups-leave.c =================================================================== --- compiler-rt/trunk/test/tsan/gcd-groups-leave.c +++ compiler-rt/trunk/test/tsan/gcd-groups-leave.c @@ -1,58 +0,0 @@ -// RUN: %clang_tsan %s -o %t -// RUN: %run %t 2>&1 | FileCheck %s - -// REQUIRES: dispatch - -#include - -#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. Index: compiler-rt/trunk/test/tsan/gcd-groups-stress.c =================================================================== --- compiler-rt/trunk/test/tsan/gcd-groups-stress.c +++ compiler-rt/trunk/test/tsan/gcd-groups-stress.c @@ -1,47 +0,0 @@ -// RUN: %clang_tsan %s -o %t -// RUN: %run %t 2>&1 | FileCheck %s - -// REQUIRES: dispatch - -#include - -#include - -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, ¬ify_callback); - dispatch_release(g); - } - - fprintf(stderr, "Done."); -} - -// CHECK: Hello world. -// CHECK: Done. -// CHECK-NOT: WARNING: ThreadSanitizer -// CHECK-NOT: CHECK failed Index: compiler-rt/trunk/test/tsan/gcd-once.c =================================================================== --- compiler-rt/trunk/test/tsan/gcd-once.c +++ compiler-rt/trunk/test/tsan/gcd-once.c @@ -1,57 +0,0 @@ -// RUN: %clang_tsan %s -o %t -// RUN: %run %t 2>&1 | FileCheck %s - -// REQUIRES: dispatch - -#include - -#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 Index: compiler-rt/trunk/test/tsan/gcd-semaphore-norace.c =================================================================== --- compiler-rt/trunk/test/tsan/gcd-semaphore-norace.c +++ compiler-rt/trunk/test/tsan/gcd-semaphore-norace.c @@ -1,33 +0,0 @@ -// RUN: %clang_tsan %s -o %t -// RUN: %run %t 2>&1 | FileCheck %s - -// REQUIRES: dispatch - -#include - -#include - -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 Index: compiler-rt/trunk/test/tsan/gcd-source-serial.c =================================================================== --- compiler-rt/trunk/test/tsan/gcd-source-serial.c +++ compiler-rt/trunk/test/tsan/gcd-source-serial.c @@ -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 - -#include - -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. Index: compiler-rt/trunk/test/tsan/gcd-suspend.c =================================================================== --- compiler-rt/trunk/test/tsan/gcd-suspend.c +++ compiler-rt/trunk/test/tsan/gcd-suspend.c @@ -1,49 +0,0 @@ -// RUN: %clang_tsan %s -o %t -// RUN: %run %t 2>&1 | FileCheck %s - -// REQUIRES: dispatch - -#include - -#include - -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. Index: compiler-rt/trunk/test/tsan/libdispatch/apply-race.c =================================================================== --- compiler-rt/trunk/test/tsan/libdispatch/apply-race.c +++ compiler-rt/trunk/test/tsan/libdispatch/apply-race.c @@ -0,0 +1,30 @@ +// RUN: %clang_tsan %s -o %t +// RUN: %deflake %run %t 2>&1 | FileCheck %s + +#include + +#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 Index: compiler-rt/trunk/test/tsan/libdispatch/apply.c =================================================================== --- compiler-rt/trunk/test/tsan/libdispatch/apply.c +++ compiler-rt/trunk/test/tsan/libdispatch/apply.c @@ -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 + +#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 Index: compiler-rt/trunk/test/tsan/libdispatch/data.c =================================================================== --- compiler-rt/trunk/test/tsan/libdispatch/data.c +++ compiler-rt/trunk/test/tsan/libdispatch/data.c @@ -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 + +#include + +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. Index: compiler-rt/trunk/test/tsan/libdispatch/dispatch_main.c =================================================================== --- compiler-rt/trunk/test/tsan/libdispatch/dispatch_main.c +++ compiler-rt/trunk/test/tsan/libdispatch/dispatch_main.c @@ -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 + +#include +#include + +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 Index: compiler-rt/trunk/test/tsan/libdispatch/dispatch_once_deadlock.c =================================================================== --- compiler-rt/trunk/test/tsan/libdispatch/dispatch_once_deadlock.c +++ compiler-rt/trunk/test/tsan/libdispatch/dispatch_once_deadlock.c @@ -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 + +#include +#include + +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. Index: compiler-rt/trunk/test/tsan/libdispatch/groups-destructor.c =================================================================== --- compiler-rt/trunk/test/tsan/libdispatch/groups-destructor.c +++ compiler-rt/trunk/test/tsan/libdispatch/groups-destructor.c @@ -0,0 +1,43 @@ +// RUN: %clangxx_tsan %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +#include + +#import +#import + +_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 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. Index: compiler-rt/trunk/test/tsan/libdispatch/groups-leave.c =================================================================== --- compiler-rt/trunk/test/tsan/libdispatch/groups-leave.c +++ compiler-rt/trunk/test/tsan/libdispatch/groups-leave.c @@ -0,0 +1,56 @@ +// RUN: %clang_tsan %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +#include + +#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. Index: compiler-rt/trunk/test/tsan/libdispatch/groups-stress.c =================================================================== --- compiler-rt/trunk/test/tsan/libdispatch/groups-stress.c +++ compiler-rt/trunk/test/tsan/libdispatch/groups-stress.c @@ -0,0 +1,45 @@ +// RUN: %clang_tsan %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +#include + +#include + +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, ¬ify_callback); + dispatch_release(g); + } + + fprintf(stderr, "Done."); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer +// CHECK-NOT: CHECK failed Index: compiler-rt/trunk/test/tsan/libdispatch/lit.local.cfg =================================================================== --- compiler-rt/trunk/test/tsan/libdispatch/lit.local.cfg +++ compiler-rt/trunk/test/tsan/libdispatch/lit.local.cfg @@ -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' Index: compiler-rt/trunk/test/tsan/libdispatch/once.c =================================================================== --- compiler-rt/trunk/test/tsan/libdispatch/once.c +++ compiler-rt/trunk/test/tsan/libdispatch/once.c @@ -0,0 +1,55 @@ +// RUN: %clang_tsan %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +#include + +#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 Index: compiler-rt/trunk/test/tsan/libdispatch/semaphore-norace.c =================================================================== --- compiler-rt/trunk/test/tsan/libdispatch/semaphore-norace.c +++ compiler-rt/trunk/test/tsan/libdispatch/semaphore-norace.c @@ -0,0 +1,31 @@ +// RUN: %clang_tsan %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +#include + +#include + +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 Index: compiler-rt/trunk/test/tsan/libdispatch/source-serial.c =================================================================== --- compiler-rt/trunk/test/tsan/libdispatch/source-serial.c +++ compiler-rt/trunk/test/tsan/libdispatch/source-serial.c @@ -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 + +#include + +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. Index: compiler-rt/trunk/test/tsan/libdispatch/suspend.c =================================================================== --- compiler-rt/trunk/test/tsan/libdispatch/suspend.c +++ compiler-rt/trunk/test/tsan/libdispatch/suspend.c @@ -0,0 +1,47 @@ +// RUN: %clang_tsan %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +#include + +#include + +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.