mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
@@ -38,6 +38,7 @@ go_library(
|
||||
"race_unsafe.go",
|
||||
"seqcount.go",
|
||||
"syncutil.go",
|
||||
"tmutex_unsafe.go",
|
||||
],
|
||||
importpath = "gvisor.dev/gvisor/pkg/sync",
|
||||
)
|
||||
@@ -48,6 +49,7 @@ go_test(
|
||||
srcs = [
|
||||
"downgradable_rwmutex_test.go",
|
||||
"seqcount_test.go",
|
||||
"tmutex_test.go",
|
||||
],
|
||||
embed = [":sync"],
|
||||
)
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright 2019 The gVisor Authors.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package sync
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// TestStructSize verifies that syncMutex's size hasn't drifted from the
|
||||
// standard library's version.
|
||||
//
|
||||
// The correctness of this package relies on these remaining in sync.
|
||||
func TestStructSize(t *testing.T) {
|
||||
const (
|
||||
got = unsafe.Sizeof(syncMutex{})
|
||||
want = unsafe.Sizeof(sync.Mutex{})
|
||||
)
|
||||
if got != want {
|
||||
t.Errorf("got sizeof(syncMutex) = %d, want = sizeof(sync.Mutex) = %d", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestFieldValues verifies that the semantics of syncMutex.state from the
|
||||
// standard library's implementation.
|
||||
//
|
||||
// The correctness of this package relies on these remaining in sync.
|
||||
func TestFieldValues(t *testing.T) {
|
||||
var m TMutex
|
||||
m.Lock()
|
||||
if got := *m.state(); got != mutexLocked {
|
||||
t.Errorf("got locked sync.Mutex.state = %d, want = %d", got, mutexLocked)
|
||||
}
|
||||
m.Unlock()
|
||||
if got := *m.state(); got != mutexUnlocked {
|
||||
t.Errorf("got unlocked sync.Mutex.state = %d, want = %d", got, mutexUnlocked)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoubleTryLock(t *testing.T) {
|
||||
var m TMutex
|
||||
if !m.TryLock() {
|
||||
t.Fatal("failed to aquire lock")
|
||||
}
|
||||
if m.TryLock() {
|
||||
t.Fatal("unexpectedly succeeded in aquiring locked mutex")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTryLockAfterLock(t *testing.T) {
|
||||
var m TMutex
|
||||
m.Lock()
|
||||
if m.TryLock() {
|
||||
t.Fatal("unexpectedly succeeded in aquiring locked mutex")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTryLockUnlock(t *testing.T) {
|
||||
var m TMutex
|
||||
if !m.TryLock() {
|
||||
t.Fatal("failed to aquire lock")
|
||||
}
|
||||
m.Unlock()
|
||||
if !m.TryLock() {
|
||||
t.Fatal("failed to aquire lock after unlock")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2019 The gVisor Authors.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.13
|
||||
// +build !go1.15
|
||||
|
||||
// When updating the build constraint (above), check that syncMutex matches the
|
||||
// standard library sync.Mutex definition.
|
||||
|
||||
package sync
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// TMutex is a try lock.
|
||||
type TMutex struct {
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
type syncMutex struct {
|
||||
state int32
|
||||
sema uint32
|
||||
}
|
||||
|
||||
func (m *TMutex) state() *int32 {
|
||||
return &(*syncMutex)(unsafe.Pointer(&m.Mutex)).state
|
||||
}
|
||||
|
||||
const (
|
||||
mutexUnlocked = 0
|
||||
mutexLocked = 1
|
||||
)
|
||||
|
||||
// TryLock tries to aquire the mutex. It returns true if it succeeds and false
|
||||
// otherwise. TryLock does not block.
|
||||
func (m *TMutex) TryLock() bool {
|
||||
if atomic.CompareAndSwapInt32(m.state(), mutexUnlocked, mutexLocked) {
|
||||
if RaceEnabled {
|
||||
RaceAcquire(unsafe.Pointer(&m.Mutex))
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user