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