Skip to content

Commit 8683bb8

Browse files
mknyszekgopherbot
authored andcommitted
runtime: optimistically CAS atomicstatus directly in enter/exitsyscall
This change steals the performance trick from the coro implementation to try to do the CAS directly first before calling into casgstatus, a much more heavyweight function. We have to be careful about synctest bubbling, but overall it's a good bit faster, and easy low-hanging fruit. goos: linux goarch: amd64 pkg: internal/runtime/cgobench cpu: AMD EPYC 7B13 │ after-2-2.out │ after-3.out │ │ sec/op │ sec/op vs base │ CgoCall-64 34.62n ± 1% 30.55n ± 1% -11.76% (p=0.002 n=6) Change-Id: Ic38620233b55f58b8a07510666aa18648373e2e7 Reviewed-on: https://go-review.googlesource.com/c/go/+/708596 Auto-Submit: Michael Knyszek <mknyszek@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Pratt <mpratt@google.com>
1 parent 5b8e850 commit 8683bb8

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

src/runtime/proc.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4622,7 +4622,12 @@ func reentersyscall(pc, sp, bp uintptr) {
46224622
}
46234623
// As soon as we switch to _Gsyscall, we are in danger of losing our P.
46244624
// We must not touch it after this point.
4625-
casgstatus(gp, _Grunning, _Gsyscall)
4625+
//
4626+
// Try to do a quick CAS to avoid calling into casgstatus in the common case.
4627+
// If we have a bubble, we need to fall into casgstatus.
4628+
if gp.bubble != nil || !gp.atomicstatus.CompareAndSwap(_Grunning, _Gsyscall) {
4629+
casgstatus(gp, _Grunning, _Gsyscall)
4630+
}
46264631
if staticLockRanking {
46274632
// casgstatus clobbers gp.sched via systemstack under staticLockRanking. Restore it.
46284633
save(pc, sp, bp)
@@ -4825,7 +4830,12 @@ func exitsyscall() {
48254830
// need to be held ahead of time. We're effectively atomic with respect to
48264831
// the tracer because we're non-preemptible and in the runtime. It can't stop
48274832
// us to read a bad status.
4828-
casgstatus(gp, _Gsyscall, _Grunning)
4833+
//
4834+
// Try to do a quick CAS to avoid calling into casgstatus in the common case.
4835+
// If we have a bubble, we need to fall into casgstatus.
4836+
if gp.bubble != nil || !gp.atomicstatus.CompareAndSwap(_Gsyscall, _Grunning) {
4837+
casgstatus(gp, _Gsyscall, _Grunning)
4838+
}
48294839

48304840
// Caution: we're in a window where we may be in _Grunning without a P.
48314841
// Either we will grab a P or call exitsyscall0, where we'll switch to

0 commit comments

Comments
 (0)