summaryrefslogtreecommitdiffhomepage
path: root/pkg/sync
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2020-01-22 03:24:18 +0000
committergVisor bot <gvisor-bot@google.com>2020-01-22 03:24:18 +0000
commit4450d973d9b18d7bfc9a7647cc5640440df6de70 (patch)
tree42ef402466dd9f6f8cdce6651dd08aa4c7ec591b /pkg/sync
parentca8d1cb6db085a700627f613d37b66ec2d1313e7 (diff)
parentd0e75f2bef4e16356693987db6ae6bbdce749618 (diff)
Merge release-20200115.0-68-gd0e75f2 (automated)
Diffstat (limited to 'pkg/sync')
-rwxr-xr-xpkg/sync/downgradable_rwmutex_unsafe.go68
1 files changed, 60 insertions, 8 deletions
diff --git a/pkg/sync/downgradable_rwmutex_unsafe.go b/pkg/sync/downgradable_rwmutex_unsafe.go
index 9bb55cd3a..0d321f5e3 100755
--- a/pkg/sync/downgradable_rwmutex_unsafe.go
+++ b/pkg/sync/downgradable_rwmutex_unsafe.go
@@ -19,7 +19,6 @@
package sync
import (
- "sync"
"sync/atomic"
"unsafe"
)
@@ -30,18 +29,43 @@ func runtimeSemacquire(s *uint32)
//go:linkname runtimeSemrelease sync.runtime_Semrelease
func runtimeSemrelease(s *uint32, handoff bool, skipframes int)
-// DowngradableRWMutex is identical to sync.RWMutex, but adds the DowngradeLock
-// method.
+// DowngradableRWMutex is identical to sync.RWMutex, but adds the DowngradeLock,
+// TryLock and TryRLock methods.
type DowngradableRWMutex struct {
- w sync.Mutex // held if there are pending writers
- writerSem uint32 // semaphore for writers to wait for completing readers
- readerSem uint32 // semaphore for readers to wait for completing writers
- readerCount int32 // number of pending readers
- readerWait int32 // number of departing readers
+ w TMutex // held if there are pending writers
+ writerSem uint32 // semaphore for writers to wait for completing readers
+ readerSem uint32 // semaphore for readers to wait for completing writers
+ readerCount int32 // number of pending readers
+ readerWait int32 // number of departing readers
}
const rwmutexMaxReaders = 1 << 30
+// TryRLock locks rw for reading. It returns true if it succeeds and false
+// otherwise. It does not block.
+func (rw *DowngradableRWMutex) TryRLock() bool {
+ if RaceEnabled {
+ RaceDisable()
+ }
+ for {
+ rc := atomic.LoadInt32(&rw.readerCount)
+ if rc < 0 {
+ if RaceEnabled {
+ RaceEnable()
+ }
+ return false
+ }
+ if !atomic.CompareAndSwapInt32(&rw.readerCount, rc, rc+1) {
+ continue
+ }
+ if RaceEnabled {
+ RaceEnable()
+ RaceAcquire(unsafe.Pointer(&rw.readerSem))
+ }
+ return true
+ }
+}
+
// RLock locks rw for reading.
func (rw *DowngradableRWMutex) RLock() {
if RaceEnabled {
@@ -78,6 +102,34 @@ func (rw *DowngradableRWMutex) RUnlock() {
}
}
+// TryLock locks rw for writing. It returns true if it succeeds and false
+// otherwise. It does not block.
+func (rw *DowngradableRWMutex) TryLock() bool {
+ if RaceEnabled {
+ RaceDisable()
+ }
+ // First, resolve competition with other writers.
+ if !rw.w.TryLock() {
+ if RaceEnabled {
+ RaceEnable()
+ }
+ return false
+ }
+ // Only proceed if there are no readers.
+ if !atomic.CompareAndSwapInt32(&rw.readerCount, 0, -rwmutexMaxReaders) {
+ rw.w.Unlock()
+ if RaceEnabled {
+ RaceEnable()
+ }
+ return false
+ }
+ if RaceEnabled {
+ RaceEnable()
+ RaceAcquire(unsafe.Pointer(&rw.writerSem))
+ }
+ return true
+}
+
// Lock locks rw for writing.
func (rw *DowngradableRWMutex) Lock() {
if RaceEnabled {