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 package runtime 8 9 import ( 10 "unsafe" 11 ) 12 13 // Public race detection API, present iff build with -race. 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 RaceErrors() int { 21 var n uint64 22 racecall(&__tsan_report_count, uintptr(unsafe.Pointer(&n)), 0, 0, 0) 23 return int(n) 24 } 25 26 //go:nosplit 27 28 // RaceAcquire/RaceRelease/RaceReleaseMerge establish happens-before relations 29 // between goroutines. These inform the race detector about actual synchronization 30 // that it can't see for some reason (e.g. synchronization within RaceDisable/RaceEnable 31 // sections of code). 32 // RaceAcquire establishes a happens-before relation with the preceding 33 // RaceReleaseMerge on addr up to and including the last RaceRelease on addr. 34 // In terms of the C memory model (C11 5.1.2.4, 7.17.3), 35 // RaceAcquire is equivalent to atomic_load(memory_order_acquire). 36 func RaceAcquire(addr unsafe.Pointer) { 37 raceacquire(addr) 38 } 39 40 //go:nosplit 41 42 // RaceRelease performs a release operation on addr that 43 // can synchronize with a later RaceAcquire on addr. 44 // 45 // In terms of the C memory model, RaceRelease is equivalent to 46 // atomic_store(memory_order_release). 47 func RaceRelease(addr unsafe.Pointer) { 48 racerelease(addr) 49 } 50 51 //go:nosplit 52 53 // RaceReleaseMerge is like RaceRelease, but also establishes a happens-before 54 // relation with the preceding RaceRelease or RaceReleaseMerge on addr. 55 // 56 // In terms of the C memory model, RaceReleaseMerge is equivalent to 57 // atomic_exchange(memory_order_release). 58 func RaceReleaseMerge(addr unsafe.Pointer) { 59 racereleasemerge(addr) 60 } 61 62 //go:nosplit 63 64 // RaceDisable disables handling of race synchronization events in the current goroutine. 65 // Handling is re-enabled with RaceEnable. RaceDisable/RaceEnable can be nested. 66 // Non-synchronization events (memory accesses, function entry/exit) still affect 67 // the race detector. 68 func RaceDisable() { 69 _g_ := getg() 70 if _g_.raceignore == 0 { 71 racecall(&__tsan_go_ignore_sync_begin, _g_.racectx, 0, 0, 0) 72 } 73 _g_.raceignore++ 74 } 75 76 //go:nosplit 77 78 // RaceEnable re-enables handling of race events in the current goroutine. 79 func RaceEnable() { 80 _g_ := getg() 81 _g_.raceignore-- 82 if _g_.raceignore == 0 { 83 racecall(&__tsan_go_ignore_sync_end, _g_.racectx, 0, 0, 0) 84 } 85 } 86 87 // Private interface for the runtime. 88 89 const raceenabled = true 90 91 // For all functions accepting callerpc and pc, 92 // callerpc is a return PC of the function that calls this function, 93 // pc is start PC of the function that calls this function. 94 func raceReadObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) { 95 kind := t.kind & kindMask 96 if kind == kindArray || kind == kindStruct { 97 // for composite objects we have to read every address 98 // because a write might happen to any subobject. 99 racereadrangepc(addr, t.size, callerpc, pc) 100 } else { 101 // for non-composite objects we can read just the start 102 // address, as any write must write the first byte. 103 racereadpc(addr, callerpc, pc) 104 } 105 } 106 107 func raceWriteObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) { 108 kind := t.kind & kindMask 109 if kind == kindArray || kind == kindStruct { 110 // for composite objects we have to write every address 111 // because a write might happen to any subobject. 112 racewriterangepc(addr, t.size, callerpc, pc) 113 } else { 114 // for non-composite objects we can write just the start 115 // address, as any write must write the first byte. 116 racewritepc(addr, callerpc, pc) 117 } 118 } 119 120 //go:noescape 121 func racereadpc(addr unsafe.Pointer, callpc, pc uintptr) 122 123 //go:noescape 124 func racewritepc(addr unsafe.Pointer, callpc, pc uintptr) 125 126 type symbolizeCodeContext struct { 127 pc uintptr 128 fn *byte 129 file *byte 130 line uintptr 131 off uintptr 132 res uintptr 133 } 134 135 var qq = [...]byte{'?', '?', 0} 136 var dash = [...]byte{'-', 0} 137 138 const ( 139 raceGetProcCmd = iota 140 raceSymbolizeCodeCmd 141 raceSymbolizeDataCmd 142 ) 143 144 // Callback from C into Go, runs on g0. 145 func racecallback(cmd uintptr, ctx unsafe.Pointer) { 146 switch cmd { 147 case raceGetProcCmd: 148 throw("should have been handled by racecallbackthunk") 149 case raceSymbolizeCodeCmd: 150 raceSymbolizeCode((*symbolizeCodeContext)(ctx)) 151 case raceSymbolizeDataCmd: 152 raceSymbolizeData((*symbolizeDataContext)(ctx)) 153 default: 154 throw("unknown command") 155 } 156 } 157 158 func raceSymbolizeCode(ctx *symbolizeCodeContext) { 159 f := FuncForPC(ctx.pc) 160 if f != nil { 161 file, line := f.FileLine(ctx.pc) 162 if line != 0 { 163 ctx.fn = cfuncname(f.funcInfo()) 164 ctx.line = uintptr(line) 165 ctx.file = &bytes(file)[0] // assume NUL-terminated 166 ctx.off = ctx.pc - f.Entry() 167 ctx.res = 1 168 return 169 } 170 } 171 ctx.fn = &qq[0] 172 ctx.file = &dash[0] 173 ctx.line = 0 174 ctx.off = ctx.pc 175 ctx.res = 1 176 } 177 178 type symbolizeDataContext struct { 179 addr uintptr 180 heap uintptr 181 start uintptr 182 size uintptr 183 name *byte 184 file *byte 185 line uintptr 186 res uintptr 187 } 188 189 func raceSymbolizeData(ctx *symbolizeDataContext) { 190 if _, x, n := findObject(unsafe.Pointer(ctx.addr)); x != nil { 191 ctx.heap = 1 192 ctx.start = uintptr(x) 193 ctx.size = n 194 ctx.res = 1 195 } 196 } 197 198 // Race runtime functions called via runtimeracecall. 199 //go:linkname __tsan_init __tsan_init 200 var __tsan_init byte 201 202 //go:linkname __tsan_fini __tsan_fini 203 var __tsan_fini byte 204 205 //go:linkname __tsan_proc_create __tsan_proc_create 206 var __tsan_proc_create byte 207 208 //go:linkname __tsan_proc_destroy __tsan_proc_destroy 209 var __tsan_proc_destroy byte 210 211 //go:linkname __tsan_map_shadow __tsan_map_shadow 212 var __tsan_map_shadow byte 213 214 //go:linkname __tsan_finalizer_goroutine __tsan_finalizer_goroutine 215 var __tsan_finalizer_goroutine byte 216 217 //go:linkname __tsan_go_start __tsan_go_start 218 var __tsan_go_start byte 219 220 //go:linkname __tsan_go_end __tsan_go_end 221 var __tsan_go_end byte 222 223 //go:linkname __tsan_malloc __tsan_malloc 224 var __tsan_malloc byte 225 226 //go:linkname __tsan_free __tsan_free 227 var __tsan_free byte 228 229 //go:linkname __tsan_acquire __tsan_acquire 230 var __tsan_acquire byte 231 232 //go:linkname __tsan_release __tsan_release 233 var __tsan_release byte 234 235 //go:linkname __tsan_release_merge __tsan_release_merge 236 var __tsan_release_merge byte 237 238 //go:linkname __tsan_go_ignore_sync_begin __tsan_go_ignore_sync_begin 239 var __tsan_go_ignore_sync_begin byte 240 241 //go:linkname __tsan_go_ignore_sync_end __tsan_go_ignore_sync_end 242 var __tsan_go_ignore_sync_end byte 243 244 //go:linkname __tsan_report_count __tsan_report_count 245 var __tsan_report_count byte 246 247 // Mimic what cmd/cgo would do. 248 //go:cgo_import_static __tsan_init 249 //go:cgo_import_static __tsan_fini 250 //go:cgo_import_static __tsan_proc_create 251 //go:cgo_import_static __tsan_proc_destroy 252 //go:cgo_import_static __tsan_map_shadow 253 //go:cgo_import_static __tsan_finalizer_goroutine 254 //go:cgo_import_static __tsan_go_start 255 //go:cgo_import_static __tsan_go_end 256 //go:cgo_import_static __tsan_malloc 257 //go:cgo_import_static __tsan_free 258 //go:cgo_import_static __tsan_acquire 259 //go:cgo_import_static __tsan_release 260 //go:cgo_import_static __tsan_release_merge 261 //go:cgo_import_static __tsan_go_ignore_sync_begin 262 //go:cgo_import_static __tsan_go_ignore_sync_end 263 //go:cgo_import_static __tsan_report_count 264 265 // These are called from race_amd64.s. 266 //go:cgo_import_static __tsan_read 267 //go:cgo_import_static __tsan_read_pc 268 //go:cgo_import_static __tsan_read_range 269 //go:cgo_import_static __tsan_write 270 //go:cgo_import_static __tsan_write_pc 271 //go:cgo_import_static __tsan_write_range 272 //go:cgo_import_static __tsan_func_enter 273 //go:cgo_import_static __tsan_func_exit 274 275 //go:cgo_import_static __tsan_go_atomic32_load 276 //go:cgo_import_static __tsan_go_atomic64_load 277 //go:cgo_import_static __tsan_go_atomic32_store 278 //go:cgo_import_static __tsan_go_atomic64_store 279 //go:cgo_import_static __tsan_go_atomic32_exchange 280 //go:cgo_import_static __tsan_go_atomic64_exchange 281 //go:cgo_import_static __tsan_go_atomic32_fetch_add 282 //go:cgo_import_static __tsan_go_atomic64_fetch_add 283 //go:cgo_import_static __tsan_go_atomic32_compare_exchange 284 //go:cgo_import_static __tsan_go_atomic64_compare_exchange 285 286 // start/end of global data (data+bss). 287 var racedatastart uintptr 288 var racedataend uintptr 289 290 // start/end of heap for race_amd64.s 291 var racearenastart uintptr 292 var racearenaend uintptr 293 294 func racefuncenter(uintptr) 295 func racefuncexit() 296 func racereadrangepc1(uintptr, uintptr, uintptr) 297 func racewriterangepc1(uintptr, uintptr, uintptr) 298 func racecallbackthunk(uintptr) 299 300 // racecall allows calling an arbitrary function f from C race runtime 301 // with up to 4 uintptr arguments. 302 func racecall(*byte, uintptr, uintptr, uintptr, uintptr) 303 304 // checks if the address has shadow (i.e. heap or data/bss) 305 //go:nosplit 306 func isvalidaddr(addr unsafe.Pointer) bool { 307 return racearenastart <= uintptr(addr) && uintptr(addr) < racearenaend || 308 racedatastart <= uintptr(addr) && uintptr(addr) < racedataend 309 } 310 311 //go:nosplit 312 func raceinit() (gctx, pctx uintptr) { 313 // cgo is required to initialize libc, which is used by race runtime 314 if !iscgo { 315 throw("raceinit: race build must use cgo") 316 } 317 318 racecall(&__tsan_init, uintptr(unsafe.Pointer(&gctx)), uintptr(unsafe.Pointer(&pctx)), funcPC(racecallbackthunk), 0) 319 320 // Round data segment to page boundaries, because it's used in mmap(). 321 start := ^uintptr(0) 322 end := uintptr(0) 323 if start > firstmoduledata.noptrdata { 324 start = firstmoduledata.noptrdata 325 } 326 if start > firstmoduledata.data { 327 start = firstmoduledata.data 328 } 329 if start > firstmoduledata.noptrbss { 330 start = firstmoduledata.noptrbss 331 } 332 if start > firstmoduledata.bss { 333 start = firstmoduledata.bss 334 } 335 if end < firstmoduledata.enoptrdata { 336 end = firstmoduledata.enoptrdata 337 } 338 if end < firstmoduledata.edata { 339 end = firstmoduledata.edata 340 } 341 if end < firstmoduledata.enoptrbss { 342 end = firstmoduledata.enoptrbss 343 } 344 if end < firstmoduledata.ebss { 345 end = firstmoduledata.ebss 346 } 347 size := round(end-start, _PageSize) 348 racecall(&__tsan_map_shadow, start, size, 0, 0) 349 racedatastart = start 350 racedataend = start + size 351 352 return 353 } 354 355 var raceFiniLock mutex 356 357 //go:nosplit 358 func racefini() { 359 // racefini() can only be called once to avoid races. 360 // This eventually (via __tsan_fini) calls C.exit which has 361 // undefined behavior if called more than once. If the lock is 362 // already held it's assumed that the first caller exits the program 363 // so other calls can hang forever without an issue. 364 lock(&raceFiniLock) 365 racecall(&__tsan_fini, 0, 0, 0, 0) 366 } 367 368 //go:nosplit 369 func raceproccreate() uintptr { 370 var ctx uintptr 371 racecall(&__tsan_proc_create, uintptr(unsafe.Pointer(&ctx)), 0, 0, 0) 372 return ctx 373 } 374 375 //go:nosplit 376 func raceprocdestroy(ctx uintptr) { 377 racecall(&__tsan_proc_destroy, ctx, 0, 0, 0) 378 } 379 380 //go:nosplit 381 func racemapshadow(addr unsafe.Pointer, size uintptr) { 382 if racearenastart == 0 { 383 racearenastart = uintptr(addr) 384 } 385 if racearenaend < uintptr(addr)+size { 386 racearenaend = uintptr(addr) + size 387 } 388 racecall(&__tsan_map_shadow, uintptr(addr), size, 0, 0) 389 } 390 391 //go:nosplit 392 func racemalloc(p unsafe.Pointer, sz uintptr) { 393 racecall(&__tsan_malloc, 0, 0, uintptr(p), sz) 394 } 395 396 //go:nosplit 397 func racefree(p unsafe.Pointer, sz uintptr) { 398 racecall(&__tsan_free, uintptr(p), sz, 0, 0) 399 } 400 401 //go:nosplit 402 func racegostart(pc uintptr) uintptr { 403 _g_ := getg() 404 var spawng *g 405 if _g_.m.curg != nil { 406 spawng = _g_.m.curg 407 } else { 408 spawng = _g_ 409 } 410 411 var racectx uintptr 412 racecall(&__tsan_go_start, spawng.racectx, uintptr(unsafe.Pointer(&racectx)), pc, 0) 413 return racectx 414 } 415 416 //go:nosplit 417 func racegoend() { 418 racecall(&__tsan_go_end, getg().racectx, 0, 0, 0) 419 } 420 421 //go:nosplit 422 func racewriterangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) { 423 _g_ := getg() 424 if _g_ != _g_.m.curg { 425 // The call is coming from manual instrumentation of Go code running on g0/gsignal. 426 // Not interesting. 427 return 428 } 429 if callpc != 0 { 430 racefuncenter(callpc) 431 } 432 racewriterangepc1(uintptr(addr), sz, pc) 433 if callpc != 0 { 434 racefuncexit() 435 } 436 } 437 438 //go:nosplit 439 func racereadrangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) { 440 _g_ := getg() 441 if _g_ != _g_.m.curg { 442 // The call is coming from manual instrumentation of Go code running on g0/gsignal. 443 // Not interesting. 444 return 445 } 446 if callpc != 0 { 447 racefuncenter(callpc) 448 } 449 racereadrangepc1(uintptr(addr), sz, pc) 450 if callpc != 0 { 451 racefuncexit() 452 } 453 } 454 455 //go:nosplit 456 func raceacquire(addr unsafe.Pointer) { 457 raceacquireg(getg(), addr) 458 } 459 460 //go:nosplit 461 func raceacquireg(gp *g, addr unsafe.Pointer) { 462 if getg().raceignore != 0 || !isvalidaddr(addr) { 463 return 464 } 465 racecall(&__tsan_acquire, gp.racectx, uintptr(addr), 0, 0) 466 } 467 468 //go:nosplit 469 func racerelease(addr unsafe.Pointer) { 470 racereleaseg(getg(), addr) 471 } 472 473 //go:nosplit 474 func racereleaseg(gp *g, addr unsafe.Pointer) { 475 if getg().raceignore != 0 || !isvalidaddr(addr) { 476 return 477 } 478 racecall(&__tsan_release, gp.racectx, uintptr(addr), 0, 0) 479 } 480 481 //go:nosplit 482 func racereleasemerge(addr unsafe.Pointer) { 483 racereleasemergeg(getg(), addr) 484 } 485 486 //go:nosplit 487 func racereleasemergeg(gp *g, addr unsafe.Pointer) { 488 if getg().raceignore != 0 || !isvalidaddr(addr) { 489 return 490 } 491 racecall(&__tsan_release_merge, gp.racectx, uintptr(addr), 0, 0) 492 } 493 494 //go:nosplit 495 func racefingo() { 496 racecall(&__tsan_finalizer_goroutine, getg().racectx, 0, 0, 0) 497 } 498