blob: bd264c9ad7fb3c51560858f98bfa6e74102e6c72 [file] [log] [blame]
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +00001//===-- tsan_go.cc --------------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// ThreadSanitizer runtime for Go language.
11//
12//===----------------------------------------------------------------------===//
13
14#include "tsan_rtl.h"
15#include "tsan_symbolize.h"
16#include "sanitizer_common/sanitizer_common.h"
17#include <stdlib.h>
18
19namespace __tsan {
20
21struct ThreadStatePlaceholder {
22 uptr opaque[sizeof(ThreadState) / sizeof(uptr) + kCacheLineSize];
23};
24
25static ThreadStatePlaceholder *threads;
26
27void InitializeInterceptors() {
28}
29
30void InitializeDynamicAnnotations() {
31}
32
33bool IsExpectedReport(uptr addr, uptr size) {
34 return false;
35}
36
37void internal_start_thread(void(*func)(void*), void *arg) {
38}
39
40ReportStack *SymbolizeCodeAddr2Line(uptr addr) {
41 return NewReportStackEntry(addr);
42}
43
44ReportStack *SymbolizeDataAddr2Line(uptr addr) {
45 return 0;
46}
47
48void *internal_alloc(MBlockType typ, uptr sz) {
49 return InternalAlloc(sz);
50}
51
52void internal_free(void *p) {
53 InternalFree(p);
54}
55
56extern "C" {
57
58enum Tsan1EventType {
59 NOOP, // Should not appear.
60 READ, // {tid, pc, addr, size}
61 WRITE, // {tid, pc, addr, size}
62 READER_LOCK, // {tid, pc, lock, 0}
63 WRITER_LOCK, // {tid, pc, lock, 0}
64 UNLOCK, // {tid, pc, lock, 0}
65 UNLOCK_OR_INIT, // {tid, pc, lock, 0}
66 LOCK_CREATE, // {tid, pc, lock, 0}
67 LOCK_DESTROY, // {tid, pc, lock, 0}
68 THR_CREATE_BEFORE, // Parent thread's event. {tid, pc, 0, 0}
69 THR_CREATE_AFTER, // Parent thread's event. {tid, 0, 0, child_tid}/* 10 */
70 THR_START, // Child thread's event {tid, CallStack, 0, parent_tid}
71 THR_FIRST_INSN, // Used only by valgrind.
72 THR_END, // {tid, 0, 0, 0}
73 THR_JOIN_AFTER, // {tid, pc, joined_tid}
74 THR_STACK_TOP, // {tid, pc, stack_top, stack_size_if_known}
75 RTN_EXIT, // {tid, 0, 0, 0}
76 RTN_CALL, // {tid, pc, 0, 0}
77 SBLOCK_ENTER, // {tid, pc, 0, 0}
78 SIGNAL, // {tid, pc, obj, 0}
79 WAIT, // {tid, pc, obj, 0} /* 20 */
80 CYCLIC_BARRIER_INIT, // {tid, pc, obj, n}
81 CYCLIC_BARRIER_WAIT_BEFORE, // {tid, pc, obj, 0}
82 CYCLIC_BARRIER_WAIT_AFTER, // {tid, pc, obj, 0}
83 PCQ_CREATE, // {tid, pc, pcq_addr, 0}
84 PCQ_DESTROY, // {tid, pc, pcq_addr, 0}
85 PCQ_PUT, // {tid, pc, pcq_addr, 0}
86 PCQ_GET, // {tid, pc, pcq_addr, 0}
87 STACK_MEM_DIE, // deprecated.
88 MALLOC, // {tid, pc, addr, size}
89 FREE, // {tid, pc, addr, 0} /* 30 */
90 MMAP, // {tid, pc, addr, size}
91 MUNMAP, // {tid, pc, addr, size}
92 PUBLISH_RANGE, // may be deprecated later.
93 UNPUBLISH_RANGE, // deprecated. TODO(kcc): get rid of this.
94 HB_LOCK, // {tid, pc, addr, 0}
95 NON_HB_LOCK, // {tid, pc, addr, 0}
96 IGNORE_READS_BEG, // {tid, pc, 0, 0}
97 IGNORE_READS_END, // {tid, pc, 0, 0}
98 IGNORE_WRITES_BEG, // {tid, pc, 0, 0}
99 IGNORE_WRITES_END, // {tid, pc, 0, 0}
100 SET_THREAD_NAME, // {tid, pc, name_str, 0}
101 SET_LOCK_NAME, // {tid, pc, lock, lock_name_str}
102 TRACE_MEM, // {tid, pc, addr, 0}
103 EXPECT_RACE, // {tid, descr_str, ptr, size}
104 BENIGN_RACE, // {tid, descr_str, ptr, size}
105 EXPECT_RACE_BEGIN, // {tid, pc, 0, 0}
106 EXPECT_RACE_END, // {tid, pc, 0, 0}
107 VERBOSITY, // Used for debugging.
108 STACK_TRACE, // {tid, pc, 0, 0}, for debugging.
109 FLUSH_STATE, // {tid, pc, 0, 0}
110 PC_DESCRIPTION, // {0, pc, descr_str, 0}, for ts_offline.
111 PRINT_MESSAGE, // {tid, pc, message_str, 0}, for ts_offline.
112 FLUSH_EXPECTED_RACES, // {0, 0, 0, 0}
113 LAST_EVENT // Should not appear.
114};
115
116void __tsan_init() {
117 threads = (ThreadStatePlaceholder*)internal_alloc(MBlockThreadContex,
118 kMaxTid * sizeof(ThreadStatePlaceholder));
119 //!!! internal_memset(threads, 0, kMaxTid * sizeof(ThreadStatePlaceholder));
120 ThreadState *thr = (ThreadState*)&threads[0];
121 thr->in_rtl++;
122 Initialize(thr);
123 thr->in_rtl--;
124}
125
126void __tsan_fini() {
127 // FIXME: Not necessary thread 0.
128 ThreadState *thr = (ThreadState*)&threads[0];
129 thr->in_rtl++;
130 int res = Finalize(thr);
131 thr->in_rtl--;
132 exit(res);
133}
134
135void __tsan_event(int typ, int tid, void *pc, void *addr, int info) {
136 //if (typ != READ && typ != WRITE && typ != SBLOCK_ENTER)
137 // Printf("typ=%d tid=%d pc=%p addr=%p info=%d\n", typ, tid, pc, addr, info);
138 ThreadState *thr = (ThreadState*)&threads[tid];
139 switch (typ) {
140 case READ:
141 MemoryAccess(thr, (uptr)pc, (uptr)addr, 0, false);
142 break;
143 case WRITE:
144 MemoryAccess(thr, (uptr)pc, (uptr)addr, 0, true);
145 break;
146 case RTN_EXIT:
147 FuncExit(thr);
148 break;
149 case RTN_CALL:
150 FuncEntry(thr, (uptr)pc);
151 break;
152 case SBLOCK_ENTER:
153 break;
154 case SIGNAL:
155 thr->in_rtl++;
156 Release(thr, (uptr)pc, (uptr)addr);
157 thr->in_rtl--;
158 break;
159 case WAIT:
160 thr->in_rtl++;
161 Acquire(thr, (uptr)pc, (uptr)addr);
162 thr->in_rtl--;
163 break;
164 case MALLOC:
165 thr->in_rtl++;
166 MemoryResetRange(thr, (uptr)pc, (uptr)addr, (uptr)info);
167 thr->in_rtl--;
168 break;
169 case FREE:
170 break;
171 case THR_START: {
172 //Printf("typ=%d tid=%d pc=%p addr=%p info=%d\n", typ, tid, pc, addr, info);
173 if (tid == 0)
174 return;
175 ThreadState *parent = (ThreadState*)&threads[info];
176 thr->in_rtl++;
177 parent->in_rtl++;
178 int tid2 = ThreadCreate(parent, (uptr)pc, 0, true);
179 CHECK_EQ(tid2, tid);
180 ThreadStart(thr, tid2);
181 parent->in_rtl--;
182 thr->in_rtl--;
183 break;
184 }
185 default:
186 thr->in_rtl++;
187 Printf("Event: typ=%d thr=%d\n", typ, tid);
188 thr->in_rtl--;
189 }
190}
191
192} // extern "C"
193} // namespace __tsan