1//===-- main.c --------------------------------------------------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#import <Foundation/Foundation.h> 10#import <pthread.h> 11 12long my_global; 13 14void *Thread1(void *arg) { 15 my_global = 42; 16 return NULL; 17} 18 19void *Thread2(void *arg) { 20 my_global = 144; 21 return NULL; 22} 23 24void TestDataRace1() { 25 pthread_t t1, t2; 26 pthread_create(&t1, NULL, Thread1, NULL); 27 pthread_create(&t2, NULL, Thread2, NULL); 28 29 pthread_join(t1, NULL); 30 pthread_join(t2, NULL); 31} 32 33void TestInvalidMutex() { 34 pthread_mutex_t m = {0}; 35 pthread_mutex_lock(&m); 36 37 pthread_mutex_init(&m, NULL); 38 pthread_mutex_lock(&m); 39 pthread_mutex_unlock(&m); 40 pthread_mutex_destroy(&m); 41 pthread_mutex_lock(&m); 42} 43 44void TestMutexWrongLock() { 45 pthread_mutex_t m = {0}; 46 pthread_mutex_init(&m, NULL); 47 pthread_mutex_unlock(&m); 48} 49 50long some_global; 51 52void TestDataRaceBlocks1() { 53 dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT); 54 55 for (int i = 0; i < 2; i++) { 56 dispatch_async(q, ^{ 57 some_global++; // race 1 58 59 usleep(100000); // force the blocks to be on different threads 60 }); 61 } 62 63 usleep(100000); 64 dispatch_barrier_sync(q, ^{ }); 65} 66 67void TestDataRaceBlocks2() { 68 dispatch_queue_t q = dispatch_queue_create("my.queue2", DISPATCH_QUEUE_CONCURRENT); 69 70 char *c; 71 72 c = malloc((rand() % 1000) + 10); 73 for (int i = 0; i < 2; i++) { 74 dispatch_async(q, ^{ 75 c[0] = 'x'; // race 2 76 fprintf(stderr, "tid: %p\n", pthread_self()); 77 usleep(100000); // force the blocks to be on different threads 78 }); 79 } 80 dispatch_barrier_sync(q, ^{ }); 81 82 free(c); 83} 84 85void TestUseAfterFree() { 86 char *c; 87 88 c = malloc((rand() % 1000) + 10); 89 free(c); 90 c[0] = 'x'; 91} 92 93void TestRacePipe() { 94 dispatch_queue_t q = dispatch_queue_create("my.queue3", DISPATCH_QUEUE_CONCURRENT); 95 96 int a[2]; 97 pipe(a); 98 int fd = a[0]; 99 100 for (int i = 0; i < 2; i++) { 101 dispatch_async(q, ^{ 102 write(fd, "abc", 3); 103 usleep(100000); // force the blocks to be on different threads 104 }); 105 dispatch_async(q, ^{ 106 close(fd); 107 usleep(100000); 108 }); 109 } 110 111 dispatch_barrier_sync(q, ^{ }); 112} 113 114void TestThreadLeak() { 115 pthread_t t1; 116 pthread_create(&t1, NULL, Thread1, NULL); 117} 118 119int main(int argc, const char * argv[]) { 120 TestDataRace1(); 121 122 TestInvalidMutex(); 123 124 TestMutexWrongLock(); 125 126 TestDataRaceBlocks1(); 127 128 TestDataRaceBlocks2(); 129 130 TestUseAfterFree(); 131 132 TestRacePipe(); 133 134 TestThreadLeak(); 135 136 return 0; 137} 138