github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/src/runtime/race.go (about) 1 // Copyright 2012 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. 4 5 // +build race 6 7 // Public race detection API, present iff build with -race. 8 9 package runtime 10 11 import ( 12 "unsafe" 13 ) 14 15 func RaceRead(addr unsafe.Pointer) 16 func RaceWrite(addr unsafe.Pointer) 17 func RaceReadRange(addr unsafe.Pointer, len int) 18 func RaceWriteRange(addr unsafe.Pointer, len int) 19 20 func RaceSemacquire(s *uint32) 21 func RaceSemrelease(s *uint32) 22 23 // private interface for the runtime 24 const raceenabled = true 25 26 // For all functions accepting callerpc and pc, 27 // callerpc is a return PC of the function that calls this function, 28 // pc is start PC of the function that calls this function. 29 func raceReadObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) { 30 kind := t.kind & kindMask 31 if kind == kindArray || kind == kindStruct { 32 // for composite objects we have to read every address 33 // because a write might happen to any subobject. 34 racereadrangepc(addr, t.size, callerpc, pc) 35 } else { 36 // for non-composite objects we can read just the start 37 // address, as any write must write the first byte. 38 racereadpc(addr, callerpc, pc) 39 } 40 } 41 42 func raceWriteObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) { 43 kind := t.kind & kindMask 44 if kind == kindArray || kind == kindStruct { 45 // for composite objects we have to write every address 46 // because a write might happen to any subobject. 47 racewriterangepc(addr, t.size, callerpc, pc) 48 } else { 49 // for non-composite objects we can write just the start 50 // address, as any write must write the first byte. 51 racewritepc(addr, callerpc, pc) 52 } 53 } 54 55 //go:noescape 56 func racereadpc(addr unsafe.Pointer, callpc, pc uintptr) 57 58 //go:noescape 59 func racewritepc(addr unsafe.Pointer, callpc, pc uintptr) 60 61 type symbolizeContext struct { 62 pc uintptr 63 fn *byte 64 file *byte 65 line uintptr 66 off uintptr 67 res uintptr 68 } 69 70 var qq = [...]byte{'?', '?', 0} 71 var dash = [...]byte{'-', 0} 72 73 // Callback from C into Go, runs on g0. 74 func racesymbolize(ctx *symbolizeContext) { 75 f := findfunc(ctx.pc) 76 if f == nil { 77 ctx.fn = &qq[0] 78 ctx.file = &dash[0] 79 ctx.line = 0 80 ctx.off = ctx.pc 81 ctx.res = 1 82 return 83 } 84 85 ctx.fn = cfuncname(f) 86 file, line := funcline(f, ctx.pc) 87 ctx.line = uintptr(line) 88 ctx.file = &bytes(file)[0] // assume NUL-terminated 89 ctx.off = ctx.pc - f.entry 90 ctx.res = 1 91 return 92 } 93 94 // Race runtime functions called via runtime·racecall. 95 //go:linkname __tsan_init __tsan_init 96 var __tsan_init byte 97 98 //go:linkname __tsan_fini __tsan_fini 99 var __tsan_fini byte 100 101 //go:linkname __tsan_map_shadow __tsan_map_shadow 102 var __tsan_map_shadow byte 103 104 //go:linkname __tsan_finalizer_goroutine __tsan_finalizer_goroutine 105 var __tsan_finalizer_goroutine byte 106 107 //go:linkname __tsan_go_start __tsan_go_start 108 var __tsan_go_start byte 109 110 //go:linkname __tsan_go_end __tsan_go_end 111 var __tsan_go_end byte 112 113 //go:linkname __tsan_malloc __tsan_malloc 114 var __tsan_malloc byte 115 116 //go:linkname __tsan_acquire __tsan_acquire 117 var __tsan_acquire byte 118 119 //go:linkname __tsan_release __tsan_release 120 var __tsan_release byte 121 122 //go:linkname __tsan_release_merge __tsan_release_merge 123 var __tsan_release_merge byte 124 125 //go:linkname __tsan_go_ignore_sync_begin __tsan_go_ignore_sync_begin 126 var __tsan_go_ignore_sync_begin byte 127 128 //go:linkname __tsan_go_ignore_sync_end __tsan_go_ignore_sync_end 129 var __tsan_go_ignore_sync_end byte 130 131 // Mimic what cmd/cgo would do. 132 //go:cgo_import_static __tsan_init 133 //go:cgo_import_static __tsan_fini 134 //go:cgo_import_static __tsan_map_shadow 135 //go:cgo_import_static __tsan_finalizer_goroutine 136 //go:cgo_import_static __tsan_go_start 137 //go:cgo_import_static __tsan_go_end 138 //go:cgo_import_static __tsan_malloc 139 //go:cgo_import_static __tsan_acquire 140 //go:cgo_import_static __tsan_release 141 //go:cgo_import_static __tsan_release_merge 142 //go:cgo_import_static __tsan_go_ignore_sync_begin 143 //go:cgo_import_static __tsan_go_ignore_sync_end 144 145 // These are called from race_amd64.s. 146 //go:cgo_import_static __tsan_read 147 //go:cgo_import_static __tsan_read_pc 148 //go:cgo_import_static __tsan_read_range 149 //go:cgo_import_static __tsan_write 150 //go:cgo_import_static __tsan_write_pc 151 //go:cgo_import_static __tsan_write_range 152 //go:cgo_import_static __tsan_func_enter 153 //go:cgo_import_static __tsan_func_exit 154 155 //go:cgo_import_static __tsan_go_atomic32_load 156 //go:cgo_import_static __tsan_go_atomic64_load 157 //go:cgo_import_static __tsan_go_atomic32_store 158 //go:cgo_import_static __tsan_go_atomic64_store 159 //go:cgo_import_static __tsan_go_atomic32_exchange 160 //go:cgo_import_static __tsan_go_atomic64_exchange 161 //go:cgo_import_static __tsan_go_atomic32_fetch_add 162 //go:cgo_import_static __tsan_go_atomic64_fetch_add 163 //go:cgo_import_static __tsan_go_atomic32_compare_exchange 164 //go:cgo_import_static __tsan_go_atomic64_compare_exchange 165 166 // start/end of global data (data+bss). 167 var racedatastart uintptr 168 var racedataend uintptr 169 170 // start/end of heap for race_amd64.s 171 var racearenastart uintptr 172 var racearenaend uintptr 173 174 func racefuncenter(uintptr) 175 func racefuncexit() 176 func racereadrangepc1(uintptr, uintptr, uintptr) 177 func racewriterangepc1(uintptr, uintptr, uintptr) 178 func racesymbolizethunk(uintptr) 179 180 // racecall allows calling an arbitrary function f from C race runtime 181 // with up to 4 uintptr arguments. 182 func racecall(*byte, uintptr, uintptr, uintptr, uintptr) 183 184 // checks if the address has shadow (i.e. heap or data/bss) 185 //go:nosplit 186 func isvalidaddr(addr unsafe.Pointer) bool { 187 return racearenastart <= uintptr(addr) && uintptr(addr) < racearenaend || 188 racedatastart <= uintptr(addr) && uintptr(addr) < racedataend 189 } 190 191 //go:nosplit 192 func raceinit() uintptr { 193 // cgo is required to initialize libc, which is used by race runtime 194 if !iscgo { 195 throw("raceinit: race build must use cgo") 196 } 197 198 var racectx uintptr 199 racecall(&__tsan_init, uintptr(unsafe.Pointer(&racectx)), funcPC(racesymbolizethunk), 0, 0) 200 201 // Round data segment to page boundaries, because it's used in mmap(). 202 start := ^uintptr(0) 203 end := uintptr(0) 204 if start > firstmoduledata.noptrdata { 205 start = firstmoduledata.noptrdata 206 } 207 if start > firstmoduledata.data { 208 start = firstmoduledata.data 209 } 210 if start > firstmoduledata.noptrbss { 211 start = firstmoduledata.noptrbss 212 } 213 if start > firstmoduledata.bss { 214 start = firstmoduledata.bss 215 } 216 if end < firstmoduledata.enoptrdata { 217 end = firstmoduledata.enoptrdata 218 } 219 if end < firstmoduledata.edata { 220 end = firstmoduledata.edata 221 } 222 if end < firstmoduledata.enoptrbss { 223 end = firstmoduledata.enoptrbss 224 } 225 if end < firstmoduledata.ebss { 226 end = firstmoduledata.ebss 227 } 228 size := round(end-start, _PageSize) 229 racecall(&__tsan_map_shadow, start, size, 0, 0) 230 racedatastart = start 231 racedataend = start + size 232 233 return racectx 234 } 235 236 //go:nosplit 237 func racefini() { 238 racecall(&__tsan_fini, 0, 0, 0, 0) 239 } 240 241 //go:nosplit 242 func racemapshadow(addr unsafe.Pointer, size uintptr) { 243 if racearenastart == 0 { 244 racearenastart = uintptr(addr) 245 } 246 if racearenaend < uintptr(addr)+size { 247 racearenaend = uintptr(addr) + size 248 } 249 racecall(&__tsan_map_shadow, uintptr(addr), size, 0, 0) 250 } 251 252 //go:nosplit 253 func racemalloc(p unsafe.Pointer, sz uintptr) { 254 racecall(&__tsan_malloc, uintptr(p), sz, 0, 0) 255 } 256 257 //go:nosplit 258 func racegostart(pc uintptr) uintptr { 259 _g_ := getg() 260 var spawng *g 261 if _g_.m.curg != nil { 262 spawng = _g_.m.curg 263 } else { 264 spawng = _g_ 265 } 266 267 var racectx uintptr 268 racecall(&__tsan_go_start, spawng.racectx, uintptr(unsafe.Pointer(&racectx)), pc, 0) 269 return racectx 270 } 271 272 //go:nosplit 273 func racegoend() { 274 racecall(&__tsan_go_end, getg().racectx, 0, 0, 0) 275 } 276 277 //go:nosplit 278 func racewriterangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) { 279 _g_ := getg() 280 if _g_ != _g_.m.curg { 281 // The call is coming from manual instrumentation of Go code running on g0/gsignal. 282 // Not interesting. 283 return 284 } 285 if callpc != 0 { 286 racefuncenter(callpc) 287 } 288 racewriterangepc1(uintptr(addr), sz, pc) 289 if callpc != 0 { 290 racefuncexit() 291 } 292 } 293 294 //go:nosplit 295 func racereadrangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) { 296 _g_ := getg() 297 if _g_ != _g_.m.curg { 298 // The call is coming from manual instrumentation of Go code running on g0/gsignal. 299 // Not interesting. 300 return 301 } 302 if callpc != 0 { 303 racefuncenter(callpc) 304 } 305 racereadrangepc1(uintptr(addr), sz, pc) 306 if callpc != 0 { 307 racefuncexit() 308 } 309 } 310 311 //go:nosplit 312 func raceacquire(addr unsafe.Pointer) { 313 raceacquireg(getg(), addr) 314 } 315 316 //go:nosplit 317 func raceacquireg(gp *g, addr unsafe.Pointer) { 318 if getg().raceignore != 0 || !isvalidaddr(addr) { 319 return 320 } 321 racecall(&__tsan_acquire, gp.racectx, uintptr(addr), 0, 0) 322 } 323 324 //go:nosplit 325 func racerelease(addr unsafe.Pointer) { 326 _g_ := getg() 327 if _g_.raceignore != 0 || !isvalidaddr(addr) { 328 return 329 } 330 racereleaseg(_g_, addr) 331 } 332 333 //go:nosplit 334 func racereleaseg(gp *g, addr unsafe.Pointer) { 335 if getg().raceignore != 0 || !isvalidaddr(addr) { 336 return 337 } 338 racecall(&__tsan_release, gp.racectx, uintptr(addr), 0, 0) 339 } 340 341 //go:nosplit 342 func racereleasemerge(addr unsafe.Pointer) { 343 racereleasemergeg(getg(), addr) 344 } 345 346 //go:nosplit 347 func racereleasemergeg(gp *g, addr unsafe.Pointer) { 348 if getg().raceignore != 0 || !isvalidaddr(addr) { 349 return 350 } 351 racecall(&__tsan_release_merge, gp.racectx, uintptr(addr), 0, 0) 352 } 353 354 //go:nosplit 355 func racefingo() { 356 racecall(&__tsan_finalizer_goroutine, getg().racectx, 0, 0, 0) 357 } 358 359 //go:nosplit 360 361 func RaceAcquire(addr unsafe.Pointer) { 362 raceacquire(addr) 363 } 364 365 //go:nosplit 366 367 func RaceRelease(addr unsafe.Pointer) { 368 racerelease(addr) 369 } 370 371 //go:nosplit 372 373 func RaceReleaseMerge(addr unsafe.Pointer) { 374 racereleasemerge(addr) 375 } 376 377 //go:nosplit 378 379 // RaceDisable disables handling of race events in the current goroutine. 380 func RaceDisable() { 381 _g_ := getg() 382 if _g_.raceignore == 0 { 383 racecall(&__tsan_go_ignore_sync_begin, _g_.racectx, 0, 0, 0) 384 } 385 _g_.raceignore++ 386 } 387 388 //go:nosplit 389 390 // RaceEnable re-enables handling of race events in the current goroutine. 391 func RaceEnable() { 392 _g_ := getg() 393 _g_.raceignore-- 394 if _g_.raceignore == 0 { 395 racecall(&__tsan_go_ignore_sync_end, _g_.racectx, 0, 0, 0) 396 } 397 }