1
0
mirror of https://github.com/golang/go synced 2024-11-11 19:41:36 -07:00

[dev.regabi] cmd/internal/obj: access Attribute atomically

Symbol's Attributes and ABI are in the same word. In the
concurrent backend, we may read one symbol's ABI (the callee)
while setting its attributes in another goroutine.

Fix racecompile build.

Change-Id: I500e869bafdd72080119ab243db94eee3afcf926
Reviewed-on: https://go-review.googlesource.com/c/go/+/289290
Trust: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cherry Zhang 2021-02-03 18:10:04 -05:00
parent bc451b5770
commit 52d5cb2822

View File

@ -39,6 +39,7 @@ import (
"cmd/internal/sys"
"fmt"
"sync"
"sync/atomic"
)
// An Addr is an argument to an instruction.
@ -647,37 +648,52 @@ const (
attrABIBase
)
func (a Attribute) DuplicateOK() bool { return a&AttrDuplicateOK != 0 }
func (a Attribute) MakeTypelink() bool { return a&AttrMakeTypelink != 0 }
func (a Attribute) CFunc() bool { return a&AttrCFunc != 0 }
func (a Attribute) NoSplit() bool { return a&AttrNoSplit != 0 }
func (a Attribute) Leaf() bool { return a&AttrLeaf != 0 }
func (a Attribute) OnList() bool { return a&AttrOnList != 0 }
func (a Attribute) ReflectMethod() bool { return a&AttrReflectMethod != 0 }
func (a Attribute) Local() bool { return a&AttrLocal != 0 }
func (a Attribute) Wrapper() bool { return a&AttrWrapper != 0 }
func (a Attribute) NeedCtxt() bool { return a&AttrNeedCtxt != 0 }
func (a Attribute) NoFrame() bool { return a&AttrNoFrame != 0 }
func (a Attribute) Static() bool { return a&AttrStatic != 0 }
func (a Attribute) WasInlined() bool { return a&AttrWasInlined != 0 }
func (a Attribute) TopFrame() bool { return a&AttrTopFrame != 0 }
func (a Attribute) Indexed() bool { return a&AttrIndexed != 0 }
func (a Attribute) UsedInIface() bool { return a&AttrUsedInIface != 0 }
func (a Attribute) ContentAddressable() bool { return a&AttrContentAddressable != 0 }
func (a Attribute) ABIWrapper() bool { return a&AttrABIWrapper != 0 }
func (a *Attribute) load() Attribute { return Attribute(atomic.LoadUint32((*uint32)(a))) }
func (a *Attribute) DuplicateOK() bool { return a.load()&AttrDuplicateOK != 0 }
func (a *Attribute) MakeTypelink() bool { return a.load()&AttrMakeTypelink != 0 }
func (a *Attribute) CFunc() bool { return a.load()&AttrCFunc != 0 }
func (a *Attribute) NoSplit() bool { return a.load()&AttrNoSplit != 0 }
func (a *Attribute) Leaf() bool { return a.load()&AttrLeaf != 0 }
func (a *Attribute) OnList() bool { return a.load()&AttrOnList != 0 }
func (a *Attribute) ReflectMethod() bool { return a.load()&AttrReflectMethod != 0 }
func (a *Attribute) Local() bool { return a.load()&AttrLocal != 0 }
func (a *Attribute) Wrapper() bool { return a.load()&AttrWrapper != 0 }
func (a *Attribute) NeedCtxt() bool { return a.load()&AttrNeedCtxt != 0 }
func (a *Attribute) NoFrame() bool { return a.load()&AttrNoFrame != 0 }
func (a *Attribute) Static() bool { return a.load()&AttrStatic != 0 }
func (a *Attribute) WasInlined() bool { return a.load()&AttrWasInlined != 0 }
func (a *Attribute) TopFrame() bool { return a.load()&AttrTopFrame != 0 }
func (a *Attribute) Indexed() bool { return a.load()&AttrIndexed != 0 }
func (a *Attribute) UsedInIface() bool { return a.load()&AttrUsedInIface != 0 }
func (a *Attribute) ContentAddressable() bool { return a.load()&AttrContentAddressable != 0 }
func (a *Attribute) ABIWrapper() bool { return a.load()&AttrABIWrapper != 0 }
func (a *Attribute) Set(flag Attribute, value bool) {
if value {
*a |= flag
} else {
*a &^= flag
for {
v0 := a.load()
v := v0
if value {
v |= flag
} else {
v &^= flag
}
if atomic.CompareAndSwapUint32((*uint32)(a), uint32(v0), uint32(v)) {
break
}
}
}
func (a Attribute) ABI() ABI { return ABI(a / attrABIBase) }
func (a *Attribute) ABI() ABI { return ABI(a.load() / attrABIBase) }
func (a *Attribute) SetABI(abi ABI) {
const mask = 1 // Only one ABI bit for now.
*a = (*a &^ (mask * attrABIBase)) | Attribute(abi)*attrABIBase
for {
v0 := a.load()
v := (v0 &^ (mask * attrABIBase)) | Attribute(abi)*attrABIBase
if atomic.CompareAndSwapUint32((*uint32)(a), uint32(v0), uint32(v)) {
break
}
}
}
var textAttrStrings = [...]struct {