xref: /llvm-project/compiler-rt/test/tsan/libdispatch/io.c (revision a59dad920ffb7a01f8e275ac4b6596048621fd20)
1 // RUN: %clang_tsan %s -o %t
2 // RUN: %run %t 2>&1 | FileCheck %s --implicit-check-not='ThreadSanitizer'
3 
4 #include <dispatch/dispatch.h>
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 
9 dispatch_queue_t queue;
10 dispatch_data_t data;
11 dispatch_semaphore_t sem;
12 const char *path;
13 
14 long my_global = 0;
15 
test_dispatch_io_write()16 void test_dispatch_io_write() {
17   dispatch_io_t channel = dispatch_io_create_with_path(DISPATCH_IO_STREAM, path, O_CREAT | O_WRONLY, 0666, queue, ^(int error) { });
18   if (! channel) abort();
19   dispatch_io_set_high_water(channel, 1);
20 
21   my_global++;
22   dispatch_io_write(channel, 0, data, queue, ^(bool done, dispatch_data_t remainingData, int error) {
23     if (error) abort();
24     my_global++;
25     dispatch_async(queue, ^{
26       my_global++;
27       if (done) {
28         dispatch_semaphore_signal(sem);
29       }
30     });
31   });
32 
33   dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
34   my_global++;
35   dispatch_io_close(channel, 0);
36 }
37 
test_dispatch_write()38 void test_dispatch_write() {
39   dispatch_fd_t fd = open(path, O_CREAT | O_WRONLY, 0666);
40   if (fd == -1) abort();
41 
42   my_global++;
43   dispatch_write(fd, data, queue, ^(dispatch_data_t data, int error) {
44     if (error) abort();
45     my_global++;
46     dispatch_async(queue, ^{
47       my_global++;
48 
49       dispatch_semaphore_signal(sem);
50     });
51   });
52 
53   dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
54   my_global++;
55   close(fd);
56 }
57 
test_dispatch_io_read()58 void test_dispatch_io_read() {
59   dispatch_io_t channel = dispatch_io_create_with_path(DISPATCH_IO_STREAM, path, O_RDONLY,
60                        0, queue, ^(int error) { });
61   dispatch_io_set_high_water(channel, 1);
62 
63   my_global++;
64   dispatch_io_read(channel, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t remainingData, int error) {
65     if (error) abort();
66     my_global++;
67     dispatch_async(queue, ^{
68       my_global++;
69       if (done) {
70         dispatch_semaphore_signal(sem);
71       }
72     });
73   });
74 
75   dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
76   my_global++;
77   dispatch_io_close(channel, 0);
78 }
79 
test_dispatch_read()80 void test_dispatch_read() {
81   dispatch_fd_t fd = open(path, O_RDONLY, 0);
82   if (fd == -1) abort();
83 
84   my_global++;
85   dispatch_read(fd, SIZE_MAX, queue, ^(dispatch_data_t data, int error) {
86     if (error) abort();
87     my_global++;
88     dispatch_async(queue, ^{
89       my_global++;
90       dispatch_semaphore_signal(sem);
91     });
92   });
93 
94   dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
95   my_global++;
96   close(fd);
97 }
98 
main(int argc,const char * argv[])99 int main(int argc, const char *argv[]) {
100   fprintf(stderr, "Hello world.\n");
101 
102   queue = dispatch_queue_create("my.queue", DISPATCH_QUEUE_SERIAL);
103   sem = dispatch_semaphore_create(0);
104   path = tempnam(NULL, "libdispatch-io-");
105   char buf[1000];
106   data = dispatch_data_create(buf, sizeof(buf), NULL, DISPATCH_DATA_DESTRUCTOR_DEFAULT);
107 
108   test_dispatch_io_write();
109   test_dispatch_write();
110   test_dispatch_io_read();
111   test_dispatch_read();
112 
113   fprintf(stderr, "Done.\n");
114   return 0;
115 }
116 
117 // CHECK: Hello world.
118 // CHECK: Done.
119