1 | // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s |
2 | #include <pthread.h> |
3 | #include <stdio.h> |
4 | #include <stdlib.h> |
5 | #include <stdint.h> |
6 | |
7 | uint64_t objs[8*3*3*2][3]; |
8 | |
9 | extern "C" { |
10 | void __tsan_unaligned_read2(void *addr); |
11 | void __tsan_unaligned_read4(void *addr); |
12 | void __tsan_unaligned_read8(void *addr); |
13 | void __tsan_unaligned_write2(void *addr); |
14 | void __tsan_unaligned_write4(void *addr); |
15 | void __tsan_unaligned_write8(void *addr); |
16 | } |
17 | |
18 | static void access(char *p, int sz, int rw) { |
19 | if (rw) { |
20 | switch (sz) { |
21 | case 0: __tsan_unaligned_write2(addr: p); break; |
22 | case 1: __tsan_unaligned_write4(addr: p); break; |
23 | case 2: __tsan_unaligned_write8(addr: p); break; |
24 | default: exit(status: 1); |
25 | } |
26 | } else { |
27 | switch (sz) { |
28 | case 0: __tsan_unaligned_read2(addr: p); break; |
29 | case 1: __tsan_unaligned_read4(addr: p); break; |
30 | case 2: __tsan_unaligned_read8(addr: p); break; |
31 | default: exit(status: 1); |
32 | } |
33 | } |
34 | } |
35 | |
36 | static int accesssize(int sz) { |
37 | switch (sz) { |
38 | case 0: return 2; |
39 | case 1: return 4; |
40 | case 2: return 8; |
41 | } |
42 | exit(status: 1); |
43 | } |
44 | |
45 | void Test(bool main) { |
46 | uint64_t *obj = objs[0]; |
47 | for (int off = 0; off < 8; off++) { |
48 | for (int sz1 = 0; sz1 < 3; sz1++) { |
49 | for (int sz2 = 0; sz2 < 3; sz2++) { |
50 | for (int rw = 0; rw < 2; rw++) { |
51 | char *p = (char*)obj + off; |
52 | if (main) { |
53 | // printf("thr=%d off=%d sz1=%d sz2=%d rw=%d p=%p\n", |
54 | // main, off, sz1, sz2, rw, p); |
55 | access(p, sz: sz1, rw: true); |
56 | } else { |
57 | p += accesssize(sz: sz1); |
58 | // printf("thr=%d off=%d sz1=%d sz2=%d rw=%d p=%p\n", |
59 | // main, off, sz1, sz2, rw, p); |
60 | access(p, sz: sz2, rw); |
61 | } |
62 | obj += 3; |
63 | } |
64 | } |
65 | } |
66 | } |
67 | } |
68 | |
69 | void *Thread(void *p) { |
70 | (void)p; |
71 | Test(main: false); |
72 | return 0; |
73 | } |
74 | |
75 | int main() { |
76 | pthread_t th; |
77 | pthread_create(newthread: &th, attr: 0, start_routine: Thread, arg: 0); |
78 | Test(main: true); |
79 | pthread_join(th: th, thread_return: 0); |
80 | fprintf(stderr, format: "OK\n" ); |
81 | } |
82 | |
83 | // CHECK-NOT: WARNING: ThreadSanitizer: |
84 | // CHECK: OK |
85 | |