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