xref: /aosp_15_r20/external/compiler-rt/test/tsan/unaligned_race.cc (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
1*7c3d14c8STreehugger Robot // RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
2*7c3d14c8STreehugger Robot #include "test.h"
3*7c3d14c8STreehugger Robot #include <stdint.h>
4*7c3d14c8STreehugger Robot 
5*7c3d14c8STreehugger Robot #define NOINLINE __attribute__((noinline))
6*7c3d14c8STreehugger Robot 
7*7c3d14c8STreehugger Robot volatile uint64_t objs[8*2*(2 + 4 + 8)][2];
8*7c3d14c8STreehugger Robot 
9*7c3d14c8STreehugger Robot extern "C" {
10*7c3d14c8STreehugger Robot uint16_t __sanitizer_unaligned_load16(volatile void *addr);
11*7c3d14c8STreehugger Robot uint32_t __sanitizer_unaligned_load32(volatile void *addr);
12*7c3d14c8STreehugger Robot uint64_t __sanitizer_unaligned_load64(volatile void *addr);
13*7c3d14c8STreehugger Robot void __sanitizer_unaligned_store16(volatile void *addr, uint16_t v);
14*7c3d14c8STreehugger Robot void __sanitizer_unaligned_store32(volatile void *addr, uint32_t v);
15*7c3d14c8STreehugger Robot void __sanitizer_unaligned_store64(volatile void *addr, uint64_t v);
16*7c3d14c8STreehugger Robot }
17*7c3d14c8STreehugger Robot 
18*7c3d14c8STreehugger Robot // All this mess is to generate unique stack for each race,
19*7c3d14c8STreehugger Robot // otherwise tsan will suppress similar stacks.
20*7c3d14c8STreehugger Robot 
access(volatile char * p,int sz,int rw)21*7c3d14c8STreehugger Robot static NOINLINE void access(volatile char *p, int sz, int rw) {
22*7c3d14c8STreehugger Robot   if (rw) {
23*7c3d14c8STreehugger Robot     switch (sz) {
24*7c3d14c8STreehugger Robot     case 0: __sanitizer_unaligned_store16(p, 0); break;
25*7c3d14c8STreehugger Robot     case 1: __sanitizer_unaligned_store32(p, 0); break;
26*7c3d14c8STreehugger Robot     case 2: __sanitizer_unaligned_store64(p, 0); break;
27*7c3d14c8STreehugger Robot     default: exit(1);
28*7c3d14c8STreehugger Robot     }
29*7c3d14c8STreehugger Robot   } else {
30*7c3d14c8STreehugger Robot     switch (sz) {
31*7c3d14c8STreehugger Robot     case 0: __sanitizer_unaligned_load16(p); break;
32*7c3d14c8STreehugger Robot     case 1: __sanitizer_unaligned_load32(p); break;
33*7c3d14c8STreehugger Robot     case 2: __sanitizer_unaligned_load64(p); break;
34*7c3d14c8STreehugger Robot     default: exit(1);
35*7c3d14c8STreehugger Robot     }
36*7c3d14c8STreehugger Robot   }
37*7c3d14c8STreehugger Robot }
38*7c3d14c8STreehugger Robot 
accesssize(int sz)39*7c3d14c8STreehugger Robot static int accesssize(int sz) {
40*7c3d14c8STreehugger Robot   switch (sz) {
41*7c3d14c8STreehugger Robot   case 0: return 2;
42*7c3d14c8STreehugger Robot   case 1: return 4;
43*7c3d14c8STreehugger Robot   case 2: return 8;
44*7c3d14c8STreehugger Robot   }
45*7c3d14c8STreehugger Robot   exit(1);
46*7c3d14c8STreehugger Robot }
47*7c3d14c8STreehugger Robot 
48*7c3d14c8STreehugger Robot template<int off, int off2>
access3(bool main,int sz1,bool rw,volatile char * p)49*7c3d14c8STreehugger Robot static NOINLINE void access3(bool main, int sz1, bool rw, volatile char *p) {
50*7c3d14c8STreehugger Robot   p += off;
51*7c3d14c8STreehugger Robot   if (main) {
52*7c3d14c8STreehugger Robot     access(p, sz1, true);
53*7c3d14c8STreehugger Robot   } else {
54*7c3d14c8STreehugger Robot     p += off2;
55*7c3d14c8STreehugger Robot     if (rw) {
56*7c3d14c8STreehugger Robot       *p = 42;
57*7c3d14c8STreehugger Robot     } else {
58*7c3d14c8STreehugger Robot        if (*p == 42)
59*7c3d14c8STreehugger Robot          printf("bingo!\n");
60*7c3d14c8STreehugger Robot     }
61*7c3d14c8STreehugger Robot   }
62*7c3d14c8STreehugger Robot }
63*7c3d14c8STreehugger Robot 
64*7c3d14c8STreehugger Robot template<int off>
65*7c3d14c8STreehugger Robot static NOINLINE void
access2(bool main,int sz1,int off2,bool rw,volatile char * obj)66*7c3d14c8STreehugger Robot access2(bool main, int sz1, int off2, bool rw, volatile char *obj) {
67*7c3d14c8STreehugger Robot   if (off2 == 0)
68*7c3d14c8STreehugger Robot     access3<off, 0>(main, sz1, rw, obj);
69*7c3d14c8STreehugger Robot   else if (off2 == 1)
70*7c3d14c8STreehugger Robot     access3<off, 1>(main, sz1, rw, obj);
71*7c3d14c8STreehugger Robot   else if (off2 == 2)
72*7c3d14c8STreehugger Robot     access3<off, 2>(main, sz1, rw, obj);
73*7c3d14c8STreehugger Robot   else if (off2 == 3)
74*7c3d14c8STreehugger Robot     access3<off, 3>(main, sz1, rw, obj);
75*7c3d14c8STreehugger Robot   else if (off2 == 4)
76*7c3d14c8STreehugger Robot     access3<off, 4>(main, sz1, rw, obj);
77*7c3d14c8STreehugger Robot   else if (off2 == 5)
78*7c3d14c8STreehugger Robot     access3<off, 5>(main, sz1, rw, obj);
79*7c3d14c8STreehugger Robot   else if (off2 == 6)
80*7c3d14c8STreehugger Robot     access3<off, 6>(main, sz1, rw, obj);
81*7c3d14c8STreehugger Robot   else if (off2 == 7)
82*7c3d14c8STreehugger Robot     access3<off, 7>(main, sz1, rw, obj);
83*7c3d14c8STreehugger Robot }
84*7c3d14c8STreehugger Robot 
85*7c3d14c8STreehugger Robot static NOINLINE void
access1(bool main,int off,int sz1,int off2,bool rw,char * obj)86*7c3d14c8STreehugger Robot access1(bool main, int off, int sz1, int off2, bool rw, char *obj) {
87*7c3d14c8STreehugger Robot   if (off == 0)
88*7c3d14c8STreehugger Robot     access2<0>(main, sz1, off2, rw, obj);
89*7c3d14c8STreehugger Robot   else if (off == 1)
90*7c3d14c8STreehugger Robot     access2<1>(main, sz1, off2, rw, obj);
91*7c3d14c8STreehugger Robot   else if (off == 2)
92*7c3d14c8STreehugger Robot     access2<2>(main, sz1, off2, rw, obj);
93*7c3d14c8STreehugger Robot   else if (off == 3)
94*7c3d14c8STreehugger Robot     access2<3>(main, sz1, off2, rw, obj);
95*7c3d14c8STreehugger Robot   else if (off == 4)
96*7c3d14c8STreehugger Robot     access2<4>(main, sz1, off2, rw, obj);
97*7c3d14c8STreehugger Robot   else if (off == 5)
98*7c3d14c8STreehugger Robot     access2<5>(main, sz1, off2, rw, obj);
99*7c3d14c8STreehugger Robot   else if (off == 6)
100*7c3d14c8STreehugger Robot     access2<6>(main, sz1, off2, rw, obj);
101*7c3d14c8STreehugger Robot   else if (off == 7)
102*7c3d14c8STreehugger Robot     access2<7>(main, sz1, off2, rw, obj);
103*7c3d14c8STreehugger Robot }
104*7c3d14c8STreehugger Robot 
Test(bool main)105*7c3d14c8STreehugger Robot NOINLINE void Test(bool main) {
106*7c3d14c8STreehugger Robot   volatile uint64_t *obj = objs[0];
107*7c3d14c8STreehugger Robot   for (int off = 0; off < 8; off++) {
108*7c3d14c8STreehugger Robot     for (int sz1 = 0; sz1 < 3; sz1++) {
109*7c3d14c8STreehugger Robot       for (int off2 = 0; off2 < accesssize(sz1); off2++) {
110*7c3d14c8STreehugger Robot         for (int rw = 0; rw < 2; rw++) {
111*7c3d14c8STreehugger Robot           // printf("thr=%d off=%d sz1=%d off2=%d rw=%d p=%p\n",
112*7c3d14c8STreehugger Robot           //        main, off, sz1, off2, rw, obj);
113*7c3d14c8STreehugger Robot           access1(main, off, sz1, off2, rw, (char*)obj);
114*7c3d14c8STreehugger Robot           obj += 2;
115*7c3d14c8STreehugger Robot         }
116*7c3d14c8STreehugger Robot       }
117*7c3d14c8STreehugger Robot     }
118*7c3d14c8STreehugger Robot   }
119*7c3d14c8STreehugger Robot }
120*7c3d14c8STreehugger Robot 
Thread(void * p)121*7c3d14c8STreehugger Robot void *Thread(void *p) {
122*7c3d14c8STreehugger Robot   (void)p;
123*7c3d14c8STreehugger Robot   barrier_wait(&barrier);
124*7c3d14c8STreehugger Robot   Test(false);
125*7c3d14c8STreehugger Robot   return 0;
126*7c3d14c8STreehugger Robot }
127*7c3d14c8STreehugger Robot 
main()128*7c3d14c8STreehugger Robot int main() {
129*7c3d14c8STreehugger Robot   barrier_init(&barrier, 2);
130*7c3d14c8STreehugger Robot   pthread_t th;
131*7c3d14c8STreehugger Robot   pthread_create(&th, 0, Thread, 0);
132*7c3d14c8STreehugger Robot   Test(true);
133*7c3d14c8STreehugger Robot   barrier_wait(&barrier);
134*7c3d14c8STreehugger Robot   pthread_join(th, 0);
135*7c3d14c8STreehugger Robot }
136*7c3d14c8STreehugger Robot 
137*7c3d14c8STreehugger Robot // CHECK: WARNING: ThreadSanitizer: data race
138*7c3d14c8STreehugger Robot // CHECK: ThreadSanitizer: reported 224 warnings
139