xref: /llvm-project/compiler-rt/test/tsan/libdispatch/async_and_wait.c (revision 40ae296bc39a2780ec4cd99edd87cce35585b9ad)
1 // RUN: %clang_tsan %s -o %t -undefined dynamic_lookup
2 // RUN: %run %t 2>&1 | FileCheck %s --implicit-check-not='ThreadSanitizer'
3 
4 #include "dispatch/dispatch.h"
5 
6 #include <stdio.h>
7 
8 // Allow compilation with pre-macOS 10.14 (and aligned) SDKs
9 API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
10 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
11 void dispatch_async_and_wait(dispatch_queue_t queue,
12            DISPATCH_NOESCAPE dispatch_block_t block);
13 
14 long global;
15 
main()16 int main() {
17   // Guard execution on pre-macOS 10.14 (and aligned) platforms
18   if (dispatch_async_and_wait == NULL) {
19     fprintf(stderr, "Done.\n");
20     return 0;
21   }
22 
23   dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_SERIAL);
24   dispatch_semaphore_t s = dispatch_semaphore_create(0);
25 
26   // Force queue to context switch onto separate thread.
27   dispatch_async(q, ^{
28     dispatch_semaphore_wait(s, DISPATCH_TIME_FOREVER);
29   });
30   dispatch_semaphore_signal(s);
31 
32   global++;
33   dispatch_async_and_wait(q, ^{
34     // The queue continues to execute on separate thread.  This would cause a
35     // race if we had used `dispatch_async()` without the `_and_wait` part.
36     global++;
37   });
38   global++;
39 
40   fprintf(stderr, "Done.\n");
41   return 0;
42 }
43 
44 // CHECK: Done.
45