Do not copy sleep.Waker

sleep.Waker's fields are modified as values.

PiperOrigin-RevId: 320873451
This commit is contained in:
Ghanan Gowripalan
2020-07-12 17:22:08 -07:00
committed by gVisor bot
parent 69f2059e5d
commit 9c32fd3f4d
7 changed files with 50 additions and 42 deletions
+1
View File
@@ -12,6 +12,7 @@ go_library(
"sleep_unsafe.go",
],
visibility = ["//:sandbox"],
deps = ["//pkg/sync"],
)
go_test(
+7 -13
View File
@@ -379,10 +379,7 @@ func TestRace(t *testing.T) {
// TestRaceInOrder tests that multiple wakers can continuously send wake requests to
// the sleeper and that the wakers are retrieved in the order asserted.
func TestRaceInOrder(t *testing.T) {
const wakers = 100
const wakeRequests = 10000
w := make([]Waker, wakers)
w := make([]Waker, 10000)
s := Sleeper{}
// Associate each waker and start goroutines that will assert them.
@@ -390,19 +387,16 @@ func TestRaceInOrder(t *testing.T) {
s.AddWaker(&w[i], i)
}
go func() {
n := 0
for n < wakeRequests {
wk := w[n%len(w)]
wk.Assert()
n++
for i := range w {
w[i].Assert()
}
}()
// Wait for all wake up notifications from all wakers.
for i := 0; i < wakeRequests; i++ {
v, _ := s.Fetch(true)
if got, want := v, i%wakers; got != want {
t.Fatalf("got %d want %d", got, want)
for want := range w {
got, _ := s.Fetch(true)
if got != want {
t.Fatalf("got %d want %d", got, want)
}
}
}
+7
View File
@@ -75,6 +75,8 @@ package sleep
import (
"sync/atomic"
"unsafe"
"gvisor.dev/gvisor/pkg/sync"
)
const (
@@ -323,7 +325,12 @@ func (s *Sleeper) enqueueAssertedWaker(w *Waker) {
//
// This struct is thread-safe, that is, its methods can be called concurrently
// by multiple goroutines.
//
// Note, it is not safe to copy a Waker as its fields are modified by value
// (the pointer fields are individually modified with atomic operations).
type Waker struct {
_ sync.NoCopy
// s is the sleeper that this waker can wake up. Only one sleeper at a
// time is allowed. This field can have three classes of values:
// nil -- the waker is not asserted: it either is not associated with
+1
View File
@@ -33,6 +33,7 @@ go_library(
"aliases.go",
"memmove_unsafe.go",
"mutex_unsafe.go",
"nocopy.go",
"norace_unsafe.go",
"race_unsafe.go",
"rwmutex_unsafe.go",
+28
View File
@@ -0,0 +1,28 @@
// Copyright 2020 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 sync
// NoCopy may be embedded into structs which must not be copied
// after the first use.
//
// See https://golang.org/issues/8005#issuecomment-190753527
// for details.
type NoCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`.
func (*NoCopy) Lock() {}
// Unlock is a no-op used by -copylocks checker from `go vet`.
func (*NoCopy) Unlock() {}
+2 -12
View File
@@ -14,6 +14,7 @@
package stack
import (
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
)
@@ -24,7 +25,7 @@ import (
// multiple endpoints. Clone() should be called in such cases so that
// modifications to the Data field do not affect other copies.
type PacketBuffer struct {
_ noCopy
_ sync.NoCopy
// PacketBufferEntry is used to build an intrusive list of
// PacketBuffers.
@@ -102,14 +103,3 @@ func (pk *PacketBuffer) Clone() *PacketBuffer {
NatDone: pk.NatDone,
}
}
// noCopy may be embedded into structs which must not be copied
// after the first use.
//
// See https://golang.org/issues/8005#issuecomment-190753527
// for details.
type noCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock() {}
func (*noCopy) Unlock() {}
+4 -17
View File
@@ -15,8 +15,9 @@
package tcpip
import (
"sync"
"time"
"gvisor.dev/gvisor/pkg/sync"
)
// cancellableTimerInstance is a specific instance of CancellableTimer.
@@ -92,6 +93,8 @@ func (t *cancellableTimerInstance) stop() {
// Note, it is not safe to copy a CancellableTimer as its timer instance creates
// a closure over the address of the CancellableTimer.
type CancellableTimer struct {
_ sync.NoCopy
// The active instance of a cancellable timer.
instance cancellableTimerInstance
@@ -157,22 +160,6 @@ func (t *CancellableTimer) Reset(d time.Duration) {
}
}
// Lock is a no-op used by the copylocks checker from go vet.
//
// See CancellableTimer for details about why it shouldn't be copied.
//
// See https://github.com/golang/go/issues/8005#issuecomment-190753527 for more
// details about the copylocks checker.
func (*CancellableTimer) Lock() {}
// Unlock is a no-op used by the copylocks checker from go vet.
//
// See CancellableTimer for details about why it shouldn't be copied.
//
// See https://github.com/golang/go/issues/8005#issuecomment-190753527 for more
// details about the copylocks checker.
func (*CancellableTimer) Unlock() {}
// NewCancellableTimer returns an unscheduled CancellableTimer with the given
// locker and fn.
//