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