mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00: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:
parent
bc451b5770
commit
52d5cb2822
1 changed files with 40 additions and 24 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue