LEFT | RIGHT |
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 | 14 |
15 void runtime·racecall(void(*f)(void), ...); | 15 // Race runtime functions called via runtime·racecall. |
16 | |
17 void __tsan_init(void); | 16 void __tsan_init(void); |
18 void __tsan_fini(void); | 17 void __tsan_fini(void); |
19 void __tsan_map_shadow(void); | 18 void __tsan_map_shadow(void); |
20 void __tsan_finalizer_goroutine(void); | 19 void __tsan_finalizer_goroutine(void); |
21 void __tsan_go_start(void); | 20 void __tsan_go_start(void); |
22 void __tsan_go_end(void); | 21 void __tsan_go_end(void); |
23 void __tsan_malloc(void); | 22 void __tsan_malloc(void); |
24 void __tsan_acquire(void); | 23 void __tsan_acquire(void); |
25 void __tsan_release(void); | 24 void __tsan_release(void); |
26 void __tsan_release_merge(void); | 25 void __tsan_release_merge(void); |
27 | 26 |
28 #pragma cgo_import_static __tsan_read | 27 // Mimic what cmd/cgo would do. |
29 #pragma cgo_import_static __tsan_read_pc | |
30 #pragma cgo_import_static __tsan_read_range | |
31 #pragma cgo_import_static __tsan_read_range_pc | |
32 #pragma cgo_import_static __tsan_write | |
33 #pragma cgo_import_static __tsan_write_pc | |
34 #pragma cgo_import_static __tsan_write_range | |
35 #pragma cgo_import_static __tsan_write_range_pc | |
36 #pragma cgo_import_static __tsan_func_enter | |
37 #pragma cgo_import_static __tsan_func_exit | |
38 | |
39 #pragma cgo_import_static __tsan_init | 28 #pragma cgo_import_static __tsan_init |
40 #pragma cgo_import_static __tsan_fini | 29 #pragma cgo_import_static __tsan_fini |
41 #pragma cgo_import_static __tsan_map_shadow | 30 #pragma cgo_import_static __tsan_map_shadow |
42 #pragma cgo_import_static __tsan_finalizer_goroutine | 31 #pragma cgo_import_static __tsan_finalizer_goroutine |
43 #pragma cgo_import_static __tsan_go_start | 32 #pragma cgo_import_static __tsan_go_start |
44 #pragma cgo_import_static __tsan_go_end | 33 #pragma cgo_import_static __tsan_go_end |
45 #pragma cgo_import_static __tsan_malloc | 34 #pragma cgo_import_static __tsan_malloc |
46 #pragma cgo_import_static __tsan_acquire | 35 #pragma cgo_import_static __tsan_acquire |
47 #pragma cgo_import_static __tsan_release | 36 #pragma cgo_import_static __tsan_release |
48 #pragma cgo_import_static __tsan_release_merge | 37 #pragma cgo_import_static __tsan_release_merge |
49 | 38 |
50 #pragma cgo_export_static __tsan_symbolize | 39 // These are called from race_amd64.s. |
51 | 40 #pragma cgo_import_static __tsan_read |
52 #pragma cgo_import_dynamic _ _ "libc.so.6" | 41 #pragma cgo_import_static __tsan_read_pc |
| 42 #pragma cgo_import_static __tsan_read_range |
| 43 #pragma cgo_import_static __tsan_write |
| 44 #pragma cgo_import_static __tsan_write_pc |
| 45 #pragma cgo_import_static __tsan_write_range |
| 46 #pragma cgo_import_static __tsan_func_enter |
| 47 #pragma cgo_import_static __tsan_func_exit |
53 | 48 |
54 extern byte noptrdata[]; | 49 extern byte noptrdata[]; |
55 extern byte enoptrbss[]; | 50 extern byte enoptrbss[]; |
| 51 ·· |
| 52 // start/end of heap for race_amd64.s |
| 53 uintptr runtime·racearenastart; |
| 54 uintptr runtime·racearenaend; |
| 55 |
| 56 void runtime·racefuncenter(void *callpc); |
| 57 void runtime·racefuncexit(void); |
| 58 void runtime·racereadrangepc1(void *addr, uintptr sz, void *pc); |
| 59 void runtime·racewriterangepc1(void *addr, uintptr sz, void *pc); |
| 60 void runtime·racesymbolizethunk(void*); |
| 61 |
| 62 // racecall allows calling an arbitrary function f from C race runtime |
| 63 // with up to 4 uintptr arguments. |
| 64 void runtime·racecall(void(*f)(void), ...); |
56 | 65 |
57 uintptr | 66 uintptr |
58 runtime·raceinit(void) | 67 runtime·raceinit(void) |
59 { | 68 { |
60 uintptr racectx, start, size; | 69 uintptr racectx, start, size; |
61 | 70 |
62 // cgo is required to initialize libc, which is used by race runtime | 71 // cgo is required to initialize libc, which is used by race runtime |
63 if(!runtime·iscgo) | 72 if(!runtime·iscgo) |
64 runtime·throw("raceinit: race build must use cgo"); | 73 runtime·throw("raceinit: race build must use cgo"); |
65 » runtime·racecall(__tsan_init, &racectx); | 74 » runtime·racecall(__tsan_init, &racectx, runtime·racesymbolizethunk); |
66 // Round data segment to page boundaries, because it's used in mmap(). | 75 // Round data segment to page boundaries, because it's used in mmap(). |
67 start = (uintptr)noptrdata & ~(PageSize-1); | 76 start = (uintptr)noptrdata & ~(PageSize-1); |
68 size = ROUND((uintptr)enoptrbss - start, PageSize); | 77 size = ROUND((uintptr)enoptrbss - start, PageSize); |
69 runtime·racecall(__tsan_map_shadow, start, size); | 78 runtime·racecall(__tsan_map_shadow, start, size); |
70 return racectx; | 79 return racectx; |
71 } | 80 } |
72 | 81 |
73 void | 82 void |
74 runtime·racefini(void) | 83 runtime·racefini(void) |
75 { | 84 { |
76 runtime·racecall(__tsan_fini); | 85 runtime·racecall(__tsan_fini); |
77 } | 86 } |
78 | 87 |
79 void | 88 void |
80 runtime·racemapshadow(void *addr, uintptr size) | 89 runtime·racemapshadow(void *addr, uintptr size) |
81 { | 90 { |
| 91 if(runtime·racearenastart == 0) |
| 92 runtime·racearenastart = (uintptr)addr; |
| 93 if(runtime·racearenaend < (uintptr)addr+size) |
| 94 runtime·racearenaend = (uintptr)addr+size; |
82 runtime·racecall(__tsan_map_shadow, addr, size); | 95 runtime·racecall(__tsan_map_shadow, addr, size); |
83 } | 96 } |
84 | 97 |
85 void | 98 void |
86 runtime·racemalloc(void *p, uintptr sz) | 99 runtime·racemalloc(void *p, uintptr sz) |
87 { | 100 { |
88 » // use m->curg because runtime·stackalloc() is called from g0 | 101 » runtime·racecall(__tsan_malloc, p, sz); |
89 » if(m->curg == nil) | |
90 » » return; | |
91 » runtime·racecall(__tsan_malloc, m->curg->racectx, p, sz); | |
92 } | 102 } |
93 | 103 |
94 uintptr | 104 uintptr |
95 runtime·racegostart(void *pc) | 105 runtime·racegostart(void *pc) |
96 { | 106 { |
97 uintptr racectx; | 107 uintptr racectx; |
98 | 108 |
99 runtime·racecall(__tsan_go_start, g->racectx, &racectx, pc); | 109 runtime·racecall(__tsan_go_start, g->racectx, &racectx, pc); |
100 return racectx; | 110 return racectx; |
101 } | 111 } |
102 | 112 |
103 void | 113 void |
104 runtime·racegoend(void) | 114 runtime·racegoend(void) |
105 { | 115 { |
106 runtime·racecall(__tsan_go_end, g->racectx); | 116 runtime·racecall(__tsan_go_end, g->racectx); |
| 117 } |
| 118 |
| 119 void |
| 120 runtime·racewriterangepc(void *addr, uintptr sz, void *callpc, void *pc) |
| 121 { |
| 122 if(callpc != nil) |
| 123 runtime·racefuncenter(callpc); |
| 124 runtime·racewriterangepc1(addr, sz, pc); |
| 125 if(callpc != nil) |
| 126 runtime·racefuncexit(); |
| 127 } |
| 128 |
| 129 void |
| 130 runtime·racereadrangepc(void *addr, uintptr sz, void *callpc, void *pc) |
| 131 { |
| 132 if(callpc != nil) |
| 133 runtime·racefuncenter(callpc); |
| 134 runtime·racereadrangepc1(addr, sz, pc); |
| 135 if(callpc != nil) |
| 136 runtime·racefuncexit(); |
107 } | 137 } |
108 | 138 |
109 void | 139 void |
110 runtime·racewriteobjectpc(void *addr, Type *t, void *callpc, void *pc) | 140 runtime·racewriteobjectpc(void *addr, Type *t, void *callpc, void *pc) |
111 { | 141 { |
112 uint8 kind; | 142 uint8 kind; |
113 | 143 |
114 kind = t->kind & ~KindNoPointers; | 144 kind = t->kind & ~KindNoPointers; |
115 if(kind == KindArray || kind == KindStruct) | 145 if(kind == KindArray || kind == KindStruct) |
116 runtime·racewriterangepc(addr, t->size, callpc, pc); | 146 runtime·racewriterangepc(addr, t->size, callpc, pc); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 uintptr res; | 268 uintptr res; |
239 }; | 269 }; |
240 | 270 |
241 // Callback from C into Go, runs on g0. | 271 // Callback from C into Go, runs on g0. |
242 void | 272 void |
243 runtime·racesymbolize(SymbolizeContext *ctx) | 273 runtime·racesymbolize(SymbolizeContext *ctx) |
244 { | 274 { |
245 Func *f; | 275 Func *f; |
246 String file; | 276 String file; |
247 | 277 |
248 //runtime·printf("runtime·racesymbolize {{ (%p) %p %s %s %p %p %p\n", ctx, ctx->
pc, ctx->func, ctx->file, ctx->line, ctx->off, ctx->res); | |
249 f = runtime·findfunc(ctx->pc); | 278 f = runtime·findfunc(ctx->pc); |
250 if(f == nil) { | 279 if(f == nil) { |
251 ctx->func = "??"; | 280 ctx->func = "??"; |
252 ctx->file = "-"; | 281 ctx->file = "-"; |
253 ctx->line = 0; | 282 ctx->line = 0; |
254 ctx->off = ctx->pc; | 283 ctx->off = ctx->pc; |
255 ctx->res = 1; | 284 ctx->res = 1; |
256 //runtime·printf("runtime·racesymbolize NO (%p) %p %s %s %p %p %p\n", ctx, ctx->
pc, ctx->func, ctx->file, ctx->line, ctx->off, ctx->res); | |
257 return; | 285 return; |
258 } | 286 } |
259 ctx->func = runtime·funcname(f); | 287 ctx->func = runtime·funcname(f); |
260 ctx->line = runtime·funcline(f, ctx->pc, &file); | 288 ctx->line = runtime·funcline(f, ctx->pc, &file); |
261 ctx->file = (int8*)file.str; // assume zero-terminated | 289 ctx->file = (int8*)file.str; // assume zero-terminated |
262 ctx->off = ctx->pc - f->entry; | 290 ctx->off = ctx->pc - f->entry; |
263 ctx->res = 1; | 291 ctx->res = 1; |
264 //runtime·printf("runtime·racesymbolize OK (%p) %p %s %s %p %p %p\n", ctx, ctx->
pc, ctx->func, ctx->file, ctx->line, ctx->off, ctx->res); | 292 } |
265 } | |
LEFT | RIGHT |