xref: /llvm-project/compiler-rt/test/tsan/Darwin/mach_vm_allocate.c (revision 4614b93f53736f18779e46c42a35375fc373ab5d)
1 // Test that mach_vm_[de]allocate resets shadow memory status.
2 //
3 // RUN: %clang_tsan %s -o %t
4 // RUN: %run %t 2>&1 | FileCheck %s --implicit-check-not='ThreadSanitizer'
5 
6 // <mach/mach_vm.h> is not provided by the simulator SDK.
7 // UNSUPPORTED: iossim
8 
9 #include <mach/mach.h>
10 #include <mach/mach_vm.h>
11 #include <pthread.h>
12 #include <assert.h>
13 #include <stdio.h>
14 
15 #include "../test.h"
16 
17 const mach_vm_size_t alloc_size = sizeof(int);
18 static int *global_ptr;
19 
alloc()20 static int *alloc() {
21   mach_vm_address_t addr;
22   kern_return_t kr =
23       mach_vm_allocate(mach_task_self(), &addr, alloc_size, VM_FLAGS_ANYWHERE);
24   assert(kr == KERN_SUCCESS);
25   return (int *)addr;
26 }
27 
alloc_fixed(int * ptr)28 static void alloc_fixed(int *ptr) {
29   mach_vm_address_t addr = (mach_vm_address_t)ptr;
30   // Re-allocation via VM_FLAGS_FIXED sporadically fails.
31   kern_return_t kr =
32       mach_vm_allocate(mach_task_self(), &addr, alloc_size, VM_FLAGS_FIXED);
33   if (kr != KERN_SUCCESS)
34     global_ptr = NULL;
35 }
36 
dealloc(int * ptr)37 static void dealloc(int *ptr) {
38   kern_return_t kr =
39       mach_vm_deallocate(mach_task_self(), (mach_vm_address_t)ptr, alloc_size);
40   assert(kr == KERN_SUCCESS);
41 }
42 
Thread(void * arg)43 static void *Thread(void *arg) {
44   *global_ptr = 7;  // Assignment 1
45 
46   // We want to test that TSan does not report a race between the two
47   // assignments to *global_ptr when the underlying memory is re-allocated
48   // between assignments. The calls to the API itself are racy though, so ignore
49   // them.
50   AnnotateIgnoreWritesBegin(__FILE__, __LINE__);
51   dealloc(global_ptr);
52   alloc_fixed(global_ptr);
53   AnnotateIgnoreWritesEnd(__FILE__, __LINE__);
54 
55   barrier_wait(&barrier);
56   return NULL;
57 }
58 
try_realloc_on_same_address()59 static bool try_realloc_on_same_address() {
60   barrier_init(&barrier, 2);
61   global_ptr = alloc();
62   pthread_t t;
63   pthread_create(&t, NULL, Thread, NULL);
64 
65   barrier_wait(&barrier);
66   if (global_ptr)
67     *global_ptr = 8;  // Assignment 2
68 
69   pthread_join(t, NULL);
70   dealloc(global_ptr);
71 
72   return global_ptr != NULL;
73 }
74 
main(int argc,const char * argv[])75 int main(int argc, const char *argv[]) {
76   bool success;
77   for (int i = 0; i < 10; i++) {
78     success = try_realloc_on_same_address();
79     if (success) break;
80   }
81 
82   if (!success)
83     fprintf(stderr, "Unable to set up testing condition; silently pass test\n");
84 
85   printf("Done.\n");
86   return 0;
87 }
88 
89 // CHECK: Done.
90