mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Make atomicbitops.Bool savable.
Earlier the atomicbitops_state_autogen.go was not being built because it had an impossible build condition: `(amd64 || arm64) && !amd64 && !arm64`. This is a known deficiency in go_stateify tool. This was solved via having two identical files like 32b_32bit.go and 32b_64bit.go. Just piggyback this. This changes also enhances `atomicbitops.Bool` in the following ways: - Added RacyLoad(), RacyStore() and CompareAndSwap() for Bool to bring it up to speed with the other types. - Delegated the actual atomic operations work to the underlying Uint32. - Cleaned up code with b32(); similar to what sync/atomic.Bool does. PiperOrigin-RevId: 597607982
This commit is contained in:
@@ -77,9 +77,6 @@ func (i *Int32) Store(v int32) {
|
||||
//
|
||||
// It may be helpful to document why a racy operation is permitted.
|
||||
//
|
||||
// Don't add fields to this struct. It is important that it remain the same
|
||||
// size as its builtin analogue.
|
||||
//
|
||||
//go:nosplit
|
||||
func (i *Int32) RacyStore(v int32) {
|
||||
i.value = v
|
||||
@@ -124,6 +121,9 @@ func (i *Int32) ptr() *int32 {
|
||||
|
||||
// Uint32 is an atomic uint32.
|
||||
//
|
||||
// Don't add fields to this struct. It is important that it remain the same
|
||||
// size as its builtin analogue.
|
||||
//
|
||||
// See aligned_unsafe.go in this directory for justification.
|
||||
//
|
||||
// +stateify savable
|
||||
@@ -210,4 +210,80 @@ func (u *Uint32) ptr() *uint32 {
|
||||
return &u.value
|
||||
}
|
||||
|
||||
// Bool is an atomic Boolean.
|
||||
//
|
||||
// It is implemented by a Uint32, with value 0 indicating false, and 1
|
||||
// indicating true.
|
||||
//
|
||||
// +stateify savable
|
||||
type Bool struct {
|
||||
Uint32
|
||||
}
|
||||
|
||||
// b32 returns a uint32 0 or 1 representing b.
|
||||
func b32(b bool) uint32 {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// FromBool returns a Bool initialized to value val.
|
||||
//
|
||||
//go:nosplit
|
||||
func FromBool(val bool) Bool {
|
||||
return Bool{
|
||||
Uint32: FromUint32(b32(val)),
|
||||
}
|
||||
}
|
||||
|
||||
// Load is analogous to atomic.LoadBool, if such a thing existed.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) Load() bool {
|
||||
return b.Uint32.Load() != 0
|
||||
}
|
||||
|
||||
// RacyLoad is analogous to reading an atomic value without using
|
||||
// synchronization.
|
||||
//
|
||||
// It may be helpful to document why a racy operation is permitted.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) RacyLoad() bool {
|
||||
return b.Uint32.RacyLoad() != 0
|
||||
}
|
||||
|
||||
// Store is analogous to atomic.StoreBool, if such a thing existed.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) Store(val bool) {
|
||||
b.Uint32.Store(b32(val))
|
||||
}
|
||||
|
||||
// RacyStore is analogous to setting an atomic value without using
|
||||
// synchronization.
|
||||
//
|
||||
// It may be helpful to document why a racy operation is permitted.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) RacyStore(val bool) {
|
||||
b.Uint32.RacyStore(b32(val))
|
||||
}
|
||||
|
||||
// Swap is analogous to atomic.SwapBool, if such a thing existed.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) Swap(val bool) bool {
|
||||
return b.Uint32.Swap(b32(val)) != 0
|
||||
}
|
||||
|
||||
// CompareAndSwap is analogous to atomic.CompareAndSwapBool, if such a thing
|
||||
// existed.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) CompareAndSwap(oldVal, newVal bool) bool {
|
||||
return b.Uint32.CompareAndSwap(b32(oldVal), b32(newVal))
|
||||
}
|
||||
|
||||
// LINT.ThenChange(32b_64bit.go)
|
||||
|
||||
@@ -77,9 +77,6 @@ func (i *Int32) Store(v int32) {
|
||||
//
|
||||
// It may be helpful to document why a racy operation is permitted.
|
||||
//
|
||||
// Don't add fields to this struct. It is important that it remain the same
|
||||
// size as its builtin analogue.
|
||||
//
|
||||
//go:nosplit
|
||||
func (i *Int32) RacyStore(v int32) {
|
||||
i.value = v
|
||||
@@ -124,6 +121,9 @@ func (i *Int32) ptr() *int32 {
|
||||
|
||||
// Uint32 is an atomic uint32.
|
||||
//
|
||||
// Don't add fields to this struct. It is important that it remain the same
|
||||
// size as its builtin analogue.
|
||||
//
|
||||
// See aligned_unsafe.go in this directory for justification.
|
||||
//
|
||||
// +stateify savable
|
||||
@@ -210,4 +210,80 @@ func (u *Uint32) ptr() *uint32 {
|
||||
return &u.value
|
||||
}
|
||||
|
||||
// Bool is an atomic Boolean.
|
||||
//
|
||||
// It is implemented by a Uint32, with value 0 indicating false, and 1
|
||||
// indicating true.
|
||||
//
|
||||
// +stateify savable
|
||||
type Bool struct {
|
||||
Uint32
|
||||
}
|
||||
|
||||
// b32 returns a uint32 0 or 1 representing b.
|
||||
func b32(b bool) uint32 {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// FromBool returns a Bool initialized to value val.
|
||||
//
|
||||
//go:nosplit
|
||||
func FromBool(val bool) Bool {
|
||||
return Bool{
|
||||
Uint32: FromUint32(b32(val)),
|
||||
}
|
||||
}
|
||||
|
||||
// Load is analogous to atomic.LoadBool, if such a thing existed.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) Load() bool {
|
||||
return b.Uint32.Load() != 0
|
||||
}
|
||||
|
||||
// RacyLoad is analogous to reading an atomic value without using
|
||||
// synchronization.
|
||||
//
|
||||
// It may be helpful to document why a racy operation is permitted.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) RacyLoad() bool {
|
||||
return b.Uint32.RacyLoad() != 0
|
||||
}
|
||||
|
||||
// Store is analogous to atomic.StoreBool, if such a thing existed.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) Store(val bool) {
|
||||
b.Uint32.Store(b32(val))
|
||||
}
|
||||
|
||||
// RacyStore is analogous to setting an atomic value without using
|
||||
// synchronization.
|
||||
//
|
||||
// It may be helpful to document why a racy operation is permitted.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) RacyStore(val bool) {
|
||||
b.Uint32.RacyStore(b32(val))
|
||||
}
|
||||
|
||||
// Swap is analogous to atomic.SwapBool, if such a thing existed.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) Swap(val bool) bool {
|
||||
return b.Uint32.Swap(b32(val)) != 0
|
||||
}
|
||||
|
||||
// CompareAndSwap is analogous to atomic.CompareAndSwapBool, if such a thing
|
||||
// existed.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) CompareAndSwap(oldVal, newVal bool) bool {
|
||||
return b.Uint32.CompareAndSwap(b32(oldVal), b32(newVal))
|
||||
}
|
||||
|
||||
// LINT.ThenChange(32b_32bit.go)
|
||||
|
||||
@@ -18,7 +18,6 @@ go_library(
|
||||
"atomicbitops_arm64.s",
|
||||
"atomicbitops_float64.go",
|
||||
"atomicbitops_noasm.go",
|
||||
"bool.go",
|
||||
],
|
||||
visibility = ["//:sandbox"],
|
||||
deps = [
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
// Copyright 2022 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.
|
||||
|
||||
package atomicbitops
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
// Bool is an atomic Boolean.
|
||||
//
|
||||
// It is implemented by a Uint32, with value 0 indicating false, and 1
|
||||
// indicating true.
|
||||
//
|
||||
// +stateify savable
|
||||
type Bool struct {
|
||||
Uint32
|
||||
}
|
||||
|
||||
// FromBool returns an Bool initialized to value val.
|
||||
//
|
||||
//go:nosplit
|
||||
func FromBool(val bool) Bool {
|
||||
var u uint32
|
||||
if val {
|
||||
u = 1
|
||||
}
|
||||
return Bool{
|
||||
Uint32{
|
||||
value: u,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Load is analogous to atomic.LoadBool, if such a thing existed.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) Load() bool {
|
||||
return atomic.LoadUint32(&b.value) == 1
|
||||
}
|
||||
|
||||
// Store is analogous to atomic.StoreBool, if such a thing existed.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) Store(val bool) {
|
||||
var u uint32
|
||||
if val {
|
||||
u = 1
|
||||
}
|
||||
atomic.StoreUint32(&b.value, u)
|
||||
}
|
||||
|
||||
// Swap is analogous to atomic.SwapBool, if such a thing existed.
|
||||
//
|
||||
//go:nosplit
|
||||
func (b *Bool) Swap(val bool) bool {
|
||||
var u uint32
|
||||
if val {
|
||||
u = 1
|
||||
}
|
||||
return atomic.SwapUint32(&b.value, u) == 1
|
||||
}
|
||||
@@ -116,7 +116,7 @@ func StartProfilingMetrics(profilingMetrics string, profilingRate time.Duration)
|
||||
return fmt.Errorf("a value for --profiling-metrics was not specified; also no conditionally compiled metrics found, consider compiling runsc with --go_tag=condmetric_profiling")
|
||||
}
|
||||
|
||||
if !profilingMetricsStarted.CompareAndSwap(0, 1) {
|
||||
if !profilingMetricsStarted.CompareAndSwap(false, true) {
|
||||
return errors.New("profiling metrics have already been started")
|
||||
}
|
||||
s := snapshots{
|
||||
|
||||
Reference in New Issue
Block a user