package runtime
import (
"runtime/internal/atomic"
)
type rwmutex struct {
rLock mutex
readers muintptr
readerPass uint32
wLock mutex
writer muintptr
readerCount uint32
readerWait uint32
}
const rwmutexMaxReaders = 1 << 30
func (rw *rwmutex ) rlock () {
acquirem ()
if int32 (atomic .Xadd (&rw .readerCount , 1 )) < 0 {
systemstack (func () {
lockWithRank (&rw .rLock , lockRankRwmutexR )
if rw .readerPass > 0 {
rw .readerPass -= 1
unlock (&rw .rLock )
} else {
m := getg ().m
m .schedlink = rw .readers
rw .readers .set (m )
unlock (&rw .rLock )
notesleep (&m .park )
noteclear (&m .park )
}
})
}
}
func (rw *rwmutex ) runlock () {
if r := int32 (atomic .Xadd (&rw .readerCount , -1 )); r < 0 {
if r +1 == 0 || r +1 == -rwmutexMaxReaders {
throw ("runlock of unlocked rwmutex" )
}
if atomic .Xadd (&rw .readerWait , -1 ) == 0 {
lockWithRank (&rw .rLock , lockRankRwmutexR )
w := rw .writer .ptr ()
if w != nil {
notewakeup (&w .park )
}
unlock (&rw .rLock )
}
}
releasem (getg ().m )
}
func (rw *rwmutex ) lock () {
lockWithRank (&rw .wLock , lockRankRwmutexW )
m := getg ().m
r := int32 (atomic .Xadd (&rw .readerCount , -rwmutexMaxReaders )) + rwmutexMaxReaders
lockWithRank (&rw .rLock , lockRankRwmutexR )
if r != 0 && atomic .Xadd (&rw .readerWait , r ) != 0 {
systemstack (func () {
rw .writer .set (m )
unlock (&rw .rLock )
notesleep (&m .park )
noteclear (&m .park )
})
} else {
unlock (&rw .rLock )
}
}
func (rw *rwmutex ) unlock () {
r := int32 (atomic .Xadd (&rw .readerCount , rwmutexMaxReaders ))
if r >= rwmutexMaxReaders {
throw ("unlock of unlocked rwmutex" )
}
lockWithRank (&rw .rLock , lockRankRwmutexR )
for rw .readers .ptr () != nil {
reader := rw .readers .ptr ()
rw .readers = reader .schedlink
reader .schedlink .set (nil )
notewakeup (&reader .park )
r -= 1
}
rw .readerPass += uint32 (r )
unlock (&rw .rLock )
unlock (&rw .wLock )
}
The pages are generated with Golds v0.4.5 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .