1*bcaeed49SFangrui Song // RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s
2*bcaeed49SFangrui Song // Race between an aligned access and an unaligned access, which
3*bcaeed49SFangrui Song // touches the same memory region.
4*bcaeed49SFangrui Song #include "test.h"
5*bcaeed49SFangrui Song #include <stdint.h>
6*bcaeed49SFangrui Song
7*bcaeed49SFangrui Song uint64_t Global[2];
8*bcaeed49SFangrui Song
Thread1(void * x)9*bcaeed49SFangrui Song void *Thread1(void *x) {
10*bcaeed49SFangrui Song Global[1]++;
11*bcaeed49SFangrui Song barrier_wait(&barrier);
12*bcaeed49SFangrui Song return NULL;
13*bcaeed49SFangrui Song }
14*bcaeed49SFangrui Song
Thread2(void * x)15*bcaeed49SFangrui Song void *Thread2(void *x) {
16*bcaeed49SFangrui Song barrier_wait(&barrier);
17*bcaeed49SFangrui Song char *p1 = reinterpret_cast<char *>(&Global[0]);
18*bcaeed49SFangrui Song struct __attribute__((packed, aligned(1))) u_uint64_t { uint64_t val; };
19*bcaeed49SFangrui Song u_uint64_t *p4 = reinterpret_cast<u_uint64_t *>(p1 + 1);
20*bcaeed49SFangrui Song (*p4).val++;
21*bcaeed49SFangrui Song return NULL;
22*bcaeed49SFangrui Song }
23*bcaeed49SFangrui Song
main()24*bcaeed49SFangrui Song int main() {
25*bcaeed49SFangrui Song barrier_init(&barrier, 2);
26*bcaeed49SFangrui Song pthread_t t[2];
27*bcaeed49SFangrui Song pthread_create(&t[0], NULL, Thread1, NULL);
28*bcaeed49SFangrui Song pthread_create(&t[1], NULL, Thread2, NULL);
29*bcaeed49SFangrui Song pthread_join(t[0], NULL);
30*bcaeed49SFangrui Song pthread_join(t[1], NULL);
31*bcaeed49SFangrui Song fprintf(stderr, "Pass\n");
32*bcaeed49SFangrui Song // CHECK: ThreadSanitizer: data race
33*bcaeed49SFangrui Song // CHECK: Pass
34*bcaeed49SFangrui Song return 0;
35*bcaeed49SFangrui Song }
36