85 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			85 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
// RUN: %clangxx_tsan -O0 %s -o %t
 | 
						|
// RUN: env %env_tsan_opts=stack_trace_format=DEFAULT %deflake %run %t 2>&1 | FileCheck %s
 | 
						|
 | 
						|
// Until I figure out how to make this test work on Linux
 | 
						|
// REQUIRES: system-darwin
 | 
						|
 | 
						|
#include "test.h"
 | 
						|
#include <pthread.h>
 | 
						|
#include <stdint.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
#ifndef __APPLE__
 | 
						|
#include <sys/types.h>
 | 
						|
#endif
 | 
						|
 | 
						|
extern "C" int __tsan_get_alloc_stack(void *addr, void **trace, size_t size,
 | 
						|
                                      int *thread_id, uint64_t *os_id);
 | 
						|
 | 
						|
char *mem;
 | 
						|
void alloc_func() { mem = (char *)malloc(10); }
 | 
						|
 | 
						|
void *AllocThread(void *context) {
 | 
						|
  uint64_t tid;
 | 
						|
#ifdef __APPLE__
 | 
						|
  pthread_threadid_np(NULL, &tid);
 | 
						|
#else
 | 
						|
  tid = gettid();
 | 
						|
#endif
 | 
						|
  fprintf(stderr, "alloc stack thread os id = 0x%llx\n", tid);
 | 
						|
  // CHECK: alloc stack thread os id = [[THREAD_OS_ID:0x[0-9a-f]+]]
 | 
						|
  alloc_func();
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
void *RaceThread(void *context) {
 | 
						|
  *mem = 'a';
 | 
						|
  barrier_wait(&barrier);
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
int main() {
 | 
						|
  pthread_t t;
 | 
						|
  barrier_init(&barrier, 2);
 | 
						|
 | 
						|
  pthread_create(&t, NULL, AllocThread, NULL);
 | 
						|
  pthread_join(t, NULL);
 | 
						|
 | 
						|
  void *trace[100];
 | 
						|
  size_t num_frames = 100;
 | 
						|
  int thread_id;
 | 
						|
  uint64_t *thread_os_id;
 | 
						|
  num_frames =
 | 
						|
      __tsan_get_alloc_stack(mem, trace, num_frames, &thread_id, &thread_os_id);
 | 
						|
 | 
						|
  fprintf(stderr, "alloc stack retval %s\n",
 | 
						|
          (num_frames > 0 && num_frames < 10) ? "ok" : "");
 | 
						|
  // CHECK: alloc stack retval ok
 | 
						|
  fprintf(stderr, "thread id = %d\n", thread_id);
 | 
						|
  // CHECK: thread id = 1
 | 
						|
  fprintf(stderr, "thread os id = 0x%llx\n", thread_os_id);
 | 
						|
  // CHECK: thread os id = [[THREAD_OS_ID]]
 | 
						|
  fprintf(stderr, "%p\n", trace[0]);
 | 
						|
  // CHECK: [[ALLOC_FRAME_0:0x[0-9a-f]+]]
 | 
						|
  fprintf(stderr, "%p\n", trace[1]);
 | 
						|
  // CHECK: [[ALLOC_FRAME_1:0x[0-9a-f]+]]
 | 
						|
  fprintf(stderr, "%p\n", trace[2]);
 | 
						|
  // CHECK: [[ALLOC_FRAME_2:0x[0-9a-f]+]]
 | 
						|
 | 
						|
  pthread_create(&t, NULL, RaceThread, NULL);
 | 
						|
  barrier_wait(&barrier);
 | 
						|
  mem[0] = 'b';
 | 
						|
  pthread_join(t, NULL);
 | 
						|
 | 
						|
  free(mem);
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
// CHECK: WARNING: ThreadSanitizer: data race
 | 
						|
// CHECK: Location is heap block of size 10 at {{.*}} allocated by thread T1
 | 
						|
// CHECK: #0 [[ALLOC_FRAME_0]]
 | 
						|
// CHECK: #1 [[ALLOC_FRAME_1]] in alloc_func
 | 
						|
// CHECK: #2 [[ALLOC_FRAME_2]] in AllocThread
 |