mutex_unsafe.go raw

   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  }
  80