package runtime
import (
)
type rwmutex struct {
rLock mutex
readers muintptr
readerPass uint32
wLock mutex
writer muintptr
readerCount uint32
readerWait uint32
}
const rwmutexMaxReaders = 1 << 30
func ( *rwmutex) () {
acquirem()
if int32(atomic.Xadd(&.readerCount, 1)) < 0 {
systemstack(func() {
lockWithRank(&.rLock, lockRankRwmutexR)
if .readerPass > 0 {
.readerPass -= 1
unlock(&.rLock)
} else {
:= getg().m
.schedlink = .readers
.readers.set()
unlock(&.rLock)
notesleep(&.park)
noteclear(&.park)
}
})
}
}
func ( *rwmutex) () {
if := int32(atomic.Xadd(&.readerCount, -1)); < 0 {
if +1 == 0 || +1 == -rwmutexMaxReaders {
throw("runlock of unlocked rwmutex")
}
if atomic.Xadd(&.readerWait, -1) == 0 {
lockWithRank(&.rLock, lockRankRwmutexR)
:= .writer.ptr()
if != nil {
notewakeup(&.park)
}
unlock(&.rLock)
}
}
releasem(getg().m)
}
func ( *rwmutex) () {
lockWithRank(&.wLock, lockRankRwmutexW)
:= getg().m
:= int32(atomic.Xadd(&.readerCount, -rwmutexMaxReaders)) + rwmutexMaxReaders
lockWithRank(&.rLock, lockRankRwmutexR)
if != 0 && atomic.Xadd(&.readerWait, ) != 0 {
systemstack(func() {
.writer.set()
unlock(&.rLock)
notesleep(&.park)
noteclear(&.park)
})
} else {
unlock(&.rLock)
}
}
func ( *rwmutex) () {
:= int32(atomic.Xadd(&.readerCount, rwmutexMaxReaders))
if >= rwmutexMaxReaders {
throw("unlock of unlocked rwmutex")
}
lockWithRank(&.rLock, lockRankRwmutexR)
for .readers.ptr() != nil {
:= .readers.ptr()
.readers = .schedlink
.schedlink.set(nil)
notewakeup(&.park)
-= 1
}
.readerPass += uint32()
unlock(&.rLock)
unlock(&.wLock)
}