Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(10)

Delta Between Two Patch Sets: src/pkg/runtime/race.c

Issue 160200044: [dev.power64] code review 160200044: build: merge default into dev.power64 (Closed)
Left Patch Set: diff -r be0c14f62257b42485019e9e1db23cf40d2e249f https://code.google.com/p/go Created 10 years, 4 months ago
Right Patch Set: diff -r be0c14f62257b42485019e9e1db23cf40d2e249f https://code.google.com/p/go Created 10 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/runtime/proc_test.go ('k') | src/pkg/runtime/race.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // Copyright 2011 The Go Authors. All rights reserved. 1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Implementation of the race detector API. 5 // Implementation of the race detector API.
6 // +build race 6 // +build race
7 7
8 #include "runtime.h" 8 #include "runtime.h"
9 #include "arch_GOARCH.h" 9 #include "arch_GOARCH.h"
10 #include "malloc.h" 10 #include "malloc.h"
11 #include "race.h" 11 #include "race.h"
12 #include "type.h" 12 #include "type.h"
13 #include "typekind.h" 13 #include "typekind.h"
14 #include "textflag.h"
14 15
15 // Race runtime functions called via runtime·racecall. 16 // Race runtime functions called via runtime·racecall.
16 void __tsan_init(void); 17 void __tsan_init(void);
17 void __tsan_fini(void); 18 void __tsan_fini(void);
18 void __tsan_map_shadow(void); 19 void __tsan_map_shadow(void);
19 void __tsan_finalizer_goroutine(void); 20 void __tsan_finalizer_goroutine(void);
20 void __tsan_go_start(void); 21 void __tsan_go_start(void);
21 void __tsan_go_end(void); 22 void __tsan_go_end(void);
22 void __tsan_malloc(void); 23 void __tsan_malloc(void);
23 void __tsan_acquire(void); 24 void __tsan_acquire(void);
24 void __tsan_release(void); 25 void __tsan_release(void);
25 void __tsan_release_merge(void); 26 void __tsan_release_merge(void);
27 void __tsan_go_ignore_sync_begin(void);
28 void __tsan_go_ignore_sync_end(void);
26 29
27 // Mimic what cmd/cgo would do. 30 // Mimic what cmd/cgo would do.
28 #pragma cgo_import_static __tsan_init 31 #pragma cgo_import_static __tsan_init
29 #pragma cgo_import_static __tsan_fini 32 #pragma cgo_import_static __tsan_fini
30 #pragma cgo_import_static __tsan_map_shadow 33 #pragma cgo_import_static __tsan_map_shadow
31 #pragma cgo_import_static __tsan_finalizer_goroutine 34 #pragma cgo_import_static __tsan_finalizer_goroutine
32 #pragma cgo_import_static __tsan_go_start 35 #pragma cgo_import_static __tsan_go_start
33 #pragma cgo_import_static __tsan_go_end 36 #pragma cgo_import_static __tsan_go_end
34 #pragma cgo_import_static __tsan_malloc 37 #pragma cgo_import_static __tsan_malloc
35 #pragma cgo_import_static __tsan_acquire 38 #pragma cgo_import_static __tsan_acquire
36 #pragma cgo_import_static __tsan_release 39 #pragma cgo_import_static __tsan_release
37 #pragma cgo_import_static __tsan_release_merge 40 #pragma cgo_import_static __tsan_release_merge
41 #pragma cgo_import_static __tsan_go_ignore_sync_begin
42 #pragma cgo_import_static __tsan_go_ignore_sync_end
38 43
39 // These are called from race_amd64.s. 44 // These are called from race_amd64.s.
40 #pragma cgo_import_static __tsan_read 45 #pragma cgo_import_static __tsan_read
41 #pragma cgo_import_static __tsan_read_pc 46 #pragma cgo_import_static __tsan_read_pc
42 #pragma cgo_import_static __tsan_read_range 47 #pragma cgo_import_static __tsan_read_range
43 #pragma cgo_import_static __tsan_write 48 #pragma cgo_import_static __tsan_write
44 #pragma cgo_import_static __tsan_write_pc 49 #pragma cgo_import_static __tsan_write_pc
45 #pragma cgo_import_static __tsan_write_range 50 #pragma cgo_import_static __tsan_write_range
46 #pragma cgo_import_static __tsan_func_enter 51 #pragma cgo_import_static __tsan_func_enter
47 #pragma cgo_import_static __tsan_func_exit 52 #pragma cgo_import_static __tsan_func_exit
48 53
49 extern byte noptrdata[]; 54 #pragma cgo_import_static __tsan_go_atomic32_load
50 extern byte enoptrbss[]; 55 #pragma cgo_import_static __tsan_go_atomic64_load
56 #pragma cgo_import_static __tsan_go_atomic32_store
57 #pragma cgo_import_static __tsan_go_atomic64_store
58 #pragma cgo_import_static __tsan_go_atomic32_exchange
59 #pragma cgo_import_static __tsan_go_atomic64_exchange
60 #pragma cgo_import_static __tsan_go_atomic32_fetch_add
61 #pragma cgo_import_static __tsan_go_atomic64_fetch_add
62 #pragma cgo_import_static __tsan_go_atomic32_compare_exchange
63 #pragma cgo_import_static __tsan_go_atomic64_compare_exchange
64
65 extern byte runtime·noptrdata[];
66 extern byte runtime·enoptrbss[];
51 ·· 67 ··
52 // start/end of heap for race_amd64.s 68 // start/end of heap for race_amd64.s
53 uintptr runtime·racearenastart; 69 uintptr runtime·racearenastart;
54 uintptr runtime·racearenaend; 70 uintptr runtime·racearenaend;
55 71
56 void runtime·racefuncenter(void *callpc); 72 void runtime·racefuncenter(void *callpc);
57 void runtime·racefuncexit(void); 73 void runtime·racefuncexit(void);
58 void runtime·racereadrangepc1(void *addr, uintptr sz, void *pc); 74 void runtime·racereadrangepc1(void *addr, uintptr sz, void *pc);
59 void runtime·racewriterangepc1(void *addr, uintptr sz, void *pc); 75 void runtime·racewriterangepc1(void *addr, uintptr sz, void *pc);
60 void runtime·racesymbolizethunk(void*); 76 void runtime·racesymbolizethunk(void*);
61 77
62 // racecall allows calling an arbitrary function f from C race runtime 78 // racecall allows calling an arbitrary function f from C race runtime
63 // with up to 4 uintptr arguments. 79 // with up to 4 uintptr arguments.
64 void runtime·racecall(void(*f)(void), ...); 80 void runtime·racecall(void(*f)(void), ...);
65 81
66 // checks if the address has shadow (i.e. heap or data/bss) 82 // checks if the address has shadow (i.e. heap or data/bss)
83 #pragma textflag NOSPLIT
67 static bool 84 static bool
68 isvalidaddr(uintptr addr) 85 isvalidaddr(uintptr addr)
69 { 86 {
70 if(addr >= runtime·racearenastart && addr < runtime·racearenaend) 87 if(addr >= runtime·racearenastart && addr < runtime·racearenaend)
71 return true; 88 return true;
72 » if(addr >= (uintptr)noptrdata && addr < (uintptr)enoptrbss) 89 » if(addr >= (uintptr)runtime·noptrdata && addr < (uintptr)runtime·enoptrb ss)
73 return true; 90 return true;
74 return false; 91 return false;
75 } 92 }
76 93
94 #pragma textflag NOSPLIT
77 uintptr 95 uintptr
78 runtime·raceinit(void) 96 runtime·raceinit(void)
79 { 97 {
80 uintptr racectx, start, size; 98 uintptr racectx, start, size;
81 99
82 // cgo is required to initialize libc, which is used by race runtime 100 // cgo is required to initialize libc, which is used by race runtime
83 if(!runtime·iscgo) 101 if(!runtime·iscgo)
84 runtime·throw("raceinit: race build must use cgo"); 102 runtime·throw("raceinit: race build must use cgo");
85 runtime·racecall(__tsan_init, &racectx, runtime·racesymbolizethunk); 103 runtime·racecall(__tsan_init, &racectx, runtime·racesymbolizethunk);
86 // Round data segment to page boundaries, because it's used in mmap(). 104 // Round data segment to page boundaries, because it's used in mmap().
87 » start = (uintptr)noptrdata & ~(PageSize-1); 105 » start = (uintptr)runtime·noptrdata & ~(PageSize-1);
88 » size = ROUND((uintptr)enoptrbss - start, PageSize); 106 » size = ROUND((uintptr)runtime·enoptrbss - start, PageSize);
89 runtime·racecall(__tsan_map_shadow, start, size); 107 runtime·racecall(__tsan_map_shadow, start, size);
90 return racectx; 108 return racectx;
91 } 109 }
92 110
111 #pragma textflag NOSPLIT
93 void 112 void
94 runtime·racefini(void) 113 runtime·racefini(void)
95 { 114 {
96 runtime·racecall(__tsan_fini); 115 runtime·racecall(__tsan_fini);
97 } 116 }
98 117
118 #pragma textflag NOSPLIT
99 void 119 void
100 runtime·racemapshadow(void *addr, uintptr size) 120 runtime·racemapshadow(void *addr, uintptr size)
101 { 121 {
102 if(runtime·racearenastart == 0) 122 if(runtime·racearenastart == 0)
103 runtime·racearenastart = (uintptr)addr; 123 runtime·racearenastart = (uintptr)addr;
104 if(runtime·racearenaend < (uintptr)addr+size) 124 if(runtime·racearenaend < (uintptr)addr+size)
105 runtime·racearenaend = (uintptr)addr+size; 125 runtime·racearenaend = (uintptr)addr+size;
106 runtime·racecall(__tsan_map_shadow, addr, size); 126 runtime·racecall(__tsan_map_shadow, addr, size);
107 } 127 }
108 128
129 #pragma textflag NOSPLIT
109 void 130 void
110 runtime·racemalloc(void *p, uintptr sz) 131 runtime·racemalloc(void *p, uintptr sz)
111 { 132 {
112 runtime·racecall(__tsan_malloc, p, sz); 133 runtime·racecall(__tsan_malloc, p, sz);
113 } 134 }
114 135
136 #pragma textflag NOSPLIT
115 uintptr 137 uintptr
116 runtime·racegostart(void *pc) 138 runtime·racegostart(void *pc)
117 { 139 {
118 uintptr racectx; 140 uintptr racectx;
119 141 » G *spawng;
120 » runtime·racecall(__tsan_go_start, g->racectx, &racectx, pc); 142
143 » if(g->m->curg != nil)
144 » » spawng = g->m->curg;
145 » else
146 » » spawng = g;
147
148 » runtime·racecall(__tsan_go_start, spawng->racectx, &racectx, pc);
121 return racectx; 149 return racectx;
122 } 150 }
123 151
152 #pragma textflag NOSPLIT
124 void 153 void
125 runtime·racegoend(void) 154 runtime·racegoend(void)
126 { 155 {
127 runtime·racecall(__tsan_go_end, g->racectx); 156 runtime·racecall(__tsan_go_end, g->racectx);
128 } 157 }
129 158
159 #pragma textflag NOSPLIT
130 void 160 void
131 runtime·racewriterangepc(void *addr, uintptr sz, void *callpc, void *pc) 161 runtime·racewriterangepc(void *addr, uintptr sz, void *callpc, void *pc)
132 { 162 {
163 if(g != g->m->curg) {
164 // The call is coming from manual instrumentation of Go code run ning on g0/gsignal.
165 // Not interesting.
166 return;
167 }
133 if(callpc != nil) 168 if(callpc != nil)
134 runtime·racefuncenter(callpc); 169 runtime·racefuncenter(callpc);
135 runtime·racewriterangepc1(addr, sz, pc); 170 runtime·racewriterangepc1(addr, sz, pc);
136 if(callpc != nil) 171 if(callpc != nil)
137 runtime·racefuncexit(); 172 runtime·racefuncexit();
138 } 173 }
139 174
175 #pragma textflag NOSPLIT
140 void 176 void
141 runtime·racereadrangepc(void *addr, uintptr sz, void *callpc, void *pc) 177 runtime·racereadrangepc(void *addr, uintptr sz, void *callpc, void *pc)
142 { 178 {
179 if(g != g->m->curg) {
180 // The call is coming from manual instrumentation of Go code run ning on g0/gsignal.
181 // Not interesting.
182 return;
183 }
143 if(callpc != nil) 184 if(callpc != nil)
144 runtime·racefuncenter(callpc); 185 runtime·racefuncenter(callpc);
145 runtime·racereadrangepc1(addr, sz, pc); 186 runtime·racereadrangepc1(addr, sz, pc);
146 if(callpc != nil) 187 if(callpc != nil)
147 runtime·racefuncexit(); 188 runtime·racefuncexit();
148 } 189 }
149 190
191 #pragma textflag NOSPLIT
150 void 192 void
151 runtime·racewriteobjectpc(void *addr, Type *t, void *callpc, void *pc) 193 runtime·racewriteobjectpc(void *addr, Type *t, void *callpc, void *pc)
152 { 194 {
153 uint8 kind; 195 uint8 kind;
154 196
155 kind = t->kind & KindMask; 197 kind = t->kind & KindMask;
156 if(kind == KindArray || kind == KindStruct) 198 if(kind == KindArray || kind == KindStruct)
157 runtime·racewriterangepc(addr, t->size, callpc, pc); 199 runtime·racewriterangepc(addr, t->size, callpc, pc);
158 else 200 else
159 runtime·racewritepc(addr, callpc, pc); 201 runtime·racewritepc(addr, callpc, pc);
160 } 202 }
161 203
204 #pragma textflag NOSPLIT
162 void 205 void
163 runtime·racereadobjectpc(void *addr, Type *t, void *callpc, void *pc) 206 runtime·racereadobjectpc(void *addr, Type *t, void *callpc, void *pc)
164 { 207 {
165 uint8 kind; 208 uint8 kind;
166 209
167 kind = t->kind & KindMask; 210 kind = t->kind & KindMask;
168 if(kind == KindArray || kind == KindStruct) 211 if(kind == KindArray || kind == KindStruct)
169 runtime·racereadrangepc(addr, t->size, callpc, pc); 212 runtime·racereadrangepc(addr, t->size, callpc, pc);
170 else 213 else
171 runtime·racereadpc(addr, callpc, pc); 214 runtime·racereadpc(addr, callpc, pc);
172 } 215 }
173 216
217 #pragma textflag NOSPLIT
174 void 218 void
175 runtime·raceacquire(void *addr) 219 runtime·raceacquire(void *addr)
176 { 220 {
177 runtime·raceacquireg(g, addr); 221 runtime·raceacquireg(g, addr);
178 } 222 }
179 223
224 #pragma textflag NOSPLIT
180 void 225 void
181 runtime·raceacquireg(G *gp, void *addr) 226 runtime·raceacquireg(G *gp, void *addr)
182 { 227 {
183 if(g->raceignore || !isvalidaddr((uintptr)addr)) 228 if(g->raceignore || !isvalidaddr((uintptr)addr))
184 return; 229 return;
185 runtime·racecall(__tsan_acquire, gp->racectx, addr); 230 runtime·racecall(__tsan_acquire, gp->racectx, addr);
186 } 231 }
187 232
233 #pragma textflag NOSPLIT
188 void 234 void
189 runtime·racerelease(void *addr) 235 runtime·racerelease(void *addr)
190 { 236 {
191 if(g->raceignore || !isvalidaddr((uintptr)addr)) 237 if(g->raceignore || !isvalidaddr((uintptr)addr))
192 return; 238 return;
193 runtime·racereleaseg(g, addr); 239 runtime·racereleaseg(g, addr);
194 } 240 }
195 241
242 #pragma textflag NOSPLIT
196 void 243 void
197 runtime·racereleaseg(G *gp, void *addr) 244 runtime·racereleaseg(G *gp, void *addr)
198 { 245 {
199 if(g->raceignore || !isvalidaddr((uintptr)addr)) 246 if(g->raceignore || !isvalidaddr((uintptr)addr))
200 return; 247 return;
201 runtime·racecall(__tsan_release, gp->racectx, addr); 248 runtime·racecall(__tsan_release, gp->racectx, addr);
202 } 249 }
203 250
251 #pragma textflag NOSPLIT
204 void 252 void
205 runtime·racereleasemerge(void *addr) 253 runtime·racereleasemerge(void *addr)
206 { 254 {
207 runtime·racereleasemergeg(g, addr); 255 runtime·racereleasemergeg(g, addr);
208 } 256 }
209 257
258 #pragma textflag NOSPLIT
210 void 259 void
211 runtime·racereleasemergeg(G *gp, void *addr) 260 runtime·racereleasemergeg(G *gp, void *addr)
212 { 261 {
213 if(g->raceignore || !isvalidaddr((uintptr)addr)) 262 if(g->raceignore || !isvalidaddr((uintptr)addr))
214 return; 263 return;
215 runtime·racecall(__tsan_release_merge, gp->racectx, addr); 264 runtime·racecall(__tsan_release_merge, gp->racectx, addr);
216 } 265 }
217 266
267 #pragma textflag NOSPLIT
218 void 268 void
219 runtime·racefingo(void) 269 runtime·racefingo(void)
220 { 270 {
221 runtime·racecall(__tsan_finalizer_goroutine, g->racectx); 271 runtime·racecall(__tsan_finalizer_goroutine, g->racectx);
222 } 272 }
223 273
224 // func RaceAcquire(addr unsafe.Pointer) 274 // func RaceAcquire(addr unsafe.Pointer)
275 #pragma textflag NOSPLIT
225 void 276 void
226 runtime·RaceAcquire(void *addr) 277 runtime·RaceAcquire(void *addr)
227 { 278 {
228 runtime·raceacquire(addr); 279 runtime·raceacquire(addr);
229 } 280 }
230 281
231 // func RaceRelease(addr unsafe.Pointer) 282 // func RaceRelease(addr unsafe.Pointer)
283 #pragma textflag NOSPLIT
232 void 284 void
233 runtime·RaceRelease(void *addr) 285 runtime·RaceRelease(void *addr)
234 { 286 {
235 runtime·racerelease(addr); 287 runtime·racerelease(addr);
236 } 288 }
237 289
238 // func RaceReleaseMerge(addr unsafe.Pointer) 290 // func RaceReleaseMerge(addr unsafe.Pointer)
291 #pragma textflag NOSPLIT
239 void 292 void
240 runtime·RaceReleaseMerge(void *addr) 293 runtime·RaceReleaseMerge(void *addr)
241 { 294 {
242 runtime·racereleasemerge(addr); 295 runtime·racereleasemerge(addr);
243 } 296 }
244 297
245 // func RaceSemacquire(s *uint32)
246 void
247 runtime·RaceSemacquire(uint32 *s)
248 {
249 runtime·semacquire(s, false);
250 }
251
252 // func RaceSemrelease(s *uint32)
253 void
254 runtime·RaceSemrelease(uint32 *s)
255 {
256 runtime·semrelease(s);
257 }
258
259 // func RaceDisable() 298 // func RaceDisable()
299 #pragma textflag NOSPLIT
260 void 300 void
261 runtime·RaceDisable(void) 301 runtime·RaceDisable(void)
262 { 302 {
263 » g->raceignore++; 303 » if(g->raceignore++ == 0)
304 » » runtime·racecall(__tsan_go_ignore_sync_begin, g->racectx);
264 } 305 }
265 306
266 // func RaceEnable() 307 // func RaceEnable()
308 #pragma textflag NOSPLIT
267 void 309 void
268 runtime·RaceEnable(void) 310 runtime·RaceEnable(void)
269 { 311 {
270 » g->raceignore--; 312 » if(--g->raceignore == 0)
271 } 313 » » runtime·racecall(__tsan_go_ignore_sync_end, g->racectx);
272 314 }
273 typedef struct SymbolizeContext SymbolizeContext;
274 struct SymbolizeContext
275 {
276 » uintptr»pc;
277 » int8*» func;
278 » int8*» file;
279 » uintptr»line;
280 » uintptr»off;
281 » uintptr»res;
282 };
283
284 // Callback from C into Go, runs on g0.
285 void
286 runtime·racesymbolize(SymbolizeContext *ctx)
287 {
288 » Func *f;
289 » String file;
290
291 » f = runtime·findfunc(ctx->pc);
292 » if(f == nil) {
293 » » ctx->func = "??";
294 » » ctx->file = "-";
295 » » ctx->line = 0;
296 » » ctx->off = ctx->pc;
297 » » ctx->res = 1;
298 » » return;
299 » }
300 » ctx->func = runtime·funcname(f);
301 » ctx->line = runtime·funcline(f, ctx->pc, &file);
302 » ctx->file = (int8*)file.str; // assume zero-terminated
303 » ctx->off = ctx->pc - f->entry;
304 » ctx->res = 1;
305 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b