gvisor/pkg/sync/runtime_amd64.s

26 lines
928 B
ArmAsm
Raw Normal View History

Support synchronous AssertAndFetch for sleep package. Some synchronization patterns require the ability to simultaneously wake and sleep a goroutine. For the sleep package, this is the case when a waker must be asserted when a subsequent fetch is imminent. Currently, this operation results in significant P churn in the runtime, which ping-pongs execution between multiple system threads and cores and consumes a significant amount of host CPU (and because of the context switches, this can be significant worse with mitigations for side channel vulnerabilities). The solution is to introduce a dedicated mechanism for a synchronous switch which does not wake another runtime P (see golang/go#32113). This can be used by the `AssertAndFetch` API in the sleep package. The benchmark results for this package are very similiar to raw channel operations for all cases, with the exception of operations that do not wait. The primary advantage is more precise control over scheduling. This will be used in a subsequent change. ``` BenchmarkGoAssertNonWaiting BenchmarkGoAssertNonWaiting-8 261364384 4.976 ns/op BenchmarkGoSingleSelect BenchmarkGoSingleSelect-8 20946358 57.77 ns/op BenchmarkGoMultiSelect BenchmarkGoMultiSelect-8 6071697 197.0 ns/op BenchmarkGoWaitOnSingleSelect BenchmarkGoWaitOnSingleSelect-8 4978051 235.4 ns/op BenchmarkGoWaitOnMultiSelect BenchmarkGoWaitOnMultiSelect-8 2309224 520.2 ns/op BenchmarkSleeperAssertNonWaiting BenchmarkSleeperAssertNonWaiting-8 447325033 2.657 ns/op BenchmarkSleeperSingleSelect BenchmarkSleeperSingleSelect-8 21488844 55.19 ns/op BenchmarkSleeperMultiSelect BenchmarkSleeperMultiSelect-8 21851674 54.89 ns/op BenchmarkSleeperWaitOnSingleSelect BenchmarkSleeperWaitOnSingleSelect-8 2860327 416.4 ns/op BenchmarkSleeperWaitOnSingleSelectSync BenchmarkSleeperWaitOnSingleSelectSync-8 2741733 427.1 ns/op BenchmarkSleeperWaitOnMultiSelect BenchmarkSleeperWaitOnMultiSelect-8 2867484 418.1 ns/op BenchmarkSleeperWaitOnMultiSelectSync BenchmarkSleeperWaitOnMultiSelectSync-8 2789158 427.9 ns/op ``` PiperOrigin-RevId: 415581417
2021-12-10 20:23:03 +00:00
// Copyright 2018 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build amd64 && go1.14 && !go1.20 && !goexperiment.staticlockranking
// +build amd64,go1.14,!go1.20,!goexperiment.staticlockranking
Support synchronous AssertAndFetch for sleep package. Some synchronization patterns require the ability to simultaneously wake and sleep a goroutine. For the sleep package, this is the case when a waker must be asserted when a subsequent fetch is imminent. Currently, this operation results in significant P churn in the runtime, which ping-pongs execution between multiple system threads and cores and consumes a significant amount of host CPU (and because of the context switches, this can be significant worse with mitigations for side channel vulnerabilities). The solution is to introduce a dedicated mechanism for a synchronous switch which does not wake another runtime P (see golang/go#32113). This can be used by the `AssertAndFetch` API in the sleep package. The benchmark results for this package are very similiar to raw channel operations for all cases, with the exception of operations that do not wait. The primary advantage is more precise control over scheduling. This will be used in a subsequent change. ``` BenchmarkGoAssertNonWaiting BenchmarkGoAssertNonWaiting-8 261364384 4.976 ns/op BenchmarkGoSingleSelect BenchmarkGoSingleSelect-8 20946358 57.77 ns/op BenchmarkGoMultiSelect BenchmarkGoMultiSelect-8 6071697 197.0 ns/op BenchmarkGoWaitOnSingleSelect BenchmarkGoWaitOnSingleSelect-8 4978051 235.4 ns/op BenchmarkGoWaitOnMultiSelect BenchmarkGoWaitOnMultiSelect-8 2309224 520.2 ns/op BenchmarkSleeperAssertNonWaiting BenchmarkSleeperAssertNonWaiting-8 447325033 2.657 ns/op BenchmarkSleeperSingleSelect BenchmarkSleeperSingleSelect-8 21488844 55.19 ns/op BenchmarkSleeperMultiSelect BenchmarkSleeperMultiSelect-8 21851674 54.89 ns/op BenchmarkSleeperWaitOnSingleSelect BenchmarkSleeperWaitOnSingleSelect-8 2860327 416.4 ns/op BenchmarkSleeperWaitOnSingleSelectSync BenchmarkSleeperWaitOnSingleSelectSync-8 2741733 427.1 ns/op BenchmarkSleeperWaitOnMultiSelect BenchmarkSleeperWaitOnMultiSelect-8 2867484 418.1 ns/op BenchmarkSleeperWaitOnMultiSelectSync BenchmarkSleeperWaitOnMultiSelectSync-8 2789158 427.9 ns/op ``` PiperOrigin-RevId: 415581417
2021-12-10 20:23:03 +00:00
#include "textflag.h"
TEXT ·addrOfSpinning(SB),NOSPLIT,$0-8
// The offset specified here is the nmspinning value in sched.
LEAQ runtime·sched(SB), AX
ADDQ $92, AX
MOVQ AX, ret+0(FP)
RET