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; |
21 | void alloc_func() { mem = (char *)malloc(size: 10); } |
22 | |
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, format: "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 | |
36 | void *RaceThread(void *context) { |
37 | *mem = 'a'; |
38 | barrier_wait(barrier: &barrier); |
39 | return NULL; |
40 | } |
41 | |
42 | int main() { |
43 | pthread_t t; |
44 | barrier_init(barrier: &barrier, count: 2); |
45 | |
46 | pthread_create(newthread: &t, NULL, start_routine: AllocThread, NULL); |
47 | pthread_join(th: 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(addr: mem, trace, size: num_frames, thread_id: &thread_id, os_id: &thread_os_id); |
55 | |
56 | fprintf(stderr, format: "alloc stack retval %s\n" , |
57 | (num_frames > 0 && num_frames < 10) ? "ok" : "" ); |
58 | // CHECK: alloc stack retval ok |
59 | fprintf(stderr, format: "thread id = %d\n" , thread_id); |
60 | // CHECK: thread id = 1 |
61 | fprintf(stderr, format: "thread os id = 0x%llx\n" , thread_os_id); |
62 | // CHECK: thread os id = [[THREAD_OS_ID]] |
63 | fprintf(stderr, format: "%p\n" , trace[0]); |
64 | // CHECK: [[ALLOC_FRAME_0:0x[0-9a-f]+]] |
65 | fprintf(stderr, format: "%p\n" , trace[1]); |
66 | // CHECK: [[ALLOC_FRAME_1:0x[0-9a-f]+]] |
67 | fprintf(stderr, format: "%p\n" , trace[2]); |
68 | // CHECK: [[ALLOC_FRAME_2:0x[0-9a-f]+]] |
69 | |
70 | pthread_create(newthread: &t, NULL, start_routine: RaceThread, NULL); |
71 | barrier_wait(barrier: &barrier); |
72 | mem[0] = 'b'; |
73 | pthread_join(th: t, NULL); |
74 | |
75 | free(ptr: 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 | |