diff options
author | pg <pg@yandex-team.com> | 2024-02-08 21:53:38 +0300 |
---|---|---|
committer | pg <pg@yandex-team.com> | 2024-02-08 22:09:55 +0300 |
commit | 8f0f06e7e5ea421375dc26ae5146934f64c21a5c (patch) | |
tree | c3999cdb83dfb8022079d7a631c835b2c3700916 /contrib/go/_std_1.21/src/runtime/rwmutex.go | |
parent | 675108d8da834c3551181bb62db4d19e012d4941 (diff) | |
download | ydb-8f0f06e7e5ea421375dc26ae5146934f64c21a5c.tar.gz |
Diffstat (limited to 'contrib/go/_std_1.21/src/runtime/rwmutex.go')
-rw-r--r-- | contrib/go/_std_1.21/src/runtime/rwmutex.go | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/contrib/go/_std_1.21/src/runtime/rwmutex.go b/contrib/go/_std_1.21/src/runtime/rwmutex.go index ede3d13599..34d8f675c1 100644 --- a/contrib/go/_std_1.21/src/runtime/rwmutex.go +++ b/contrib/go/_std_1.21/src/runtime/rwmutex.go @@ -25,6 +25,43 @@ type rwmutex struct { readerCount atomic.Int32 // number of pending readers readerWait atomic.Int32 // number of departing readers + + readRank lockRank // semantic lock rank for read locking +} + +// Lock ranking an rwmutex has two aspects: +// +// Semantic ranking: this rwmutex represents some higher level lock that +// protects some resource (e.g., allocmLock protects creation of new Ms). The +// read and write locks of that resource need to be represented in the lock +// rank. +// +// Internal ranking: as an implementation detail, rwmutex uses two mutexes: +// rLock and wLock. These have lock order requirements: wLock must be locked +// before rLock. This also needs to be represented in the lock rank. +// +// Semantic ranking is represented by acquiring readRank during read lock and +// writeRank during write lock. +// +// wLock is held for the duration of a write lock, so it uses writeRank +// directly, both for semantic and internal ranking. rLock is only held +// temporarily inside the rlock/lock methods, so it uses readRankInternal to +// represent internal ranking. Semantic ranking is represented by a separate +// acquire of readRank for the duration of a read lock. +// +// The lock ranking must document this ordering: +// - readRankInternal is a leaf lock. +// - readRank is taken before readRankInternal. +// - writeRank is taken before readRankInternal. +// - readRank is placed in the lock order wherever a read lock of this rwmutex +// belongs. +// - writeRank is placed in the lock order wherever a write lock of this +// rwmutex belongs. +func (rw *rwmutex) init(readRank, readRankInternal, writeRank lockRank) { + rw.readRank = readRank + + lockInit(&rw.rLock, readRankInternal) + lockInit(&rw.wLock, writeRank) } const rwmutexMaxReaders = 1 << 30 @@ -36,10 +73,14 @@ func (rw *rwmutex) rlock() { // deadlock (issue #20903). Alternatively, we could drop the P // while sleeping. acquirem() + + acquireLockRank(rw.readRank) + lockWithRankMayAcquire(&rw.rLock, getLockRank(&rw.rLock)) + if rw.readerCount.Add(1) < 0 { // A writer is pending. Park on the reader queue. systemstack(func() { - lockWithRank(&rw.rLock, lockRankRwmutexR) + lock(&rw.rLock) if rw.readerPass > 0 { // Writer finished. rw.readerPass -= 1 @@ -67,7 +108,7 @@ func (rw *rwmutex) runlock() { // A writer is pending. if rw.readerWait.Add(-1) == 0 { // The last reader unblocks the writer. - lockWithRank(&rw.rLock, lockRankRwmutexR) + lock(&rw.rLock) w := rw.writer.ptr() if w != nil { notewakeup(&w.park) @@ -75,18 +116,19 @@ func (rw *rwmutex) runlock() { unlock(&rw.rLock) } } + releaseLockRank(rw.readRank) releasem(getg().m) } // lock locks rw for writing. func (rw *rwmutex) lock() { // Resolve competition with other writers and stick to our P. - lockWithRank(&rw.wLock, lockRankRwmutexW) + lock(&rw.wLock) m := getg().m // Announce that there is a pending writer. r := rw.readerCount.Add(-rwmutexMaxReaders) + rwmutexMaxReaders // Wait for any active readers to complete. - lockWithRank(&rw.rLock, lockRankRwmutexR) + lock(&rw.rLock) if r != 0 && rw.readerWait.Add(r) != 0 { // Wait for reader to wake us up. systemstack(func() { @@ -108,7 +150,7 @@ func (rw *rwmutex) unlock() { throw("unlock of unlocked rwmutex") } // Unblock blocked readers. - lockWithRank(&rw.rLock, lockRankRwmutexR) + lock(&rw.rLock) for rw.readers.ptr() != nil { reader := rw.readers.ptr() rw.readers = reader.schedlink |