mirror of
https://github.com/golang/go
synced 2024-11-19 20:54:39 -07:00
runtime: add RaceRead/RaceWrite functions
It allows to catch e.g. a data race between atomic write and non-atomic write, or Mutex.Lock() and mutex overwrite (e.g. mu = Mutex{}). R=golang-dev, rsc CC=golang-dev https://golang.org/cl/6817103
This commit is contained in:
parent
89bfddbf67
commit
51e89f59b2
@ -254,6 +254,22 @@ void runtime·RaceSemrelease(uint32 *s)
|
|||||||
runtime·semrelease(s);
|
runtime·semrelease(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func RaceRead(addr unsafe.Pointer)
|
||||||
|
#pragma textflag 7
|
||||||
|
void
|
||||||
|
runtime·RaceRead(void *addr)
|
||||||
|
{
|
||||||
|
runtime·racereadpc(addr, runtime·getcallerpc(&addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
// func RaceWrite(addr unsafe.Pointer)
|
||||||
|
#pragma textflag 7
|
||||||
|
void
|
||||||
|
runtime·RaceWrite(void *addr)
|
||||||
|
{
|
||||||
|
runtime·racewritepc(addr, runtime·getcallerpc(&addr));
|
||||||
|
}
|
||||||
|
|
||||||
// func RaceDisable()
|
// func RaceDisable()
|
||||||
void runtime·RaceDisable(void)
|
void runtime·RaceDisable(void)
|
||||||
{
|
{
|
||||||
|
@ -22,5 +22,8 @@ func RaceAcquire(addr unsafe.Pointer)
|
|||||||
func RaceRelease(addr unsafe.Pointer)
|
func RaceRelease(addr unsafe.Pointer)
|
||||||
func RaceReleaseMerge(addr unsafe.Pointer)
|
func RaceReleaseMerge(addr unsafe.Pointer)
|
||||||
|
|
||||||
|
func RaceRead(addr unsafe.Pointer)
|
||||||
|
func RaceWrite(addr unsafe.Pointer)
|
||||||
|
|
||||||
func RaceSemacquire(s *uint32)
|
func RaceSemacquire(s *uint32)
|
||||||
func RaceSemrelease(s *uint32)
|
func RaceSemrelease(s *uint32)
|
||||||
|
@ -11,6 +11,13 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// We use runtime.RaceRead() inside of atomic operations to catch races
|
||||||
|
// between atomic and non-atomic operations. It will also catch races
|
||||||
|
// between Mutex.Lock() and mutex overwrite (mu = Mutex{}). Since we use
|
||||||
|
// only RaceRead() we won't catch races with non-atomic loads.
|
||||||
|
// Otherwise (if we use RaceWrite()) we will report races
|
||||||
|
// between atomic operations (false positives).
|
||||||
|
|
||||||
var mtx uint32 = 1 // same for all
|
var mtx uint32 = 1 // same for all
|
||||||
|
|
||||||
func CompareAndSwapInt32(val *int32, old, new int32) bool {
|
func CompareAndSwapInt32(val *int32, old, new int32) bool {
|
||||||
@ -20,6 +27,7 @@ func CompareAndSwapInt32(val *int32, old, new int32) bool {
|
|||||||
func CompareAndSwapUint32(val *uint32, old, new uint32) (swapped bool) {
|
func CompareAndSwapUint32(val *uint32, old, new uint32) (swapped bool) {
|
||||||
swapped = false
|
swapped = false
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(val))
|
||||||
runtime.RaceAcquire(unsafe.Pointer(val))
|
runtime.RaceAcquire(unsafe.Pointer(val))
|
||||||
if *val == old {
|
if *val == old {
|
||||||
*val = new
|
*val = new
|
||||||
@ -37,6 +45,7 @@ func CompareAndSwapInt64(val *int64, old, new int64) bool {
|
|||||||
func CompareAndSwapUint64(val *uint64, old, new uint64) (swapped bool) {
|
func CompareAndSwapUint64(val *uint64, old, new uint64) (swapped bool) {
|
||||||
swapped = false
|
swapped = false
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(val))
|
||||||
runtime.RaceAcquire(unsafe.Pointer(val))
|
runtime.RaceAcquire(unsafe.Pointer(val))
|
||||||
if *val == old {
|
if *val == old {
|
||||||
*val = new
|
*val = new
|
||||||
@ -50,6 +59,7 @@ func CompareAndSwapUint64(val *uint64, old, new uint64) (swapped bool) {
|
|||||||
func CompareAndSwapPointer(val *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool) {
|
func CompareAndSwapPointer(val *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool) {
|
||||||
swapped = false
|
swapped = false
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(val))
|
||||||
runtime.RaceAcquire(unsafe.Pointer(val))
|
runtime.RaceAcquire(unsafe.Pointer(val))
|
||||||
if *val == old {
|
if *val == old {
|
||||||
*val = new
|
*val = new
|
||||||
@ -63,6 +73,7 @@ func CompareAndSwapPointer(val *unsafe.Pointer, old, new unsafe.Pointer) (swappe
|
|||||||
func CompareAndSwapUintptr(val *uintptr, old, new uintptr) (swapped bool) {
|
func CompareAndSwapUintptr(val *uintptr, old, new uintptr) (swapped bool) {
|
||||||
swapped = false
|
swapped = false
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(val))
|
||||||
runtime.RaceAcquire(unsafe.Pointer(val))
|
runtime.RaceAcquire(unsafe.Pointer(val))
|
||||||
if *val == old {
|
if *val == old {
|
||||||
*val = new
|
*val = new
|
||||||
@ -79,6 +90,7 @@ func AddInt32(val *int32, delta int32) int32 {
|
|||||||
|
|
||||||
func AddUint32(val *uint32, delta uint32) (new uint32) {
|
func AddUint32(val *uint32, delta uint32) (new uint32) {
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(val))
|
||||||
runtime.RaceAcquire(unsafe.Pointer(val))
|
runtime.RaceAcquire(unsafe.Pointer(val))
|
||||||
*val = *val + delta
|
*val = *val + delta
|
||||||
new = *val
|
new = *val
|
||||||
@ -94,6 +106,7 @@ func AddInt64(val *int64, delta int64) int64 {
|
|||||||
|
|
||||||
func AddUint64(val *uint64, delta uint64) (new uint64) {
|
func AddUint64(val *uint64, delta uint64) (new uint64) {
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(val))
|
||||||
runtime.RaceAcquire(unsafe.Pointer(val))
|
runtime.RaceAcquire(unsafe.Pointer(val))
|
||||||
*val = *val + delta
|
*val = *val + delta
|
||||||
new = *val
|
new = *val
|
||||||
@ -105,6 +118,7 @@ func AddUint64(val *uint64, delta uint64) (new uint64) {
|
|||||||
|
|
||||||
func AddUintptr(val *uintptr, delta uintptr) (new uintptr) {
|
func AddUintptr(val *uintptr, delta uintptr) (new uintptr) {
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(val))
|
||||||
runtime.RaceAcquire(unsafe.Pointer(val))
|
runtime.RaceAcquire(unsafe.Pointer(val))
|
||||||
*val = *val + delta
|
*val = *val + delta
|
||||||
new = *val
|
new = *val
|
||||||
@ -120,6 +134,7 @@ func LoadInt32(addr *int32) int32 {
|
|||||||
|
|
||||||
func LoadUint32(addr *uint32) (val uint32) {
|
func LoadUint32(addr *uint32) (val uint32) {
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(addr))
|
||||||
runtime.RaceAcquire(unsafe.Pointer(addr))
|
runtime.RaceAcquire(unsafe.Pointer(addr))
|
||||||
val = *addr
|
val = *addr
|
||||||
runtime.RaceSemrelease(&mtx)
|
runtime.RaceSemrelease(&mtx)
|
||||||
@ -132,6 +147,7 @@ func LoadInt64(addr *int64) int64 {
|
|||||||
|
|
||||||
func LoadUint64(addr *uint64) (val uint64) {
|
func LoadUint64(addr *uint64) (val uint64) {
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(addr))
|
||||||
runtime.RaceAcquire(unsafe.Pointer(addr))
|
runtime.RaceAcquire(unsafe.Pointer(addr))
|
||||||
val = *addr
|
val = *addr
|
||||||
runtime.RaceSemrelease(&mtx)
|
runtime.RaceSemrelease(&mtx)
|
||||||
@ -140,6 +156,7 @@ func LoadUint64(addr *uint64) (val uint64) {
|
|||||||
|
|
||||||
func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer) {
|
func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer) {
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(addr))
|
||||||
runtime.RaceAcquire(unsafe.Pointer(addr))
|
runtime.RaceAcquire(unsafe.Pointer(addr))
|
||||||
val = *addr
|
val = *addr
|
||||||
runtime.RaceSemrelease(&mtx)
|
runtime.RaceSemrelease(&mtx)
|
||||||
@ -148,6 +165,7 @@ func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer) {
|
|||||||
|
|
||||||
func LoadUintptr(addr *uintptr) (val uintptr) {
|
func LoadUintptr(addr *uintptr) (val uintptr) {
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(val))
|
||||||
runtime.RaceAcquire(unsafe.Pointer(addr))
|
runtime.RaceAcquire(unsafe.Pointer(addr))
|
||||||
val = *addr
|
val = *addr
|
||||||
runtime.RaceSemrelease(&mtx)
|
runtime.RaceSemrelease(&mtx)
|
||||||
@ -160,6 +178,7 @@ func StoreInt32(addr *int32, val int32) {
|
|||||||
|
|
||||||
func StoreUint32(addr *uint32, val uint32) {
|
func StoreUint32(addr *uint32, val uint32) {
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(addr))
|
||||||
*addr = val
|
*addr = val
|
||||||
runtime.RaceRelease(unsafe.Pointer(addr))
|
runtime.RaceRelease(unsafe.Pointer(addr))
|
||||||
runtime.RaceSemrelease(&mtx)
|
runtime.RaceSemrelease(&mtx)
|
||||||
@ -171,6 +190,7 @@ func StoreInt64(addr *int64, val int64) {
|
|||||||
|
|
||||||
func StoreUint64(addr *uint64, val uint64) {
|
func StoreUint64(addr *uint64, val uint64) {
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(addr))
|
||||||
*addr = val
|
*addr = val
|
||||||
runtime.RaceRelease(unsafe.Pointer(addr))
|
runtime.RaceRelease(unsafe.Pointer(addr))
|
||||||
runtime.RaceSemrelease(&mtx)
|
runtime.RaceSemrelease(&mtx)
|
||||||
@ -178,6 +198,7 @@ func StoreUint64(addr *uint64, val uint64) {
|
|||||||
|
|
||||||
func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer) {
|
func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer) {
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(val))
|
||||||
*addr = val
|
*addr = val
|
||||||
runtime.RaceRelease(unsafe.Pointer(addr))
|
runtime.RaceRelease(unsafe.Pointer(addr))
|
||||||
runtime.RaceSemrelease(&mtx)
|
runtime.RaceSemrelease(&mtx)
|
||||||
@ -185,6 +206,7 @@ func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer) {
|
|||||||
|
|
||||||
func StoreUintptr(addr *uintptr, val uintptr) {
|
func StoreUintptr(addr *uintptr, val uintptr) {
|
||||||
runtime.RaceSemacquire(&mtx)
|
runtime.RaceSemacquire(&mtx)
|
||||||
|
runtime.RaceRead(unsafe.Pointer(val))
|
||||||
*addr = val
|
*addr = val
|
||||||
runtime.RaceRelease(unsafe.Pointer(addr))
|
runtime.RaceRelease(unsafe.Pointer(addr))
|
||||||
runtime.RaceSemrelease(&mtx)
|
runtime.RaceSemrelease(&mtx)
|
||||||
|
Loading…
Reference in New Issue
Block a user