blob: d0437d9efcf3a2f50c0a1f0a4f9c68d9afaeaa3c [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
Dmitry Vyukov239ae712012-07-06 20:23:59 +000025static ThreadState *goroutines[kMaxTid];
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +000026
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
Dmitry Vyukovbcf0b702012-07-24 12:29:43 +000040extern "C" int __tsan_symbolize(uptr pc, char **func, char **file,
41 int *line, int *off);
Dmitry Vyukovc40c0072012-07-16 13:02:40 +000042extern "C" void free(void *p);
Dmitry Vyukove0d31e92012-07-06 14:54:25 +000043
44ReportStack *SymbolizeCode(uptr addr) {
45 ReportStack *s = NewReportStackEntry(addr);
Dmitry Vyukovd654f062012-07-25 11:50:37 +000046 char *func = 0, *file = 0;
47 int line = 0, off = 0;
Dmitry Vyukovbcf0b702012-07-24 12:29:43 +000048 if (__tsan_symbolize(addr, &func, &file, &line, &off)) {
49 s->offset = off;
Dmitry Vyukovd654f062012-07-25 11:50:37 +000050 s->func = internal_strdup(func ? func : "??");
51 s->file = internal_strdup(file ? file : "-");
Dmitry Vyukovbcf0b702012-07-24 12:29:43 +000052 s->line = line;
Dmitry Vyukove0d31e92012-07-06 14:54:25 +000053 s->col = 0;
Dmitry Vyukovbcf0b702012-07-24 12:29:43 +000054 free(func);
55 free(file);
Dmitry Vyukove0d31e92012-07-06 14:54:25 +000056 }
57 return s;
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +000058}
59
Dmitry Vyukove0d31e92012-07-06 14:54:25 +000060ReportStack *SymbolizeData(uptr addr) {
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +000061 return 0;
62}
63
Dmitry Vyukove0d31e92012-07-06 14:54:25 +000064ReportStack *NewReportStackEntry(uptr addr) {
65 ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack,
66 sizeof(ReportStack));
67 internal_memset(ent, 0, sizeof(*ent));
68 ent->pc = addr;
69 return ent;
70}
71
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +000072void *internal_alloc(MBlockType typ, uptr sz) {
73 return InternalAlloc(sz);
74}
75
76void internal_free(void *p) {
77 InternalFree(p);
78}
79
80extern "C" {
81
82enum Tsan1EventType {
83 NOOP, // Should not appear.
84 READ, // {tid, pc, addr, size}
85 WRITE, // {tid, pc, addr, size}
86 READER_LOCK, // {tid, pc, lock, 0}
87 WRITER_LOCK, // {tid, pc, lock, 0}
88 UNLOCK, // {tid, pc, lock, 0}
89 UNLOCK_OR_INIT, // {tid, pc, lock, 0}
90 LOCK_CREATE, // {tid, pc, lock, 0}
91 LOCK_DESTROY, // {tid, pc, lock, 0}
92 THR_CREATE_BEFORE, // Parent thread's event. {tid, pc, 0, 0}
93 THR_CREATE_AFTER, // Parent thread's event. {tid, 0, 0, child_tid}/* 10 */
94 THR_START, // Child thread's event {tid, CallStack, 0, parent_tid}
95 THR_FIRST_INSN, // Used only by valgrind.
96 THR_END, // {tid, 0, 0, 0}
97 THR_JOIN_AFTER, // {tid, pc, joined_tid}
98 THR_STACK_TOP, // {tid, pc, stack_top, stack_size_if_known}
99 RTN_EXIT, // {tid, 0, 0, 0}
100 RTN_CALL, // {tid, pc, 0, 0}
101 SBLOCK_ENTER, // {tid, pc, 0, 0}
102 SIGNAL, // {tid, pc, obj, 0}
103 WAIT, // {tid, pc, obj, 0} /* 20 */
104 CYCLIC_BARRIER_INIT, // {tid, pc, obj, n}
105 CYCLIC_BARRIER_WAIT_BEFORE, // {tid, pc, obj, 0}
106 CYCLIC_BARRIER_WAIT_AFTER, // {tid, pc, obj, 0}
107 PCQ_CREATE, // {tid, pc, pcq_addr, 0}
108 PCQ_DESTROY, // {tid, pc, pcq_addr, 0}
109 PCQ_PUT, // {tid, pc, pcq_addr, 0}
110 PCQ_GET, // {tid, pc, pcq_addr, 0}
111 STACK_MEM_DIE, // deprecated.
112 MALLOC, // {tid, pc, addr, size}
113 FREE, // {tid, pc, addr, 0} /* 30 */
114 MMAP, // {tid, pc, addr, size}
115 MUNMAP, // {tid, pc, addr, size}
116 PUBLISH_RANGE, // may be deprecated later.
117 UNPUBLISH_RANGE, // deprecated. TODO(kcc): get rid of this.
118 HB_LOCK, // {tid, pc, addr, 0}
119 NON_HB_LOCK, // {tid, pc, addr, 0}
120 IGNORE_READS_BEG, // {tid, pc, 0, 0}
121 IGNORE_READS_END, // {tid, pc, 0, 0}
122 IGNORE_WRITES_BEG, // {tid, pc, 0, 0}
123 IGNORE_WRITES_END, // {tid, pc, 0, 0}
124 SET_THREAD_NAME, // {tid, pc, name_str, 0}
125 SET_LOCK_NAME, // {tid, pc, lock, lock_name_str}
126 TRACE_MEM, // {tid, pc, addr, 0}
127 EXPECT_RACE, // {tid, descr_str, ptr, size}
128 BENIGN_RACE, // {tid, descr_str, ptr, size}
129 EXPECT_RACE_BEGIN, // {tid, pc, 0, 0}
130 EXPECT_RACE_END, // {tid, pc, 0, 0}
131 VERBOSITY, // Used for debugging.
132 STACK_TRACE, // {tid, pc, 0, 0}, for debugging.
133 FLUSH_STATE, // {tid, pc, 0, 0}
134 PC_DESCRIPTION, // {0, pc, descr_str, 0}, for ts_offline.
135 PRINT_MESSAGE, // {tid, pc, message_str, 0}, for ts_offline.
136 FLUSH_EXPECTED_RACES, // {0, 0, 0, 0}
137 LAST_EVENT // Should not appear.
138};
139
Dmitry Vyukov239ae712012-07-06 20:23:59 +0000140static void AllocGoroutine(int tid) {
141 goroutines[tid] = (ThreadState*)internal_alloc(MBlockThreadContex,
142 sizeof(ThreadState));
143 internal_memset(goroutines[tid], 0, sizeof(ThreadState));
144}
145
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000146void __tsan_init() {
Dmitry Vyukov239ae712012-07-06 20:23:59 +0000147 AllocGoroutine(0);
148 ThreadState *thr = goroutines[0];
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000149 thr->in_rtl++;
150 Initialize(thr);
151 thr->in_rtl--;
152}
153
154void __tsan_fini() {
155 // FIXME: Not necessary thread 0.
Dmitry Vyukov239ae712012-07-06 20:23:59 +0000156 ThreadState *thr = goroutines[0];
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000157 thr->in_rtl++;
158 int res = Finalize(thr);
159 thr->in_rtl--;
160 exit(res);
161}
162
163void __tsan_event(int typ, int tid, void *pc, void *addr, int info) {
Dmitry Vyukov239ae712012-07-06 20:23:59 +0000164 ThreadState *thr = goroutines[tid];
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000165 switch (typ) {
166 case READ:
167 MemoryAccess(thr, (uptr)pc, (uptr)addr, 0, false);
168 break;
169 case WRITE:
170 MemoryAccess(thr, (uptr)pc, (uptr)addr, 0, true);
171 break;
172 case RTN_EXIT:
173 FuncExit(thr);
174 break;
175 case RTN_CALL:
176 FuncEntry(thr, (uptr)pc);
177 break;
178 case SBLOCK_ENTER:
179 break;
180 case SIGNAL:
181 thr->in_rtl++;
182 Release(thr, (uptr)pc, (uptr)addr);
183 thr->in_rtl--;
184 break;
185 case WAIT:
186 thr->in_rtl++;
187 Acquire(thr, (uptr)pc, (uptr)addr);
188 thr->in_rtl--;
189 break;
190 case MALLOC:
191 thr->in_rtl++;
192 MemoryResetRange(thr, (uptr)pc, (uptr)addr, (uptr)info);
Dmitry Vyukov3abd0962012-07-16 16:55:01 +0000193 MemoryAccessRange(thr, (uptr)pc, (uptr)addr, (uptr)info, true);
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000194 thr->in_rtl--;
195 break;
196 case FREE:
197 break;
198 case THR_START: {
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000199 if (tid == 0)
200 return;
Dmitry Vyukov239ae712012-07-06 20:23:59 +0000201 ThreadState *parent = goroutines[info];
202 AllocGoroutine(tid);
203 thr = goroutines[tid];
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000204 thr->in_rtl++;
205 parent->in_rtl++;
206 int tid2 = ThreadCreate(parent, (uptr)pc, 0, true);
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000207 ThreadStart(thr, tid2);
208 parent->in_rtl--;
209 thr->in_rtl--;
210 break;
211 }
Dmitry Vyukov9270eaf2012-07-16 16:01:08 +0000212 case THR_END: {
213 thr->in_rtl++;
214 ThreadFinish(thr);
215 thr->in_rtl--;
216 break;
217 }
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000218 default:
Dmitry Vyukov239ae712012-07-06 20:23:59 +0000219 Printf("Unknown event type %d\n", typ);
220 Die();
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000221 }
222}
223
Dmitry Vyukovdfc8e522012-07-25 13:16:35 +0000224void __tsan_finalizer_goroutine(int tid) {
225 ThreadState *thr = goroutines[tid];
226 ThreadFinalizerGoroutine(thr);
227}
228
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000229} // extern "C"
230} // namespace __tsan