mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-16 11:41: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/net/tshttpproxy from tailscale.com/derp/derphttp+
|
||||||
💣 tailscale.com/paths from tailscale.com/cmd/tailscale/cli+
|
💣 tailscale.com/paths from tailscale.com/cmd/tailscale/cli+
|
||||||
tailscale.com/safesocket 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+
|
tailscale.com/tailcfg from tailscale.com/cmd/tailscale/cli+
|
||||||
W tailscale.com/tsconst from tailscale.com/net/interfaces
|
W tailscale.com/tsconst from tailscale.com/net/interfaces
|
||||||
💣 tailscale.com/tstime/mono from tailscale.com/tstime/rate
|
💣 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/safesocket from tailscale.com/client/tailscale+
|
||||||
tailscale.com/smallzstd from tailscale.com/ipn/ipnserver+
|
tailscale.com/smallzstd from tailscale.com/ipn/ipnserver+
|
||||||
LD 💣 tailscale.com/ssh/tailssh from tailscale.com/wgengine/netstack
|
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+
|
tailscale.com/tailcfg from tailscale.com/client/tailscale+
|
||||||
W tailscale.com/tsconst from tailscale.com/net/interfaces
|
W tailscale.com/tsconst from tailscale.com/net/interfaces
|
||||||
tailscale.com/tstime from tailscale.com/wgengine/magicsock
|
tailscale.com/tstime from tailscale.com/wgengine/magicsock
|
||||||
|
@ -2,58 +2,32 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// 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
|
package syncs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"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.
|
// AssertLocked panics if m is not locked.
|
||||||
func AssertLocked(m *sync.Mutex) {
|
func AssertLocked(m *sync.Mutex) {
|
||||||
p := add(unsafe.Pointer(m), stateOffset)
|
if m.TryLock() {
|
||||||
if atomic.LoadInt32((*int32)(p))&mutexLocked == 0 {
|
m.Unlock()
|
||||||
panic("mutex is not locked")
|
panic("mutex is not locked")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssertRLocked panics if rw is not locked for reading or writing.
|
// AssertRLocked panics if rw is not locked for reading or writing.
|
||||||
func AssertRLocked(rw *sync.RWMutex) {
|
func AssertRLocked(rw *sync.RWMutex) {
|
||||||
p := add(unsafe.Pointer(rw), readerCountOffset)
|
if rw.TryLock() {
|
||||||
if atomic.LoadInt32((*int32)(p)) != 0 {
|
rw.Unlock()
|
||||||
// There are readers present or writers pending, so someone has a read lock.
|
panic("mutex is not locked")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
// No readers.
|
|
||||||
AssertWLocked(rw)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssertWLocked panics if rw is not locked for writing.
|
// AssertWLocked panics if rw is not locked for writing.
|
||||||
func AssertWLocked(rw *sync.RWMutex) {
|
func AssertWLocked(rw *sync.RWMutex) {
|
||||||
m := (*sync.Mutex)(add(unsafe.Pointer(rw), mutexOffset))
|
if rw.TryRLock() {
|
||||||
AssertLocked(m)
|
rw.RUnlock()
|
||||||
|
panic("mutex is not rlocked")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user