mirror of
https://github.com/golang/go
synced 2024-11-23 06:50:05 -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:
parent
bc451b5770
commit
52d5cb2822
@ -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…
Reference in New Issue
Block a user