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