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
17extern "C" int __tsan_get_alloc_stack(void *addr, void **trace, size_t size,
18 int *thread_id, uint64_t *os_id);
19
20char *mem;
21void alloc_func() { mem = (char *)malloc(10); }
22
23void *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
36void *RaceThread(void *context) {
37 *mem = 'a';
38 barrier_wait(&barrier);
39 return NULL;
40}
41
42int 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