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(newthread: &t1, NULL, start_routine: Thread1, NULL);
19 pthread_create(newthread: &t2, NULL, start_routine: Thread2, NULL);
20
21 pthread_join(th: t1, NULL);
22 pthread_join(th: t2, NULL);
23}
24
25void TestInvalidMutex() {
26 pthread_mutex_t m = {0};
27 pthread_mutex_lock(mutex: &m);
28
29 pthread_mutex_init(mutex: &m, NULL);
30 pthread_mutex_lock(mutex: &m);
31 pthread_mutex_unlock(mutex: &m);
32 pthread_mutex_destroy(mutex: &m);
33 pthread_mutex_lock(mutex: &m);
34}
35
36void TestMutexWrongLock() {
37 pthread_mutex_t m = {0};
38 pthread_mutex_init(mutex: &m, NULL);
39 pthread_mutex_unlock(mutex: &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(newthread: &t1, NULL, start_routine: 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

source code of lldb/test/API/functionalities/tsan/multiple/main.m