Source File
mutex.go
Belonging Package
sync
package sync
import (
)
func (string) // provided by runtime
type Locker interface {
Lock()
Unlock()
}
const (
mutexLocked = 1 << iota // mutex is locked
mutexWoken
mutexStarving
mutexWaiterShift = iota
starvationThresholdNs = 1e6
)
if atomic.CompareAndSwapInt32(&.state, 0, mutexLocked) {
if race.Enabled {
race.Acquire(unsafe.Pointer())
}
return
if ! && &mutexWoken == 0 && >>mutexWaiterShift != 0 &&
atomic.CompareAndSwapInt32(&.state, , |mutexWoken) {
= true
}
runtime_doSpin()
++
= .state
continue
}
if &mutexStarving == 0 {
|= mutexLocked
}
if &(mutexLocked|mutexStarving) != 0 {
+= 1 << mutexWaiterShift
if && &mutexLocked != 0 {
|= mutexStarving
}
if &mutexWoken == 0 {
throw("sync: inconsistent mutex state")
}
&^= mutexWoken
}
if atomic.CompareAndSwapInt32(&.state, , ) {
if &(mutexLocked|mutexStarving) == 0 {
break // locked the mutex with CAS
:= != 0
if == 0 {
= runtime_nanotime()
}
runtime_SemacquireMutex(&.sema, , 1)
= || runtime_nanotime()- > starvationThresholdNs
= .state
if &(mutexLocked|mutexWoken) != 0 || >>mutexWaiterShift == 0 {
throw("sync: inconsistent mutex state")
}
:= int32(mutexLocked - 1<<mutexWaiterShift)
:= atomic.AddInt32(&.state, -mutexLocked)
.unlockSlow()
}
}
func ( *Mutex) ( int32) {
if (+mutexLocked)&mutexLocked == 0 {
throw("sync: unlock of unlocked mutex")
}
if &mutexStarving == 0 {
:=
if >>mutexWaiterShift == 0 || &(mutexLocked|mutexWoken|mutexStarving) != 0 {
return
= ( - 1<<mutexWaiterShift) | mutexWoken
if atomic.CompareAndSwapInt32(&.state, , ) {
runtime_Semrelease(&.sema, false, 1)
return
}
= .state
}
runtime_Semrelease(&.sema, true, 1)
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin 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. |