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