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
17const mach_vm_size_t alloc_size = sizeof(int);
18static int *global_ptr;
19
20static 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
28static 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
37static 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
43static 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(ptr: global_ptr);
52 alloc_fixed(ptr: global_ptr);
53 AnnotateIgnoreWritesEnd(__FILE__, __LINE__);
54
55 barrier_wait(barrier: &barrier);
56 return NULL;
57}
58
59static bool try_realloc_on_same_address() {
60 barrier_init(barrier: &barrier, count: 2);
61 global_ptr = alloc();
62 pthread_t t;
63 pthread_create(newthread: &t, NULL, start_routine: Thread, NULL);
64
65 barrier_wait(barrier: &barrier);
66 if (global_ptr)
67 *global_ptr = 8; // Assignment 2
68
69 pthread_join(th: t, NULL);
70 dealloc(ptr: global_ptr);
71
72 return global_ptr != NULL;
73}
74
75int 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, format: "Unable to set up testing condition; silently pass test\n");
84
85 printf(format: "Done.\n");
86 return 0;
87}
88
89// CHECK: Done.
90

source code of compiler-rt/test/tsan/Darwin/mach_vm_allocate.c