github.com/sagernet/gvisor@v0.0.0-20240428053021-e691de28565f/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  }