github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/pkg/sync/mutex_unsafe.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package sync 7 8 import ( 9 "sync" 10 "unsafe" 11 ) 12 13 // CrossGoroutineMutex is equivalent to Mutex, but it need not be unlocked by a 14 // the same goroutine that locked the mutex. 15 type CrossGoroutineMutex struct { 16 m sync.Mutex 17 } 18 19 // Lock locks the underlying Mutex. 20 // +checklocksignore 21 func (m *CrossGoroutineMutex) Lock() { 22 m.m.Lock() 23 } 24 25 // Unlock unlocks the underlying Mutex. 26 // +checklocksignore 27 func (m *CrossGoroutineMutex) Unlock() { 28 m.m.Unlock() 29 } 30 31 // TryLock tries to acquire the mutex. It returns true if it succeeds and false 32 // otherwise. TryLock does not block. 33 func (m *CrossGoroutineMutex) TryLock() bool { 34 return m.m.TryLock() 35 } 36 37 // Mutex is a mutual exclusion lock. The zero value for a Mutex is an unlocked 38 // mutex. 39 // 40 // A Mutex must not be copied after first use. 41 // 42 // A Mutex must be unlocked by the same goroutine that locked it. This 43 // invariant is enforced with the 'checklocks' build tag. 44 type Mutex struct { 45 m CrossGoroutineMutex 46 } 47 48 // Lock locks m. If the lock is already in use, the calling goroutine blocks 49 // until the mutex is available. 50 // +checklocksignore 51 func (m *Mutex) Lock() { 52 noteLock(unsafe.Pointer(m)) 53 m.m.Lock() 54 } 55 56 // Unlock unlocks m. 57 // 58 // Preconditions: 59 // - m is locked. 60 // - m was locked by this goroutine. 61 // 62 // +checklocksignore 63 func (m *Mutex) Unlock() { 64 noteUnlock(unsafe.Pointer(m)) 65 m.m.Unlock() 66 } 67 68 // TryLock tries to acquire the mutex. It returns true if it succeeds and false 69 // otherwise. TryLock does not block. 70 // +checklocksignore 71 func (m *Mutex) TryLock() bool { 72 // Note lock first to enforce proper locking even if unsuccessful. 73 noteLock(unsafe.Pointer(m)) 74 locked := m.m.TryLock() 75 if !locked { 76 noteUnlock(unsafe.Pointer(m)) 77 } 78 return locked 79 }