mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-15 19:21:39 +00:00
syncs: use TryLock and TryRLock instead of unsafe
The docs say: Note that while correct uses of TryLock do exist, they are rare, and use of TryLock is often a sign of a deeper problem in a particular use of mutexes. Rare code! Or bad code! Who can tell! Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
This commit is contained in:
parent
ead16b24ec
commit
997b19545b
@ -64,7 +64,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
||||
💣 tailscale.com/net/tshttpproxy from tailscale.com/derp/derphttp+
|
||||
💣 tailscale.com/paths from tailscale.com/cmd/tailscale/cli+
|
||||
tailscale.com/safesocket from tailscale.com/cmd/tailscale/cli+
|
||||
💣 tailscale.com/syncs from tailscale.com/net/interfaces+
|
||||
tailscale.com/syncs from tailscale.com/net/interfaces+
|
||||
tailscale.com/tailcfg from tailscale.com/cmd/tailscale/cli+
|
||||
W tailscale.com/tsconst from tailscale.com/net/interfaces
|
||||
💣 tailscale.com/tstime/mono from tailscale.com/tstime/rate
|
||||
|
@ -228,7 +228,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
||||
tailscale.com/safesocket from tailscale.com/client/tailscale+
|
||||
tailscale.com/smallzstd from tailscale.com/ipn/ipnserver+
|
||||
LD 💣 tailscale.com/ssh/tailssh from tailscale.com/wgengine/netstack
|
||||
💣 tailscale.com/syncs from tailscale.com/control/controlknobs+
|
||||
tailscale.com/syncs from tailscale.com/control/controlknobs+
|
||||
tailscale.com/tailcfg from tailscale.com/client/tailscale+
|
||||
W tailscale.com/tsconst from tailscale.com/net/interfaces
|
||||
tailscale.com/tstime from tailscale.com/wgengine/magicsock
|
||||
|
@ -2,58 +2,32 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.13 && !go1.19
|
||||
// +build go1.13,!go1.19
|
||||
|
||||
// This file makes assumptions about the inner workings of sync.Mutex and sync.RWMutex.
|
||||
// This includes not just their memory layout but their invariants and functionality.
|
||||
// To prevent accidents, it is limited to a known good subset of Go versions.
|
||||
|
||||
package syncs
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
mutexLocked = 1
|
||||
|
||||
// sync.Mutex field offsets
|
||||
stateOffset = 0
|
||||
|
||||
// sync.RWMutext field offsets
|
||||
mutexOffset = 0
|
||||
readerCountOffset = 16
|
||||
)
|
||||
|
||||
// add returns a pointer with value p + off.
|
||||
func add(p unsafe.Pointer, off uintptr) unsafe.Pointer {
|
||||
return unsafe.Pointer(uintptr(p) + off)
|
||||
}
|
||||
|
||||
// AssertLocked panics if m is not locked.
|
||||
func AssertLocked(m *sync.Mutex) {
|
||||
p := add(unsafe.Pointer(m), stateOffset)
|
||||
if atomic.LoadInt32((*int32)(p))&mutexLocked == 0 {
|
||||
if m.TryLock() {
|
||||
m.Unlock()
|
||||
panic("mutex is not locked")
|
||||
}
|
||||
}
|
||||
|
||||
// AssertRLocked panics if rw is not locked for reading or writing.
|
||||
func AssertRLocked(rw *sync.RWMutex) {
|
||||
p := add(unsafe.Pointer(rw), readerCountOffset)
|
||||
if atomic.LoadInt32((*int32)(p)) != 0 {
|
||||
// There are readers present or writers pending, so someone has a read lock.
|
||||
return
|
||||
if rw.TryLock() {
|
||||
rw.Unlock()
|
||||
panic("mutex is not locked")
|
||||
}
|
||||
// No readers.
|
||||
AssertWLocked(rw)
|
||||
}
|
||||
|
||||
// AssertWLocked panics if rw is not locked for writing.
|
||||
func AssertWLocked(rw *sync.RWMutex) {
|
||||
m := (*sync.Mutex)(add(unsafe.Pointer(rw), mutexOffset))
|
||||
AssertLocked(m)
|
||||
if rw.TryRLock() {
|
||||
rw.RUnlock()
|
||||
panic("mutex is not rlocked")
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user