1 // RUN: %clangxx_tsan -O0 %s -o %t
2 // RUN: env %env_tsan_opts=stack_trace_format=DEFAULT %deflake %run %t 2>&1 | FileCheck %s
3 
4 // Until I figure out how to make this test work on Linux
5 // REQUIRES: system-darwin
6 
7 #include "test.h"
8 #include <pthread.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 
13 #ifndef __APPLE__
14 #include <sys/types.h>
15 #endif
16 
17 extern "C" int __tsan_get_alloc_stack(void *addr, void **trace, size_t size,
18                                       int *thread_id, uint64_t *os_id);
19 
20 char *mem;
alloc_func()21 void alloc_func() { mem = (char *)malloc(10); }
22 
AllocThread(void * context)23 void *AllocThread(void *context) {
24   uint64_t tid;
25 #ifdef __APPLE__
26   pthread_threadid_np(NULL, &tid);
27 #else
28   tid = gettid();
29 #endif
30   fprintf(stderr, "alloc stack thread os id = 0x%llx\n", tid);
31   // CHECK: alloc stack thread os id = [[THREAD_OS_ID:0x[0-9a-f]+]]
32   alloc_func();
33   return NULL;
34 }
35 
RaceThread(void * context)36 void *RaceThread(void *context) {
37   *mem = 'a';
38   barrier_wait(&barrier);
39   return NULL;
40 }
41 
main()42 int main() {
43   pthread_t t;
44   barrier_init(&barrier, 2);
45 
46   pthread_create(&t, NULL, AllocThread, NULL);
47   pthread_join(t, NULL);
48 
49   void *trace[100];
50   size_t num_frames = 100;
51   int thread_id;
52   uint64_t *thread_os_id;
53   num_frames =
54       __tsan_get_alloc_stack(mem, trace, num_frames, &thread_id, &thread_os_id);
55 
56   fprintf(stderr, "alloc stack retval %s\n",
57           (num_frames > 0 && num_frames < 10) ? "ok" : "");
58   // CHECK: alloc stack retval ok
59   fprintf(stderr, "thread id = %d\n", thread_id);
60   // CHECK: thread id = 1
61   fprintf(stderr, "thread os id = 0x%llx\n", thread_os_id);
62   // CHECK: thread os id = [[THREAD_OS_ID]]
63   fprintf(stderr, "%p\n", trace[0]);
64   // CHECK: [[ALLOC_FRAME_0:0x[0-9a-f]+]]
65   fprintf(stderr, "%p\n", trace[1]);
66   // CHECK: [[ALLOC_FRAME_1:0x[0-9a-f]+]]
67   fprintf(stderr, "%p\n", trace[2]);
68   // CHECK: [[ALLOC_FRAME_2:0x[0-9a-f]+]]
69 
70   pthread_create(&t, NULL, RaceThread, NULL);
71   barrier_wait(&barrier);
72   mem[0] = 'b';
73   pthread_join(t, NULL);
74 
75   free(mem);
76 
77   return 0;
78 }
79 
80 // CHECK: WARNING: ThreadSanitizer: data race
81 // CHECK: Location is heap block of size 10 at {{.*}} allocated by thread T1
82 // CHECK: #0 [[ALLOC_FRAME_0]]
83 // CHECK: #1 [[ALLOC_FRAME_1]] in alloc_func
84 // CHECK: #2 [[ALLOC_FRAME_2]] in AllocThread
85