cmd/compile, runtime: add new lightweight atomics for ppc64x

This change creates the infrastructure for new lightweight atomics
primitives in runtime/internal/atomic:

- LoadAcq, for load-acquire
- StoreRel, for store-release
- CasRel, for Compare-and-Swap-release

and implements them for ppc64x. There is visible performance improvement
in producer-consumer scenarios, like BenchmarkChanProdCons*:

benchmark                           old ns/op     new ns/op     delta
BenchmarkChanProdCons0-48           2034          2034          +0.00%
BenchmarkChanProdCons10-48          1798          1608          -10.57%
BenchmarkChanProdCons100-48         1596          1585          -0.69%
BenchmarkChanProdConsWork0-48       2084          2046          -1.82%
BenchmarkChanProdConsWork10-48      1829          1668          -8.80%
BenchmarkChanProdConsWork100-48     1650          1650          +0.00%

Fixes #21348

Change-Id: I1f6ce377e4a0fe4bd7f5f775e8036f50070ad8db
Reviewed-on: https://go-review.googlesource.com/c/142277
Run-TryBot: Lynn Boger <laboger@linux.vnet.ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Carlos Eduardo Seo 2018-08-06 15:36:16 -05:00 committed by Lynn Boger
parent 5dbc67a99a
commit 5c472132bf
29 changed files with 386 additions and 50 deletions

View File

@ -2862,6 +2862,7 @@ func init() {
var all []*sys.Arch
var p4 []*sys.Arch
var p8 []*sys.Arch
var lwatomics []*sys.Arch
for _, a := range sys.Archs {
all = append(all, a)
if a.PtrSize == 4 {
@ -2869,6 +2870,9 @@ func init() {
} else {
p8 = append(p8, a)
}
if a.Family != sys.PPC64 {
lwatomics = append(lwatomics, a)
}
}
// add adds the intrinsic b for pkg.fn for the given list of architectures.
@ -2985,6 +2989,13 @@ func init() {
return s.newValue1(ssa.OpSelect0, types.Types[TUINT64], v)
},
sys.AMD64, sys.ARM64, sys.S390X, sys.MIPS64, sys.PPC64)
addF("runtime/internal/atomic", "LoadAcq",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
v := s.newValue2(ssa.OpAtomicLoadAcq32, types.NewTuple(types.Types[TUINT32], types.TypeMem), args[0], s.mem())
s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
return s.newValue1(ssa.OpSelect0, types.Types[TUINT32], v)
},
sys.PPC64)
addF("runtime/internal/atomic", "Loadp",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
v := s.newValue2(ssa.OpAtomicLoadPtr, types.NewTuple(s.f.Config.Types.BytePtr, types.TypeMem), args[0], s.mem())
@ -3011,6 +3022,12 @@ func init() {
return nil
},
sys.AMD64, sys.ARM64, sys.S390X, sys.MIPS, sys.MIPS64)
addF("runtime/internal/atomic", "StoreRel",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
s.vars[&memVar] = s.newValue3(ssa.OpAtomicStoreRel32, types.TypeMem, args[0], args[1], s.mem())
return nil
},
sys.PPC64)
addF("runtime/internal/atomic", "Xchg",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
@ -3098,6 +3115,13 @@ func init() {
return s.newValue1(ssa.OpSelect0, types.Types[TBOOL], v)
},
sys.AMD64, sys.ARM64, sys.S390X, sys.MIPS64, sys.PPC64)
addF("runtime/internal/atomic", "CasRel",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
v := s.newValue4(ssa.OpAtomicCompareAndSwap32, types.NewTuple(types.Types[TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem())
s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
return s.newValue1(ssa.OpSelect0, types.Types[TBOOL], v)
},
sys.PPC64)
addF("runtime/internal/atomic", "And8",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
@ -3118,8 +3142,10 @@ func init() {
alias("runtime/internal/atomic", "Loaduint", "runtime/internal/atomic", "Load64", p8...)
alias("runtime/internal/atomic", "Loaduintptr", "runtime/internal/atomic", "Load", p4...)
alias("runtime/internal/atomic", "Loaduintptr", "runtime/internal/atomic", "Load64", p8...)
alias("runtime/internal/atomic", "LoadAcq", "runtime/internal/atomic", "Load", lwatomics...)
alias("runtime/internal/atomic", "Storeuintptr", "runtime/internal/atomic", "Store", p4...)
alias("runtime/internal/atomic", "Storeuintptr", "runtime/internal/atomic", "Store64", p8...)
alias("runtime/internal/atomic", "StoreRel", "runtime/internal/atomic", "Store", lwatomics...)
alias("runtime/internal/atomic", "Xchguintptr", "runtime/internal/atomic", "Xchg", p4...)
alias("runtime/internal/atomic", "Xchguintptr", "runtime/internal/atomic", "Xchg64", p8...)
alias("runtime/internal/atomic", "Xadduintptr", "runtime/internal/atomic", "Xadd", p4...)
@ -3128,6 +3154,7 @@ func init() {
alias("runtime/internal/atomic", "Casuintptr", "runtime/internal/atomic", "Cas64", p8...)
alias("runtime/internal/atomic", "Casp1", "runtime/internal/atomic", "Cas", p4...)
alias("runtime/internal/atomic", "Casp1", "runtime/internal/atomic", "Cas64", p8...)
alias("runtime/internal/atomic", "CasRel", "runtime/internal/atomic", "Cas", lwatomics...)
alias("runtime/internal/sys", "Ctz8", "math/bits", "TrailingZeros8", all...)

View File

@ -313,9 +313,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
}
arg0 := v.Args[0].Reg()
out := v.Reg0()
// SYNC
psync := s.Prog(ppc64.ASYNC)
psync.To.Type = obj.TYPE_NONE
// SYNC when AuxInt == 1; otherwise, load-acquire
if v.AuxInt == 1 {
psync := s.Prog(ppc64.ASYNC)
psync.To.Type = obj.TYPE_NONE
}
// Load
p := s.Prog(ld)
p.From.Type = obj.TYPE_MEM
@ -338,7 +340,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case ssa.OpPPC64LoweredAtomicStore32,
ssa.OpPPC64LoweredAtomicStore64:
// SYNC
// SYNC or LWSYNC
// MOVD/MOVW arg1,(arg0)
st := ppc64.AMOVD
if v.Op == ssa.OpPPC64LoweredAtomicStore32 {
@ -346,8 +348,13 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
}
arg0 := v.Args[0].Reg()
arg1 := v.Args[1].Reg()
// If AuxInt == 0, LWSYNC (Store-Release), else SYNC
// SYNC
psync := s.Prog(ppc64.ASYNC)
syncOp := ppc64.ASYNC
if v.AuxInt == 0 {
syncOp = ppc64.ALWSYNC
}
psync := s.Prog(syncOp)
psync.To.Type = obj.TYPE_NONE
// Store
p := s.Prog(st)
@ -360,12 +367,12 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
ssa.OpPPC64LoweredAtomicCas32:
// LWSYNC
// loop:
// LDAR (Rarg0), Rtmp
// LDAR (Rarg0), MutexHint, Rtmp
// CMP Rarg1, Rtmp
// BNE fail
// STDCCC Rarg2, (Rarg0)
// BNE loop
// LWSYNC
// LWSYNC // Only for sequential consistency; not required in CasRel.
// MOVD $1, Rout
// BR end
// fail:
@ -393,6 +400,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.From.Reg = r0
p.To.Type = obj.TYPE_REG
p.To.Reg = ppc64.REGTMP
// If it is a Compare-and-Swap-Release operation, set the EH field with
// the release hint.
if v.AuxInt == 0 {
p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: 0})
}
// CMP reg1,reg2
p1 := s.Prog(cmp)
p1.From.Type = obj.TYPE_REG
@ -414,8 +426,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
gc.Patch(p4, p)
// LWSYNC - Assuming shared data not write-through-required nor
// caching-inhibited. See Appendix B.2.1.1 in the ISA 2.07b.
plwsync2 := s.Prog(ppc64.ALWSYNC)
plwsync2.To.Type = obj.TYPE_NONE
// If the operation is a CAS-Release, then synchronization is not necessary.
if v.AuxInt != 0 {
plwsync2 := s.Prog(ppc64.ALWSYNC)
plwsync2.To.Type = obj.TYPE_NONE
}
// return true
p5 := s.Prog(ppc64.AMOVD)
p5.From.Type = obj.TYPE_CONST

View File

@ -896,16 +896,19 @@
(MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} x mem)
// atomic intrinsics
(AtomicLoad(32|64|Ptr) ptr mem) -> (LoweredAtomicLoad(32|64|Ptr) ptr mem)
(AtomicLoad(32|64|Ptr) ptr mem) -> (LoweredAtomicLoad(32|64|Ptr) [1] ptr mem)
(AtomicLoadAcq32 ptr mem) -> (LoweredAtomicLoad32 [0] ptr mem)
(AtomicStore(32|64) ptr val mem) -> (LoweredAtomicStore(32|64) ptr val mem)
(AtomicStore(32|64) ptr val mem) -> (LoweredAtomicStore(32|64) [1] ptr val mem)
(AtomicStoreRel32 ptr val mem) -> (LoweredAtomicStore32 [0] ptr val mem)
//(AtomicStorePtrNoWB ptr val mem) -> (STLR ptr val mem)
(AtomicExchange(32|64) ptr val mem) -> (LoweredAtomicExchange(32|64) ptr val mem)
(AtomicAdd(32|64) ptr val mem) -> (LoweredAtomicAdd(32|64) ptr val mem)
(AtomicCompareAndSwap(32|64) ptr old new_ mem) -> (LoweredAtomicCas(32|64) ptr old new_ mem)
(AtomicCompareAndSwap(32|64) ptr old new_ mem) -> (LoweredAtomicCas(32|64) [1] ptr old new_ mem)
(AtomicCompareAndSwapRel32 ptr old new_ mem) -> (LoweredAtomicCas32 [0] ptr old new_ mem)
(AtomicAnd8 ptr val mem) -> (LoweredAtomicAnd8 ptr val mem)
(AtomicOr8 ptr val mem) -> (LoweredAtomicOr8 ptr val mem)

