blob: 2aa9f178e5a7e68fbc63c50834e6179181e9bf97 [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
Dmitry Vyukov81a78ad2012-08-13 18:44:44 +000021const int kMaxGoroutinesEver = 128*1024;
22
23static ThreadState *goroutines[kMaxGoroutinesEver];
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +000024
25void InitializeInterceptors() {
26}
27
28void InitializeDynamicAnnotations() {
29}
30
31bool IsExpectedReport(uptr addr, uptr size) {
32 return false;
33}
34
35void internal_start_thread(void(*func)(void*), void *arg) {
36}
37
Dmitry Vyukove0d31e92012-07-06 14:54:25 +000038ReportStack *SymbolizeData(uptr addr) {
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +000039 return 0;
40}
41
Dmitry Vyukove0d31e92012-07-06 14:54:25 +000042ReportStack *NewReportStackEntry(uptr addr) {
43 ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack,
44 sizeof(ReportStack));
45 internal_memset(ent, 0, sizeof(*ent));
46 ent->pc = addr;
47 return ent;
48}
49
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +000050void *internal_alloc(MBlockType typ, uptr sz) {
51 return InternalAlloc(sz);
52}
53
54void internal_free(void *p) {
55 InternalFree(p);
56}
57
Dmitry Vyukov4e946622012-07-27 14:00:39 +000058// Callback into Go.
59extern "C" int __tsan_symbolize(uptr pc, char **func, char **file,
60 int *line, int *off);
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +000061
Dmitry Vyukov4e946622012-07-27 14:00:39 +000062ReportStack *SymbolizeCode(uptr addr) {
63 ReportStack *s = (ReportStack*)internal_alloc(MBlockReportStack,
64 sizeof(ReportStack));
65 internal_memset(s, 0, sizeof(*s));
66 s->pc = addr;
67 char *func = 0, *file = 0;
68 int line = 0, off = 0;
69 if (__tsan_symbolize(addr, &func, &file, &line, &off)) {
70 s->offset = off;
71 s->func = internal_strdup(func ? func : "??");
72 s->file = internal_strdup(file ? file : "-");
73 s->line = line;
74 s->col = 0;
75 free(func);
76 free(file);
77 }
78 return s;
79}
80
81extern "C" {
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +000082
Dmitry Vyukov239ae712012-07-06 20:23:59 +000083static void AllocGoroutine(int tid) {
Dmitry Vyukov81a78ad2012-08-13 18:44:44 +000084 if (tid >= kMaxGoroutinesEver) {
85 Printf("FATAL: Reached goroutine limit\n");
86 Die();
87 }
88 ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex,
Dmitry Vyukov239ae712012-07-06 20:23:59 +000089 sizeof(ThreadState));
Dmitry Vyukov81a78ad2012-08-13 18:44:44 +000090 internal_memset(thr, 0, sizeof(*thr));
91 goroutines[tid] = thr;
Dmitry Vyukov239ae712012-07-06 20:23:59 +000092}
93
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +000094void __tsan_init() {
Dmitry Vyukov239ae712012-07-06 20:23:59 +000095 AllocGoroutine(0);
96 ThreadState *thr = goroutines[0];
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +000097 thr->in_rtl++;
98 Initialize(thr);
99 thr->in_rtl--;
100}
101
102void __tsan_fini() {
103 // FIXME: Not necessary thread 0.
Dmitry Vyukov239ae712012-07-06 20:23:59 +0000104 ThreadState *thr = goroutines[0];
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000105 thr->in_rtl++;
106 int res = Finalize(thr);
107 thr->in_rtl--;
108 exit(res);
109}
110
Dmitry Vyukov4e946622012-07-27 14:00:39 +0000111void __tsan_read(int goid, void *addr, void *pc) {
112 ThreadState *thr = goroutines[goid];
113 MemoryAccess(thr, (uptr)pc, (uptr)addr, 0, false);
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000114}
115
Dmitry Vyukov4e946622012-07-27 14:00:39 +0000116void __tsan_write(int goid, void *addr, void *pc) {
117 ThreadState *thr = goroutines[goid];
118 MemoryAccess(thr, (uptr)pc, (uptr)addr, 0, true);
119}
120
121void __tsan_func_enter(int goid, void *pc) {
122 ThreadState *thr = goroutines[goid];
123 FuncEntry(thr, (uptr)pc);
124}
125
126void __tsan_func_exit(int goid) {
127 ThreadState *thr = goroutines[goid];
128 FuncExit(thr);
129}
130
131void __tsan_malloc(int goid, void *p, uptr sz, void *pc) {
132 ThreadState *thr = goroutines[goid];
133 thr->in_rtl++;
134 MemoryResetRange(thr, (uptr)pc, (uptr)p, sz);
135 MemoryAccessRange(thr, (uptr)pc, (uptr)p, sz, true);
136 thr->in_rtl--;
137}
138
139void __tsan_free(void *p) {
140 (void)p;
141}
142
143void __tsan_go_start(int pgoid, int chgoid, void *pc) {
144 if (chgoid == 0)
145 return;
146 AllocGoroutine(chgoid);
147 ThreadState *thr = goroutines[chgoid];
148 ThreadState *parent = goroutines[pgoid];
149 thr->in_rtl++;
150 parent->in_rtl++;
151 int goid2 = ThreadCreate(parent, (uptr)pc, 0, true);
152 ThreadStart(thr, goid2);
153 parent->in_rtl--;
154 thr->in_rtl--;
155}
156
157void __tsan_go_end(int goid) {
158 ThreadState *thr = goroutines[goid];
159 thr->in_rtl++;
160 ThreadFinish(thr);
161 thr->in_rtl--;
Dmitry Vyukov81a78ad2012-08-13 18:44:44 +0000162 internal_free(thr);
163 goroutines[goid] = 0;
Dmitry Vyukov4e946622012-07-27 14:00:39 +0000164}
165
166void __tsan_acquire(int goid, void *addr) {
167 ThreadState *thr = goroutines[goid];
168 thr->in_rtl++;
169 Acquire(thr, 0, (uptr)addr);
170 thr->in_rtl--;
Dmitry Vyukov4e946622012-07-27 14:00:39 +0000171}
172
173void __tsan_release(int goid, void *addr) {
174 ThreadState *thr = goroutines[goid];
175 thr->in_rtl++;
Dmitry Vyukov904d3f92012-07-28 15:27:41 +0000176 ReleaseStore(thr, 0, (uptr)addr);
Dmitry Vyukov4e946622012-07-27 14:00:39 +0000177 thr->in_rtl--;
178}
179
180void __tsan_release_merge(int goid, void *addr) {
181 ThreadState *thr = goroutines[goid];
182 thr->in_rtl++;
183 Release(thr, 0, (uptr)addr);
Dmitry Vyukov4e946622012-07-27 14:00:39 +0000184 thr->in_rtl--;
185}
186
187void __tsan_finalizer_goroutine(int goid) {
188 ThreadState *thr = goroutines[goid];
Dmitry Vyukovdfc8e522012-07-25 13:16:35 +0000189 ThreadFinalizerGoroutine(thr);
190}
191
Dmitry Vyukov03d32ec2012-07-05 16:18:28 +0000192} // extern "C"
193} // namespace __tsan