64 lines · c
1// RUN: %clang_tsan %s -o %t && %run %t | FileCheck %s2 3// In these systems, the behavior of ReleaseMemoryPagesToOS is madvise(beg, end, MADV_FREE),4// which tags the relevant pages as 'FREE' and does not release them immediately.5// Therefore, we cannot assume that __tsan_read1 will not race with the shadow cleared.6// UNSUPPORTED: darwin,target={{.*(freebsd|netbsd|solaris|haiku).*}}7 8#include "test.h"9#include <assert.h>10#include <pthread.h>11#include <stdint.h>12#include <stdio.h>13#include <sys/mman.h>14#include <unistd.h>15 16void __tsan_read1(void *addr);17 18struct thread_params {19 char *buf;20 unsigned int size;21};22 23static void *thread_func(void *arg) {24 struct thread_params *p = (struct thread_params *)arg;25 // Access 126 p->buf[0] = 0x42;27 p->buf[p->size - 1] = 0x42;28 barrier_wait(&barrier);29 return 0;30}31 32int main() {33 const unsigned int kPageSize = sysconf(_SC_PAGESIZE);34 // The relevant shadow memory size should be exactly multiple of kPageSize,35 // even if Size = kPageSize - 1.36 const unsigned int Size = kPageSize - 1;37 38 barrier_init(&barrier, 2);39 char *buf = (char *)mmap(NULL, Size, PROT_READ | PROT_WRITE,40 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);41 assert(buf != MAP_FAILED);42 assert(((uintptr_t)buf % kPageSize) == 0);43 44 pthread_t t;45 struct thread_params p = {buf, Size};46 pthread_create(&t, 0, thread_func, &p);47 48 barrier_wait(&barrier);49 // Should clear all the shadow memory related to the mmaped memory.50 munmap(buf, Size);51 52 // If the shadow memory is cleared completely, the following reads should not53 // cause races and behave the same. However, previously, __tsan_read1(&buf[0])54 // would not report a race, while __tsan_read1(&buf[Size - 1]) did.55 // CHECK-NOT: WARNING: ThreadSanitizer: data race56 __tsan_read1(&buf[0]); // Access 257 __tsan_read1(&buf[Size - 1]); // Access 258 pthread_join(t, 0);59 60 puts("DONE");61 62 return 0;63}64