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