[Sanitizer] Add rudimentary support for wide-character strings to scanf/printf interc...
[blocksruntime.git] / test / tsan / unaligned_race.cc
blob3534ff5d6e0f39f51fedcacf63011fc441160177
1 // RUN: %clangxx_tsan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
2 #include <pthread.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <stdint.h>
6 #include <unistd.h>
8 #define NOINLINE __attribute__((noinline))
10 volatile uint64_t objs[8*2*(2 + 4 + 8)][2];
12 extern "C" {
13 uint16_t __sanitizer_unaligned_load16(volatile void *addr);
14 uint32_t __sanitizer_unaligned_load32(volatile void *addr);
15 uint64_t __sanitizer_unaligned_load64(volatile void *addr);
16 void __sanitizer_unaligned_store16(volatile void *addr, uint16_t v);
17 void __sanitizer_unaligned_store32(volatile void *addr, uint32_t v);
18 void __sanitizer_unaligned_store64(volatile void *addr, uint64_t v);
21 // All this mess is to generate unique stack for each race,
22 // otherwise tsan will suppress similar stacks.
24 static NOINLINE void access(volatile char *p, int sz, int rw) {
25 if (rw) {
26 switch (sz) {
27 case 0: __sanitizer_unaligned_store16(p, 0); break;
28 case 1: __sanitizer_unaligned_store32(p, 0); break;
29 case 2: __sanitizer_unaligned_store64(p, 0); break;
30 default: exit(1);
32 } else {
33 switch (sz) {
34 case 0: __sanitizer_unaligned_load16(p); break;
35 case 1: __sanitizer_unaligned_load32(p); break;
36 case 2: __sanitizer_unaligned_load64(p); break;
37 default: exit(1);
42 static int accesssize(int sz) {
43 switch (sz) {
44 case 0: return 2;
45 case 1: return 4;
46 case 2: return 8;
48 exit(1);
51 template<int off, int off2>
52 static NOINLINE void access3(bool main, int sz1, bool rw, volatile char *p) {
53 p += off;
54 if (main) {
55 access(p, sz1, true);
56 } else {
57 p += off2;
58 if (rw) {
59 *p = 42;
60 } else {
61 if (*p == 42)
62 printf("bingo!\n");
67 template<int off>
68 static NOINLINE void
69 access2(bool main, int sz1, int off2, bool rw, volatile char *obj) {
70 if (off2 == 0)
71 access3<off, 0>(main, sz1, rw, obj);
72 else if (off2 == 1)
73 access3<off, 1>(main, sz1, rw, obj);
74 else if (off2 == 2)
75 access3<off, 2>(main, sz1, rw, obj);
76 else if (off2 == 3)
77 access3<off, 3>(main, sz1, rw, obj);
78 else if (off2 == 4)
79 access3<off, 4>(main, sz1, rw, obj);
80 else if (off2 == 5)
81 access3<off, 5>(main, sz1, rw, obj);
82 else if (off2 == 6)
83 access3<off, 6>(main, sz1, rw, obj);
84 else if (off2 == 7)
85 access3<off, 7>(main, sz1, rw, obj);
88 static NOINLINE void
89 access1(bool main, int off, int sz1, int off2, bool rw, char *obj) {
90 if (off == 0)
91 access2<0>(main, sz1, off2, rw, obj);
92 else if (off == 1)
93 access2<1>(main, sz1, off2, rw, obj);
94 else if (off == 2)
95 access2<2>(main, sz1, off2, rw, obj);
96 else if (off == 3)
97 access2<3>(main, sz1, off2, rw, obj);
98 else if (off == 4)
99 access2<4>(main, sz1, off2, rw, obj);
100 else if (off == 5)
101 access2<5>(main, sz1, off2, rw, obj);
102 else if (off == 6)
103 access2<6>(main, sz1, off2, rw, obj);
104 else if (off == 7)
105 access2<7>(main, sz1, off2, rw, obj);
108 NOINLINE void Test(bool main) {
109 volatile uint64_t *obj = objs[0];
110 for (int off = 0; off < 8; off++) {
111 for (int sz1 = 0; sz1 < 3; sz1++) {
112 for (int off2 = 0; off2 < accesssize(sz1); off2++) {
113 for (int rw = 0; rw < 2; rw++) {
114 // printf("thr=%d off=%d sz1=%d off2=%d rw=%d p=%p\n",
115 // main, off, sz1, off2, rw, obj);
116 access1(main, off, sz1, off2, rw, (char*)obj);
117 obj += 2;
124 void *Thread(void *p) {
125 (void)p;
126 sleep(1);
127 Test(false);
128 return 0;
131 int main() {
132 pthread_t th;
133 pthread_create(&th, 0, Thread, 0);
134 Test(true);
135 pthread_join(th, 0);
138 // CHECK: WARNING: ThreadSanitizer: data race
139 // CHECK: ThreadSanitizer: reported 224 warnings