1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Implementation of the race detector API.
12 // Race runtime functions called via runtime·racecall.
13 //go:linkname __tsan_init __tsan_init
16 //go:linkname __tsan_fini __tsan_fini
19 //go:linkname __tsan_map_shadow __tsan_map_shadow
20 var __tsan_map_shadow byte
22 //go:linkname __tsan_finalizer_goroutine __tsan_finalizer_goroutine
23 var __tsan_finalizer_goroutine byte
25 //go:linkname __tsan_go_start __tsan_go_start
26 var __tsan_go_start byte
28 //go:linkname __tsan_go_end __tsan_go_end
29 var __tsan_go_end byte
31 //go:linkname __tsan_malloc __tsan_malloc
32 var __tsan_malloc byte
34 //go:linkname __tsan_acquire __tsan_acquire
35 var __tsan_acquire byte
37 //go:linkname __tsan_release __tsan_release
38 var __tsan_release byte
40 //go:linkname __tsan_release_merge __tsan_release_merge
41 var __tsan_release_merge byte
43 //go:linkname __tsan_go_ignore_sync_begin __tsan_go_ignore_sync_begin
44 var __tsan_go_ignore_sync_begin byte
46 //go:linkname __tsan_go_ignore_sync_end __tsan_go_ignore_sync_end
47 var __tsan_go_ignore_sync_end byte
49 // Mimic what cmd/cgo would do.
50 //go:cgo_import_static __tsan_init
51 //go:cgo_import_static __tsan_fini
52 //go:cgo_import_static __tsan_map_shadow
53 //go:cgo_import_static __tsan_finalizer_goroutine
54 //go:cgo_import_static __tsan_go_start
55 //go:cgo_import_static __tsan_go_end
56 //go:cgo_import_static __tsan_malloc
57 //go:cgo_import_static __tsan_acquire
58 //go:cgo_import_static __tsan_release
59 //go:cgo_import_static __tsan_release_merge
60 //go:cgo_import_static __tsan_go_ignore_sync_begin
61 //go:cgo_import_static __tsan_go_ignore_sync_end
63 // These are called from race_amd64.s.
64 //go:cgo_import_static __tsan_read
65 //go:cgo_import_static __tsan_read_pc
66 //go:cgo_import_static __tsan_read_range
67 //go:cgo_import_static __tsan_write
68 //go:cgo_import_static __tsan_write_pc
69 //go:cgo_import_static __tsan_write_range
70 //go:cgo_import_static __tsan_func_enter
71 //go:cgo_import_static __tsan_func_exit
73 //go:cgo_import_static __tsan_go_atomic32_load
74 //go:cgo_import_static __tsan_go_atomic64_load
75 //go:cgo_import_static __tsan_go_atomic32_store
76 //go:cgo_import_static __tsan_go_atomic64_store
77 //go:cgo_import_static __tsan_go_atomic32_exchange
78 //go:cgo_import_static __tsan_go_atomic64_exchange
79 //go:cgo_import_static __tsan_go_atomic32_fetch_add
80 //go:cgo_import_static __tsan_go_atomic64_fetch_add
81 //go:cgo_import_static __tsan_go_atomic32_compare_exchange
82 //go:cgo_import_static __tsan_go_atomic64_compare_exchange
84 // start/end of heap for race_amd64.s
85 var racearenastart uintptr
86 var racearenaend uintptr
88 func racefuncenter(uintptr)
90 func racereadrangepc1(uintptr, uintptr, uintptr)
91 func racewriterangepc1(uintptr, uintptr, uintptr)
92 func racesymbolizethunk(uintptr)
94 // racecall allows calling an arbitrary function f from C race runtime
95 // with up to 4 uintptr arguments.
96 func racecall(*byte, uintptr, uintptr, uintptr, uintptr)
98 // checks if the address has shadow (i.e. heap or data/bss)
100 func isvalidaddr(addr unsafe.Pointer) bool {
101 return racearenastart <= uintptr(addr) && uintptr(addr) < racearenaend ||
102 uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(addr) && uintptr(addr) < uintptr(unsafe.Pointer(&enoptrbss))
106 func raceinit() uintptr {
107 // cgo is required to initialize libc, which is used by race runtime
109 gothrow("raceinit: race build must use cgo")
113 racecall(&__tsan_init, uintptr(unsafe.Pointer(&racectx)), funcPC(racesymbolizethunk), 0, 0)
115 // Round data segment to page boundaries, because it's used in mmap().
116 start := uintptr(unsafe.Pointer(&noptrdata)) &^ (_PageSize - 1)
117 size := round(uintptr(unsafe.Pointer(&enoptrbss))-start, _PageSize)
118 racecall(&__tsan_map_shadow, start, size, 0, 0)
125 racecall(&__tsan_fini, 0, 0, 0, 0)
129 func racemapshadow(addr unsafe.Pointer, size uintptr) {
130 if racearenastart == 0 {
131 racearenastart = uintptr(addr)
133 if racearenaend < uintptr(addr)+size {
134 racearenaend = uintptr(addr) + size
136 racecall(&__tsan_map_shadow, uintptr(addr), size, 0, 0)
140 func racemalloc(p unsafe.Pointer, sz uintptr) {
141 racecall(&__tsan_malloc, uintptr(p), sz, 0, 0)
145 func racegostart(pc uintptr) uintptr {
148 if _g_.m.curg != nil {
155 racecall(&__tsan_go_start, spawng.racectx, uintptr(unsafe.Pointer(&racectx)), pc, 0)
161 racecall(&__tsan_go_end, getg().racectx, 0, 0, 0)
165 func racewriterangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) {
167 if _g_ != _g_.m.curg {
168 // The call is coming from manual instrumentation of Go code running on g0/gsignal.
173 racefuncenter(callpc)
175 racewriterangepc1(uintptr(addr), sz, pc)
182 func racereadrangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) {
184 if _g_ != _g_.m.curg {
185 // The call is coming from manual instrumentation of Go code running on g0/gsignal.
190 racefuncenter(callpc)
192 racereadrangepc1(uintptr(addr), sz, pc)
199 func racewriteobjectpc(addr unsafe.Pointer, t *_type, callpc, pc uintptr) {
200 kind := t.kind & _KindMask
201 if kind == _KindArray || kind == _KindStruct {
202 racewriterangepc(addr, t.size, callpc, pc)
204 racewritepc(addr, callpc, pc)
209 func racereadobjectpc(addr unsafe.Pointer, t *_type, callpc, pc uintptr) {
210 kind := t.kind & _KindMask
211 if kind == _KindArray || kind == _KindStruct {
212 racereadrangepc(addr, t.size, callpc, pc)
214 racereadpc(addr, callpc, pc)
219 func raceacquire(addr unsafe.Pointer) {
220 raceacquireg(getg(), addr)
224 func raceacquireg(gp *g, addr unsafe.Pointer) {
225 if getg().raceignore != 0 || !isvalidaddr(addr) {
228 racecall(&__tsan_acquire, gp.racectx, uintptr(addr), 0, 0)
232 func racerelease(addr unsafe.Pointer) {
234 if _g_.raceignore != 0 || !isvalidaddr(addr) {
237 racereleaseg(_g_, addr)
241 func racereleaseg(gp *g, addr unsafe.Pointer) {
242 if getg().raceignore != 0 || !isvalidaddr(addr) {
245 racecall(&__tsan_release, gp.racectx, uintptr(addr), 0, 0)
249 func racereleasemerge(addr unsafe.Pointer) {
250 racereleasemergeg(getg(), addr)
254 func racereleasemergeg(gp *g, addr unsafe.Pointer) {
255 if getg().raceignore != 0 || !isvalidaddr(addr) {
258 racecall(&__tsan_release_merge, gp.racectx, uintptr(addr), 0, 0)
263 racecall(&__tsan_finalizer_goroutine, getg().racectx, 0, 0, 0)
268 func RaceAcquire(addr unsafe.Pointer) {
274 func RaceRelease(addr unsafe.Pointer) {
280 func RaceReleaseMerge(addr unsafe.Pointer) {
281 racereleasemerge(addr)
286 // RaceEnable re-enables handling of race events in the current goroutine.
289 if _g_.raceignore == 0 {
290 racecall(&__tsan_go_ignore_sync_begin, _g_.racectx, 0, 0, 0)
297 // RaceDisable disables handling of race events in the current goroutine.
301 if _g_.raceignore == 0 {
302 racecall(&__tsan_go_ignore_sync_end, _g_.racectx, 0, 0, 0)