1 // RUN: %clangxx_tsan -O0 %s -o %t
2 // RUN: not %run %t        2>&1 | FileCheck %s --check-prefix=CHECK-RACE
3 // RUN:     %run %t ignore 2>&1 | FileCheck %s --check-prefix=CHECK-IGNORE
4 
5 #include <sys/mman.h>
6 #include <string.h>
7 #include <assert.h>
8 #include <atomic>
9 
10 #include "test.h"
11 
12 // Use atomic to ensure we do not have a race for the pointer value itself.  We
13 // only want to check races in the mmap'd memory to isolate the test that mmap
14 // respects ignore annotations.
15 std::atomic<int*> global_p;
16 
mmap_ignored(bool ignore)17 void mmap_ignored(bool ignore) {
18   const size_t kSize = sysconf(_SC_PAGESIZE);
19 
20   if (ignore) AnnotateIgnoreWritesBegin(__FILE__, __LINE__);
21   void *p = mmap(0, kSize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
22   if (ignore) AnnotateIgnoreWritesEnd(__FILE__, __LINE__);
23 
24   // Use relaxed to retain the race between the mmap call and the memory write
25   global_p.store((int *)p, std::memory_order_relaxed);
26   barrier_wait(&barrier);
27 }
28 
WriteToMemory(void * unused)29 void *WriteToMemory(void *unused) {
30   barrier_wait(&barrier);
31   global_p[0] = 7;
32   return 0;
33 }
34 
35 // Create race between allocating (mmap) and writing memory
main(int argc,const char * argv[])36 int main(int argc, const char *argv[]) {
37   bool ignore = (argc > 1) && (strcmp(argv[1], "ignore") == 0);
38 
39   barrier_init(&barrier, 2);
40   pthread_t t;
41   pthread_create(&t, 0, WriteToMemory, 0);
42   mmap_ignored(ignore);
43   pthread_join(t, 0);
44 
45   assert(global_p[0] == 7);
46   printf("OK\n");
47   return 0;
48 }
49 
50 // CHECK-RACE: WARNING: ThreadSanitizer: data race
51 // CHECK-RACE: OK
52 // CHECK-IGNORE-NOT: WARNING: ThreadSanitizer: data race
53 // CHECK-IGNORE: OK
54