View File

@ -470,12 +470,12 @@ func init() {
faultOnNilArg1: true,
},
{name: "LoweredAtomicStore32", argLength: 3, reg: gpstore, typ: "Mem", faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicStore64", argLength: 3, reg: gpstore, typ: "Mem", faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicStore32", argLength: 3, reg: gpstore, typ: "Mem", aux: "Int64", faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicStore64", argLength: 3, reg: gpstore, typ: "Mem", aux: "Int64", faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicLoad32", argLength: 2, reg: gpload, typ: "UInt32", clobberFlags: true, faultOnNilArg0: true},
{name: "LoweredAtomicLoad64", argLength: 2, reg: gpload, typ: "Int64", clobberFlags: true, faultOnNilArg0: true},
{name: "LoweredAtomicLoadPtr", argLength: 2, reg: gpload, typ: "Int64", clobberFlags: true, faultOnNilArg0: true},
{name: "LoweredAtomicLoad32", argLength: 2, reg: gpload, typ: "UInt32", aux: "Int64", clobberFlags: true, faultOnNilArg0: true},
{name: "LoweredAtomicLoad64", argLength: 2, reg: gpload, typ: "Int64", aux: "Int64", clobberFlags: true, faultOnNilArg0: true},
{name: "LoweredAtomicLoadPtr", argLength: 2, reg: gpload, typ: "Int64", aux: "Int64", clobberFlags: true, faultOnNilArg0: true},
// atomic add32, 64
// SYNC
@ -516,8 +516,8 @@ func init() {
// BNE -4(PC)
// CBNZ Rtmp, -4(PC)
// CSET EQ, Rout
{name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, aux: "Int64", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, aux: "Int64", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
// atomic 8 and/or.
// *arg0 &= (|=) arg1. arg2=mem. returns memory. auxint must be zero.

View File

@ -512,20 +512,23 @@ var genericOps = []opData{
// Atomic loads return a new memory so that the loads are properly ordered
// with respect to other loads and stores.
// TODO: use for sync/atomic at some point.
{name: "AtomicLoad32", argLength: 2, typ: "(UInt32,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
{name: "AtomicLoad64", argLength: 2, typ: "(UInt64,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
{name: "AtomicLoadPtr", argLength: 2, typ: "(BytePtr,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
{name: "AtomicStore32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
{name: "AtomicStore64", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
{name: "AtomicStorePtrNoWB", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
{name: "AtomicExchange32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
{name: "AtomicExchange64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
{name: "AtomicAdd32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
{name: "AtomicAdd64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
{name: "AtomicCompareAndSwap32", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true iff store happens and new memory.
{name: "AtomicCompareAndSwap64", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true iff store happens and new memory.
{name: "AtomicAnd8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 &= arg1. arg2=memory. Returns memory.
{name: "AtomicOr8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory.
{name: "AtomicLoad32", argLength: 2, typ: "(UInt32,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
{name: "AtomicLoad64", argLength: 2, typ: "(UInt64,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
{name: "AtomicLoadPtr", argLength: 2, typ: "(BytePtr,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
{name: "AtomicLoadAcq32", argLength: 2, typ: "(UInt32,Mem)"}, // Load from arg0. arg1=memory. Lock acquisition, returns loaded value and new memory.
{name: "AtomicStore32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
{name: "AtomicStore64", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
{name: "AtomicStorePtrNoWB", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
{name: "AtomicStoreRel32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Lock release, returns memory.
{name: "AtomicExchange32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
{name: "AtomicExchange64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
{name: "AtomicAdd32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
{name: "AtomicAdd64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
{name: "AtomicCompareAndSwap32", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true if store happens and new memory.
{name: "AtomicCompareAndSwap64", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true if store happens and new memory.
{name: "AtomicCompareAndSwapRel32", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Lock release, returns true if store happens and new memory.
{name: "AtomicAnd8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 &= arg1. arg2=memory. Returns memory.
{name: "AtomicOr8", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory.
// Atomic operation variants
// These variants have the same semantics as above atomic operations.

View File

@ -2409,15 +2409,18 @@ const (
OpAtomicLoad32
OpAtomicLoad64
OpAtomicLoadPtr
OpAtomicLoadAcq32
OpAtomicStore32
OpAtomicStore64
OpAtomicStorePtrNoWB
OpAtomicStoreRel32
OpAtomicExchange32
OpAtomicExchange64
OpAtomicAdd32
OpAtomicAdd64
OpAtomicCompareAndSwap32
OpAtomicCompareAndSwap64
OpAtomicCompareAndSwapRel32
OpAtomicAnd8
OpAtomicOr8
OpAtomicAdd32Variant
@ -23449,6 +23452,7 @@ var opcodeTable = [...]opInfo{
},
{
name: "LoweredAtomicStore32",
auxType: auxInt64,
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
@ -23461,6 +23465,7 @@ var opcodeTable = [...]opInfo{
},
{
name: "LoweredAtomicStore64",
auxType: auxInt64,
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
@ -23473,6 +23478,7 @@ var opcodeTable = [...]opInfo{
},
{
name: "LoweredAtomicLoad32",
auxType: auxInt64,
argLen: 2,
clobberFlags: true,
faultOnNilArg0: true,
@ -23487,6 +23493,7 @@ var opcodeTable = [...]opInfo{
},
{
name: "LoweredAtomicLoad64",
auxType: auxInt64,
argLen: 2,
clobberFlags: true,
faultOnNilArg0: true,
@ -23501,6 +23508,7 @@ var opcodeTable = [...]opInfo{
},
{
name: "LoweredAtomicLoadPtr",
auxType: auxInt64,
argLen: 2,
clobberFlags: true,
faultOnNilArg0: true,
@ -23583,6 +23591,7 @@ var opcodeTable = [...]opInfo{
},
{
name: "LoweredAtomicCas64",
auxType: auxInt64,
argLen: 4,
resultNotInArgs: true,
clobberFlags: true,
@ -23601,6 +23610,7 @@ var opcodeTable = [...]opInfo{
},
{
name: "LoweredAtomicCas32",
auxType: auxInt64,
argLen: 4,
resultNotInArgs: true,
clobberFlags: true,
@ -29701,6 +29711,11 @@ var opcodeTable = [...]opInfo{
argLen: 2,
generic: true,
},
{
name: "AtomicLoadAcq32",
argLen: 2,
generic: true,
},
{
name: "AtomicStore32",
argLen: 3,
@ -29719,6 +29734,12 @@ var opcodeTable = [...]opInfo{
hasSideEffects: true,
generic: true,
},
{
name: "AtomicStoreRel32",
argLen: 3,
hasSideEffects: true,
generic: true,
},
{
name: "AtomicExchange32",
argLen: 3,
@ -29755,6 +29776,12 @@ var opcodeTable = [...]opInfo{
hasSideEffects: true,
generic: true,
},
{
name: "AtomicCompareAndSwapRel32",
argLen: 4,
hasSideEffects: true,
generic: true,
},
{
name: "AtomicAnd8",
argLen: 3,

View File

@ -53,6 +53,8 @@ func rewriteValuePPC64(v *Value) bool {
return rewriteValuePPC64_OpAtomicCompareAndSwap32_0(v)
case OpAtomicCompareAndSwap64:
return rewriteValuePPC64_OpAtomicCompareAndSwap64_0(v)
case OpAtomicCompareAndSwapRel32:
return rewriteValuePPC64_OpAtomicCompareAndSwapRel32_0(v)
case OpAtomicExchange32:
return rewriteValuePPC64_OpAtomicExchange32_0(v)
case OpAtomicExchange64:
@ -61,6 +63,8 @@ func rewriteValuePPC64(v *Value) bool {
return rewriteValuePPC64_OpAtomicLoad32_0(v)
case OpAtomicLoad64:
return rewriteValuePPC64_OpAtomicLoad64_0(v)
case OpAtomicLoadAcq32:
return rewriteValuePPC64_OpAtomicLoadAcq32_0(v)
case OpAtomicLoadPtr:
return rewriteValuePPC64_OpAtomicLoadPtr_0(v)
case OpAtomicOr8:
@ -69,6 +73,8 @@ func rewriteValuePPC64(v *Value) bool {
return rewriteValuePPC64_OpAtomicStore32_0(v)
case OpAtomicStore64:
return rewriteValuePPC64_OpAtomicStore64_0(v)
case OpAtomicStoreRel32:
return rewriteValuePPC64_OpAtomicStoreRel32_0(v)
case OpAvg64u:
return rewriteValuePPC64_OpAvg64u_0(v)
case OpBitLen32:
@ -931,7 +937,7 @@ func rewriteValuePPC64_OpAtomicAnd8_0(v *Value) bool {
func rewriteValuePPC64_OpAtomicCompareAndSwap32_0(v *Value) bool {
// match: (AtomicCompareAndSwap32 ptr old new_ mem)
// cond:
// result: (LoweredAtomicCas32 ptr old new_ mem)
// result: (LoweredAtomicCas32 [1] ptr old new_ mem)
for {
_ = v.Args[3]
ptr := v.Args[0]
@ -939,6 +945,7 @@ func rewriteValuePPC64_OpAtomicCompareAndSwap32_0(v *Value) bool {
new_ := v.Args[2]
mem := v.Args[3]
v.reset(OpPPC64LoweredAtomicCas32)
v.AuxInt = 1
v.AddArg(ptr)
v.AddArg(old)
v.AddArg(new_)
@ -949,7 +956,7 @@ func rewriteValuePPC64_OpAtomicCompareAndSwap32_0(v *Value) bool {
func rewriteValuePPC64_OpAtomicCompareAndSwap64_0(v *Value) bool {
// match: (AtomicCompareAndSwap64 ptr old new_ mem)
// cond:
// result: (LoweredAtomicCas64 ptr old new_ mem)
// result: (LoweredAtomicCas64 [1] ptr old new_ mem)
for {
_ = v.Args[3]
ptr := v.Args[0]
@ -957,6 +964,26 @@ func rewriteValuePPC64_OpAtomicCompareAndSwap64_0(v *Value) bool {
new_ := v.Args[2]
mem := v.Args[3]
v.reset(OpPPC64LoweredAtomicCas64)
v.AuxInt = 1
v.AddArg(ptr)
v.AddArg(old)
v.AddArg(new_)
v.AddArg(mem)
return true
}
}
func rewriteValuePPC64_OpAtomicCompareAndSwapRel32_0(v *Value) bool {
// match: (AtomicCompareAndSwapRel32 ptr old new_ mem)
// cond:
// result: (LoweredAtomicCas32 [0] ptr old new_ mem)
for {
_ = v.Args[3]
ptr := v.Args[0]
old := v.Args[1]
new_ := v.Args[2]
mem := v.Args[3]
v.reset(OpPPC64LoweredAtomicCas32)
v.AuxInt = 0
v.AddArg(ptr)
v.AddArg(old)
v.AddArg(new_)
@ -999,12 +1026,13 @@ func rewriteValuePPC64_OpAtomicExchange64_0(v *Value) bool {
func rewriteValuePPC64_OpAtomicLoad32_0(v *Value) bool {
// match: (AtomicLoad32 ptr mem)
// cond:
// result: (LoweredAtomicLoad32 ptr mem)
// result: (LoweredAtomicLoad32 [1] ptr mem)
for {
_ = v.Args[1]
ptr := v.Args[0]
mem := v.Args[1]
v.reset(OpPPC64LoweredAtomicLoad32)
v.AuxInt = 1
v.AddArg(ptr)
v.AddArg(mem)
return true
@ -1013,12 +1041,28 @@ func rewriteValuePPC64_OpAtomicLoad32_0(v *Value) bool {
func rewriteValuePPC64_OpAtomicLoad64_0(v *Value) bool {
// match: (AtomicLoad64 ptr mem)
// cond:
// result: (LoweredAtomicLoad64 ptr mem)
// result: (LoweredAtomicLoad64 [1] ptr mem)
for {
_ = v.Args[1]
ptr := v.Args[0]
mem := v.Args[1]
v.reset(OpPPC64LoweredAtomicLoad64)
v.AuxInt = 1
v.AddArg(ptr)
v.AddArg(mem)
return true
}
}
func rewriteValuePPC64_OpAtomicLoadAcq32_0(v *Value) bool {
// match: (AtomicLoadAcq32 ptr mem)
// cond:
// result: (LoweredAtomicLoad32 [0] ptr mem)
for {
_ = v.Args[1]
ptr := v.Args[0]
mem := v.Args[1]
v.reset(OpPPC64LoweredAtomicLoad32)
v.AuxInt = 0
v.AddArg(ptr)
v.AddArg(mem)
return true
@ -1027,12 +1071,13 @@ func rewriteValuePPC64_OpAtomicLoad64_0(v *Value) bool {
func rewriteValuePPC64_OpAtomicLoadPtr_0(v *Value) bool {
// match: (AtomicLoadPtr ptr mem)
// cond:
// result: (LoweredAtomicLoadPtr ptr mem)
// result: (LoweredAtomicLoadPtr [1] ptr mem)
for {
_ = v.Args[1]
ptr := v.Args[0]
mem := v.Args[1]
v.reset(OpPPC64LoweredAtomicLoadPtr)
v.AuxInt = 1
v.AddArg(ptr)
v.AddArg(mem)
return true
@ -1057,13 +1102,14 @@ func rewriteValuePPC64_OpAtomicOr8_0(v *Value) bool {
func rewriteValuePPC64_OpAtomicStore32_0(v *Value) bool {
// match: (AtomicStore32 ptr val mem)
// cond:
// result: (LoweredAtomicStore32 ptr val mem)
// result: (LoweredAtomicStore32 [1] ptr val mem)
for {
_ = v.Args[2]
ptr := v.Args[0]
val := v.Args[1]
mem := v.Args[2]
v.reset(OpPPC64LoweredAtomicStore32)
v.AuxInt = 1
v.AddArg(ptr)
v.AddArg(val)
v.AddArg(mem)
@ -1073,13 +1119,31 @@ func rewriteValuePPC64_OpAtomicStore32_0(v *Value) bool {
func rewriteValuePPC64_OpAtomicStore64_0(v *Value) bool {
// match: (AtomicStore64 ptr val mem)
// cond:
// result: (LoweredAtomicStore64 ptr val mem)
// result: (LoweredAtomicStore64 [1] ptr val mem)
for {
_ = v.Args[2]
ptr := v.Args[0]
val := v.Args[1]
mem := v.Args[2]
v.reset(OpPPC64LoweredAtomicStore64)
v.AuxInt = 1
v.AddArg(ptr)
v.AddArg(val)
v.AddArg(mem)
return true
}
}
func rewriteValuePPC64_OpAtomicStoreRel32_0(v *Value) bool {
// match: (AtomicStoreRel32 ptr val mem)
// cond:
// result: (LoweredAtomicStore32 [0] ptr val mem)
for {
_ = v.Args[2]
ptr := v.Args[0]
val := v.Args[1]
mem := v.Args[2]
v.reset(OpPPC64LoweredAtomicStore32)
v.AuxInt = 0
v.AddArg(ptr)
v.AddArg(val)
v.AddArg(mem)

View File

@ -23,6 +23,9 @@ TEXT runtimeinternalatomic·Cas(SB), NOSPLIT, $0-13
TEXT runtimeinternalatomic·Casuintptr(SB), NOSPLIT, $0-13
JMP runtimeinternalatomic·Cas(SB)
TEXT runtimeinternalatomic·CasRel(SB), NOSPLIT, $0-13
JMP runtimeinternalatomic·Cas(SB)
TEXT runtimeinternalatomic·Loaduintptr(SB), NOSPLIT, $0-8
JMP runtimeinternalatomic·Load(SB)
@ -180,6 +183,9 @@ TEXT runtimeinternalatomic·Store(SB), NOSPLIT, $0-8
XCHGL AX, 0(BX)
RET
TEXT runtimeinternalatomic·StoreRel(SB), NOSPLIT, $0-8
JMP runtimeinternalatomic·Store(SB)
// uint64 atomicload64(uint64 volatile* addr);
TEXT runtimeinternalatomic·Load64(SB), NOSPLIT, $0-12
MOVL ptr+0(FP), AX

View File

@ -43,6 +43,9 @@ TEXT runtimeinternalatomic·Cas64(SB), NOSPLIT, $0-25
TEXT runtimeinternalatomic·Casuintptr(SB), NOSPLIT, $0-25
JMP runtimeinternalatomic·Cas64(SB)
TEXT runtimeinternalatomic·CasRel(SB), NOSPLIT, $0-17
JMP runtimeinternalatomic·Cas(SB)
TEXT runtimeinternalatomic·Loaduintptr(SB), NOSPLIT, $0-16
JMP runtimeinternalatomic·Load64(SB)
@ -130,6 +133,9 @@ TEXT runtimeinternalatomic·Store(SB), NOSPLIT, $0-12
XCHGL AX, 0(BX)
RET
TEXT runtimeinternalatomic·StoreRel(SB), NOSPLIT, $0-12
JMP runtimeinternalatomic·Store(SB)
TEXT runtimeinternalatomic·Store64(SB), NOSPLIT, $0-16
MOVQ ptr+0(FP), BX
MOVQ val+8(FP), AX

View File

@ -23,6 +23,9 @@ TEXT runtimeinternalatomic·Cas(SB), NOSPLIT, $0-17
TEXT runtimeinternalatomic·Casuintptr(SB), NOSPLIT, $0-17
JMP runtimeinternalatomic·Cas(SB)
TEXT runtimeinternalatomic·CasRel(SB), NOSPLIT, $0-17
JMP runtimeinternalatomic·Cas(SB)
TEXT runtimeinternalatomic·Loaduintptr(SB), NOSPLIT, $0-12
JMP runtimeinternalatomic·Load(SB)
@ -130,6 +133,9 @@ TEXT runtimeinternalatomic·Store(SB), NOSPLIT, $0-8
XCHGL AX, 0(BX)
RET
TEXT runtimeinternalatomic·StoreRel(SB), NOSPLIT, $0-8
JMP runtimeinternalatomic·Store(SB)
TEXT runtimeinternalatomic·Store64(SB), NOSPLIT, $0-16
MOVL ptr+0(FP), BX
MOVQ val+8(FP), AX

View File

@ -53,12 +53,18 @@ casfail:
TEXT runtimeinternalatomic·Loadp(SB),NOSPLIT|NOFRAME,$0-8
B runtimeinternalatomic·Load(SB)
TEXT runtimeinternalatomic·LoadAcq(SB),NOSPLIT|NOFRAME,$0-8
B runtimeinternalatomic·Load(SB)
TEXT runtimeinternalatomic·Casuintptr(SB),NOSPLIT,$0-13
B runtimeinternalatomic·Cas(SB)
TEXT runtimeinternalatomic·Casp1(SB),NOSPLIT,$0-13
B runtimeinternalatomic·Cas(SB)
TEXT runtimeinternalatomic·CasRel(SB),NOSPLIT,$0-13
B runtimeinternalatomic·Cas(SB)
TEXT runtimeinternalatomic·Loaduintptr(SB),NOSPLIT,$0-8
B runtimeinternalatomic·Load(SB)
@ -71,6 +77,9 @@ TEXT runtimeinternalatomic·Storeuintptr(SB),NOSPLIT,$0-8
TEXT runtimeinternalatomic·StorepNoWB(SB),NOSPLIT,$0-8
B runtimeinternalatomic·Store(SB)
TEXT runtimeinternalatomic·StoreRel(SB),NOSPLIT,$0-8
B runtimeinternalatomic·Store(SB)
TEXT runtimeinternalatomic·Xadduintptr(SB),NOSPLIT,$0-12
B runtimeinternalatomic·Xadd(SB)

View File

@ -29,6 +29,9 @@ ok:
TEXT runtimeinternalatomic·Casuintptr(SB), NOSPLIT, $0-25
B runtimeinternalatomic·Cas64(SB)
TEXT runtimeinternalatomic·CasRel(SB), NOSPLIT, $0-17
B runtimeinternalatomic·Cas(SB)
TEXT runtimeinternalatomic·Loaduintptr(SB), NOSPLIT, $0-16
B runtimeinternalatomic·Load64(SB)

View File

@ -62,6 +62,9 @@ cas64_fail:
TEXT ·Casuintptr(SB), NOSPLIT, $0-25
JMP ·Cas64(SB)
TEXT ·CasRel(SB), NOSPLIT, $0-17
JMP ·Cas(SB)
TEXT ·Loaduintptr(SB), NOSPLIT|NOFRAME, $0-16
JMP ·Load64(SB)
@ -152,6 +155,9 @@ TEXT ·Xchguintptr(SB), NOSPLIT, $0-24
TEXT ·StorepNoWB(SB), NOSPLIT, $0-16
JMP ·Store64(SB)
TEXT ·StoreRel(SB), NOSPLIT, $0-12
JMP ·Store(SB)
TEXT ·Store(SB), NOSPLIT, $0-12
MOVV ptr+0(FP), R1
MOVW val+8(FP), R2

View File

@ -70,6 +70,9 @@ try_xchg:
TEXT ·Casuintptr(SB),NOSPLIT,$0-13
JMP ·Cas(SB)
TEXT ·CasRel(SB),NOSPLIT,$0-13
JMP ·Cas(SB)
TEXT ·Loaduintptr(SB),NOSPLIT,$0-8
JMP ·Load(SB)
@ -100,6 +103,9 @@ TEXT ·Xchguintptr(SB),NOSPLIT,$0-12
TEXT ·StorepNoWB(SB),NOSPLIT,$0-8
JMP ·Store(SB)
TEXT ·StoreRel(SB),NOSPLIT,$0-8
JMP ·Store(SB)
// void Or8(byte volatile*, byte);
TEXT ·Or8(SB),NOSPLIT,$0-5
MOVW ptr+0(FP), R1

View File

@ -59,6 +59,24 @@ cas64_fail:
MOVB R0, ret+24(FP)
RET
TEXT runtimeinternalatomic·CasRel(SB), NOSPLIT, $0-17
MOVD ptr+0(FP), R3
MOVWZ old+8(FP), R4
MOVWZ new+12(FP), R5
LWSYNC
cas_again:
LWAR (R3), $0, R6 // 0 = Mutex release hint
CMPW R6, R4
BNE cas_fail
STWCCC R5, (R3)
BNE cas_again
MOVD $1, R3
MOVB R3, ret+16(FP)
RET
cas_fail:
MOVB R0, ret+16(FP)
RET
TEXT runtimeinternalatomic·Casuintptr(SB), NOSPLIT, $0-25
BR runtimeinternalatomic·Cas64(SB)
@ -159,6 +177,13 @@ TEXT runtimeinternalatomic·Store64(SB), NOSPLIT, $0-16
MOVD R4, 0(R3)
RET
TEXT runtimeinternalatomic·StoreRel(SB), NOSPLIT, $0-12
MOVD ptr+0(FP), R3
MOVW val+8(FP), R4
LWSYNC
MOVW R4, 0(R3)
RET
// void runtimeinternalatomic·Or8(byte volatile*, byte);
TEXT runtimeinternalatomic·Or8(SB), NOSPLIT, $0-9
MOVD ptr+0(FP), R3

View File

@ -48,6 +48,10 @@ cas64_fail:
TEXT ·Casuintptr(SB), NOSPLIT, $0-25
BR ·Cas64(SB)
// func CasRel(ptr *uint32, old, new uint32) bool
TEXT ·CasRel(SB), NOSPLIT, $0-17
BR ·Cas(SB)
// func Loaduintptr(ptr *uintptr) uintptr
TEXT ·Loaduintptr(SB), NOSPLIT, $0-16
BR ·Load64(SB)

View File

@ -20,6 +20,12 @@ func Loadp(ptr unsafe.Pointer) unsafe.Pointer {
return *(*unsafe.Pointer)(ptr)
}
//go:nosplit
//go:noinline
func LoadAcq(ptr *uint32) uint32 {
return *ptr
}
//go:noescape
func Xadd64(ptr *uint64, delta int64) uint64
@ -52,11 +58,17 @@ func Or8(ptr *uint8, val uint8)
//go:noescape
func Cas64(ptr *uint64, old, new uint64) bool
//go:noescape
func CasRel(ptr *uint32, old, new uint32) bool
//go:noescape
func Store(ptr *uint32, val uint32)
//go:noescape
func Store64(ptr *uint64, val uint64)
//go:noescape
func StoreRel(ptr *uint32, val uint32)
// NO go:noescape annotation; see atomic_pointer.go.
func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer)

View File

@ -26,6 +26,12 @@ func Load64(ptr *uint64) uint64 {
return *ptr
}
//go:nosplit
//go:noinline
func LoadAcq(ptr *uint32) uint32 {
return *ptr
}
//go:noescape
func Xadd(ptr *uint32, delta int32) uint32
@ -55,12 +61,18 @@ func Or8(ptr *uint8, val uint8)
//go:noescape
func Cas64(ptr *uint64, old, new uint64) bool
//go:noescape
func CasRel(ptr *uint32, old, new uint32) bool
//go:noescape
func Store(ptr *uint32, val uint32)
//go:noescape
func Store64(ptr *uint64, val uint64)
//go:noescape
func StoreRel(ptr *uint32, val uint32)
// StorepNoWB performs *ptr = val atomically and without a write
// barrier.
//

View File

@ -74,6 +74,9 @@ func StorepNoWB(addr unsafe.Pointer, v unsafe.Pointer)
//go:noescape
func Store(addr *uint32, v uint32)
//go:noescape
func StoreRel(addr *uint32, v uint32)
//go:nosplit
func goCas64(addr *uint64, old, new uint64) bool {
if uintptr(unsafe.Pointer(addr))&7 != 0 {
@ -181,9 +184,15 @@ func Load(addr *uint32) uint32
//go:noescape
func Loadp(addr unsafe.Pointer) unsafe.Pointer
//go:noescape
func LoadAcq(addr *uint32) uint32
//go:noescape
func Cas64(addr *uint64, old, new uint64) bool
//go:noescape
func CasRel(addr *uint32, old, new uint32) bool
//go:noescape
func Xadd64(addr *uint64, delta int64) uint64

View File

@ -35,6 +35,9 @@ func Load64(ptr *uint64) uint64
//go:noescape
func Loadp(ptr unsafe.Pointer) unsafe.Pointer
//go:noescape
func LoadAcq(addr *uint32) uint32
//go:noescape
func Or8(ptr *uint8, val uint8)
@ -44,6 +47,9 @@ func And8(ptr *uint8, val uint8)
//go:noescape
func Cas64(ptr *uint64, old, new uint64) bool
//go:noescape
func CasRel(ptr *uint32, old, new uint32) bool
//go:noescape
func Store(ptr *uint32, val uint32)
@ -52,3 +58,6 @@ func Store64(ptr *uint64, val uint64)
// NO go:noescape annotation; see atomic_pointer.go.
func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer)
//go:noescape
func StoreRel(ptr *uint32, val uint32)

View File

@ -25,9 +25,16 @@ TEXT ·Loadp(SB),NOSPLIT,$0-16
MOVD R0, ret+8(FP)
RET
// uint32 runtimeinternalatomic·LoadAcq(uint32 volatile* addr)
TEXT ·LoadAcq(SB),NOSPLIT,$0-12
B ·Load(SB)
TEXT runtimeinternalatomic·StorepNoWB(SB), NOSPLIT, $0-16
B runtimeinternalatomic·Store64(SB)
TEXT runtimeinternalatomic·StoreRel(SB), NOSPLIT, $0-12
B runtimeinternalatomic·Store(SB)
TEXT runtimeinternalatomic·Store(SB), NOSPLIT, $0-12
MOVD ptr+0(FP), R0
MOVW val+8(FP), R1

View File

@ -35,6 +35,9 @@ func Load64(ptr *uint64) uint64
//go:noescape
func Loadp(ptr unsafe.Pointer) unsafe.Pointer
//go:noescape
func LoadAcq(ptr *uint32) uint32
//go:noescape
func And8(ptr *uint8, val uint8)
@ -46,6 +49,9 @@ func Or8(ptr *uint8, val uint8)
//go:noescape
func Cas64(ptr *uint64, old, new uint64) bool
//go:noescape
func CasRel(ptr *uint32, old, new uint32) bool
//go:noescape
func Store(ptr *uint32, val uint32)
@ -54,3 +60,6 @@ func Store64(ptr *uint64, val uint64)
// NO go:noescape annotation; see atomic_pointer.go.
func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer)
//go:noescape
func StoreRel(ptr *uint32, val uint32)

View File

@ -34,3 +34,7 @@ TEXT ·Loadp(SB),NOSPLIT|NOFRAME,$0-16
SYNC
MOVV R1, ret+8(FP)
RET
// uint32 runtimeinternalatomic·LoadAcq(uint32 volatile* ptr)
TEXT ·LoadAcq(SB),NOSPLIT|NOFRAME,$0-12
JMP atomic·Load(SB)

View File

@ -119,6 +119,9 @@ func Load(ptr *uint32) uint32
//go:noescape
func Loadp(ptr unsafe.Pointer) unsafe.Pointer
//go:noescape
func LoadAcq(ptr *uint32) uint32
//go:noescape
func And8(ptr *uint8, val uint8)
@ -130,3 +133,9 @@ func Store(ptr *uint32, val uint32)
// NO go:noescape annotation; see atomic_pointer.go.
func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer)
//go:noescape
func StoreRel(ptr *uint32, val uint32)
//go:noescape
func CasRel(addr *uint32, old, new uint32) bool

View File

@ -35,6 +35,9 @@ func Load64(ptr *uint64) uint64
//go:noescape
func Loadp(ptr unsafe.Pointer) unsafe.Pointer
//go:noescape
func LoadAcq(ptr *uint32) uint32
//go:noescape
func And8(ptr *uint8, val uint8)
@ -46,11 +49,17 @@ func Or8(ptr *uint8, val uint8)
//go:noescape
func Cas64(ptr *uint64, old, new uint64) bool
//go:noescape
func CasRel(ptr *uint32, old, new uint32) bool
//go:noescape
func Store(ptr *uint32, val uint32)
//go:noescape
func Store64(ptr *uint64, val uint64)
//go:noescape
func StoreRel(ptr *uint32, val uint32)
// NO go:noescape annotation; see atomic_pointer.go.
func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer)

View File

@ -38,3 +38,12 @@ TEXT ·Loadp(SB),NOSPLIT|NOFRAME,$-8-16
ISYNC
MOVD R3, ret+8(FP)
RET
// uint32 runtimeinternalatomic·LoadAcq(uint32 volatile* ptr)
TEXT ·LoadAcq(SB),NOSPLIT|NOFRAME,$-8-12
MOVD ptr+0(FP), R3
MOVWZ 0(R3), R3
CMPW R3, R3, CR7
BC 4, 30, 1(PC) // bne- cr7, 0x4
MOVW R3, ret+8(FP)
RET

View File

@ -24,6 +24,12 @@ func Load64(ptr *uint64) uint64 {
return *ptr
}
//go:nosplit
//go:noinline
func LoadAcq(ptr *uint32) uint32 {
return *ptr
}
//go:noinline
//go:nosplit
func Store(ptr *uint32, val uint32) {
@ -43,6 +49,12 @@ func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer) {
*(*uintptr)(ptr) = uintptr(val)
}
//go:noinline
//go:nosplit
func StoreRel(ptr *uint32, val uint32) {
*ptr = val
}
//go:noescape
func And8(ptr *uint8, val uint8)
@ -71,3 +83,6 @@ func Xchguintptr(ptr *uintptr, new uintptr) uintptr
//go:noescape
func Cas64(ptr *uint64, old, new uint64) bool
//go:noescape
func CasRel(ptr *uint32, old, new uint32) bool

View File

@ -21,6 +21,12 @@ func Loadp(ptr unsafe.Pointer) unsafe.Pointer {
return *(*unsafe.Pointer)(ptr)
}
//go:nosplit
//go:noinline
func LoadAcq(ptr *uint32) uint32 {
return *ptr
}
//go:nosplit
//go:noinline
func Load64(ptr *uint64) uint64 {
@ -105,6 +111,12 @@ func Store(ptr *uint32, val uint32) {
*ptr = val
}
//go:nosplit
//go:noinline
func StoreRel(ptr *uint32, val uint32) {
*ptr = val
}
//go:nosplit
//go:noinline
func Store64(ptr *uint64, val uint64) {
@ -147,6 +159,16 @@ func Casuintptr(ptr *uintptr, old, new uintptr) bool {
return false
}
//go:nosplit
//go:noinline
func CasRel(ptr *uint32, old, new uint32) bool {
if *ptr == old {
*ptr = new
return true
}
return false
}
//go:nosplit
//go:noinline
func Storeuintptr(ptr *uintptr, new uintptr) {

View File

@ -4765,11 +4765,11 @@ func runqput(_p_ *p, gp *g, next bool) {
}
retry:
h := atomic.Load(&_p_.runqhead) // load-acquire, synchronize with consumers
h := atomic.LoadAcq(&_p_.runqhead) // load-acquire, synchronize with consumers
t := _p_.runqtail
if t-h < uint32(len(_p_.runq)) {
_p_.runq[t%uint32(len(_p_.runq))].set(gp)
atomic.Store(&_p_.runqtail, t+1) // store-release, makes the item available for consumption
atomic.StoreRel(&_p_.runqtail, t+1) // store-release, makes the item available for consumption
return
}
if runqputslow(_p_, gp, h, t) {
@ -4793,7 +4793,7 @@ func runqputslow(_p_ *p, gp *g, h, t uint32) bool {
for i := uint32(0); i < n; i++ {
batch[i] = _p_.runq[(h+i)%uint32(len(_p_.runq))].ptr()
}
if !atomic.Cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
if !atomic.CasRel(&_p_.runqhead, h, h+n) { // cas-release, commits consume
return false
}
batch[n] = gp
@ -4837,13 +4837,13 @@ func runqget(_p_ *p) (gp *g, inheritTime bool) {
}
for {
h := atomic.Load(&_p_.runqhead) // load-acquire, synchronize with other consumers
h := atomic.LoadAcq(&_p_.runqhead) // load-acquire, synchronize with other consumers
t := _p_.runqtail
if t == h {
return nil, false
}
gp := _p_.runq[h%uint32(len(_p_.runq))].ptr()
if atomic.Cas(&_p_.runqhead, h, h+1) { // cas-release, commits consume
if atomic.CasRel(&_p_.runqhead, h, h+1) { // cas-release, commits consume
return gp, false
}
}
@ -4855,8 +4855,8 @@ func runqget(_p_ *p) (gp *g, inheritTime bool) {
// Can be executed by any P.
func runqgrab(_p_ *p, batch *[256]guintptr, batchHead uint32, stealRunNextG bool) uint32 {
for {
h := atomic.Load(&_p_.runqhead) // load-acquire, synchronize with other consumers
t := atomic.Load(&_p_.runqtail) // load-acquire, synchronize with the producer
h := atomic.LoadAcq(&_p_.runqhead) // load-acquire, synchronize with other consumers
t := atomic.LoadAcq(&_p_.runqtail) // load-acquire, synchronize with the producer
n := t - h
n = n - n/2
if n == 0 {
@ -4899,7 +4899,7 @@ func runqgrab(_p_ *p, batch *[256]guintptr, batchHead uint32, stealRunNextG bool
g := _p_.runq[(h+i)%uint32(len(_p_.runq))]
batch[(batchHead+i)%uint32(len(batch))] = g
}
if atomic.Cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
if atomic.CasRel(&_p_.runqhead, h, h+n) { // cas-release, commits consume
return n
}
}
@ -4919,11 +4919,11 @@ func runqsteal(_p_, p2 *p, stealRunNextG bool) *g {
if n == 0 {
return gp
}
h := atomic.Load(&_p_.runqhead) // load-acquire, synchronize with consumers
h := atomic.LoadAcq(&_p_.runqhead) // load-acquire, synchronize with consumers
if t-h+n >= uint32(len(_p_.runq)) {
throw("runqsteal: runq overflow")
}
atomic.Store(&_p_.runqtail, t+n) // store-release, makes the item available for consumption
atomic.StoreRel(&_p_.runqtail, t+n) // store-release, makes the item available for consumption
return gp
}