2012-10-07 12:05:32 -06:00
|
|
|
// Copyright 2012 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
// +build race
|
|
|
|
|
|
|
|
// Public race detection API, present iff build with -race.
|
|
|
|
|
|
|
|
package runtime
|
|
|
|
|
|
|
|
import (
|
|
|
|
"unsafe"
|
|
|
|
)
|
|
|
|
|
2012-11-14 05:51:23 -07:00
|
|
|
func RaceRead(addr unsafe.Pointer)
|
|
|
|
func RaceWrite(addr unsafe.Pointer)
|
2013-06-10 12:40:35 -06:00
|
|
|
func RaceReadRange(addr unsafe.Pointer, len int)
|
|
|
|
func RaceWriteRange(addr unsafe.Pointer, len int)
|
2012-11-14 05:51:23 -07:00
|
|
|
|
2012-10-07 12:05:32 -06:00
|
|
|
func RaceSemacquire(s *uint32)
|
|
|
|
func RaceSemrelease(s *uint32)
|
2014-06-17 00:03:03 -06:00
|
|
|
|
|
|
|
// private interface for the runtime
|
|
|
|
const raceenabled = true
|
2014-07-16 15:16:19 -06:00
|
|
|
|
|
|
|
func raceReadObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) {
|
2014-07-31 10:32:09 -06:00
|
|
|
kind := t.kind & kindMask
|
2014-07-16 15:16:19 -06:00
|
|
|
if kind == kindArray || kind == kindStruct {
|
|
|
|
// for composite objects we have to read every address
|
|
|
|
// because a write might happen to any subobject.
|
2014-09-04 13:53:45 -06:00
|
|
|
racereadrangepc(addr, t.size, callerpc, pc)
|
2014-07-16 15:16:19 -06:00
|
|
|
} else {
|
|
|
|
// for non-composite objects we can read just the start
|
|
|
|
// address, as any write must write the first byte.
|
|
|
|
racereadpc(addr, callerpc, pc)
|
|
|
|
}
|
|
|
|
}
|
2014-09-02 15:13:29 -06:00
|
|
|
|
|
|
|
func raceWriteObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) {
|
|
|
|
kind := t.kind & kindMask
|
|
|
|
if kind == kindArray || kind == kindStruct {
|
|
|
|
// for composite objects we have to write every address
|
|
|
|
// because a write might happen to any subobject.
|
2014-09-04 13:53:45 -06:00
|
|
|
racewriterangepc(addr, t.size, callerpc, pc)
|
2014-09-02 15:13:29 -06:00
|
|
|
} else {
|
|
|
|
// for non-composite objects we can write just the start
|
|
|
|
// address, as any write must write the first byte.
|
|
|
|
racewritepc(addr, callerpc, pc)
|
|
|
|
}
|
|
|
|
}
|
2014-09-04 13:53:45 -06:00
|
|
|
|
|
|
|
//go:noescape
|
|
|
|
func racereadpc(addr unsafe.Pointer, callpc, pc uintptr)
|
|
|
|
|
|
|
|
//go:noescape
|
|
|
|
func racewritepc(addr unsafe.Pointer, callpc, pc uintptr)
|
|
|
|
|
|
|
|
type symbolizeContext struct {
|
|
|
|
pc uintptr
|
|
|
|
fn *byte
|
|
|
|
file *byte
|
|
|
|
line uintptr
|
|
|
|
off uintptr
|
|
|
|
res uintptr
|
|
|
|
}
|
|
|
|
|
|
|
|
var qq = [...]byte{'?', '?', 0}
|
|
|
|
var dash = [...]byte{'-', 0}
|
|
|
|
|
|
|
|
// Callback from C into Go, runs on g0.
|
|
|
|
func racesymbolize(ctx *symbolizeContext) {
|
|
|
|
f := findfunc(ctx.pc)
|
|
|
|
if f == nil {
|
|
|
|
ctx.fn = &qq[0]
|
|
|
|
ctx.file = &dash[0]
|
|
|
|
ctx.line = 0
|
|
|
|
ctx.off = ctx.pc
|
|
|
|
ctx.res = 1
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.fn = funcname(f)
|
|
|
|
var file string
|
|
|
|
ctx.line = uintptr(funcline(f, ctx.pc, &file))
|
|
|
|
ctx.file = &bytes(file)[0] // assume NUL-terminated
|
|
|
|
ctx.off = ctx.pc - f.entry
|
|
|
|
ctx.res = 1
|
|
|
|
return
|
|
|
|
}
|