package runtime
import (
)
const (
mutex_unlocked = 0
mutex_locked = 1
mutex_sleeping = 2
active_spin = 4
active_spin_cnt = 30
passive_spin = 1
)
func ( *uintptr) *uint32 {
return (*uint32)(unsafe.Pointer())
}
func ( *mutex) {
lockWithRank(, getLockRank())
}
func ( *mutex) {
:= getg()
if .m.locks < 0 {
throw("runtime·lock: lock count")
}
.m.locks++
:= atomic.Xchg(key32(&.key), mutex_locked)
if == mutex_unlocked {
return
}
:=
:= 0
if ncpu > 1 {
= active_spin
}
for {
for := 0; < ; ++ {
for .key == mutex_unlocked {
if atomic.Cas(key32(&.key), mutex_unlocked, ) {
return
}
}
procyield(active_spin_cnt)
}
for := 0; < passive_spin; ++ {
for .key == mutex_unlocked {
if atomic.Cas(key32(&.key), mutex_unlocked, ) {
return
}
}
osyield()
}
= atomic.Xchg(key32(&.key), mutex_sleeping)
if == mutex_unlocked {
return
}
= mutex_sleeping
futexsleep(key32(&.key), mutex_sleeping, -1)
}
}
func ( *mutex) {
unlockWithRank()
}
func ( *mutex) {
:= atomic.Xchg(key32(&.key), mutex_unlocked)
if == mutex_unlocked {
throw("unlock of unlocked lock")
}
if == mutex_sleeping {
futexwakeup(key32(&.key), 1)
}
:= getg()
.m.locks--
if .m.locks < 0 {
throw("runtime·unlock: lock count")
}
if .m.locks == 0 && .preempt {
.stackguard0 = stackPreempt
}
}
func ( *note) {
.key = 0
}
func ( *note) {
:= atomic.Xchg(key32(&.key), 1)
if != 0 {
print("notewakeup - double wakeup (", , ")\n")
throw("notewakeup - double wakeup")
}
futexwakeup(key32(&.key), 1)
}
func ( *note) {
:= getg()
if != .m.g0 {
throw("notesleep not on g0")
}
:= int64(-1)
if *cgo_yield != nil {
= 10e6
}
for atomic.Load(key32(&.key)) == 0 {
.m.blocked = true
futexsleep(key32(&.key), 0, )
if *cgo_yield != nil {
asmcgocall(*cgo_yield, nil)
}
.m.blocked = false
}
}
func ( *note, int64) bool {
:= getg()
if < 0 {
if *cgo_yield != nil {
= 10e6
}
for atomic.Load(key32(&.key)) == 0 {
.m.blocked = true
futexsleep(key32(&.key), 0, )
if *cgo_yield != nil {
asmcgocall(*cgo_yield, nil)
}
.m.blocked = false
}
return true
}
if atomic.Load(key32(&.key)) != 0 {
return true
}
:= nanotime() +
for {
if *cgo_yield != nil && > 10e6 {
= 10e6
}
.m.blocked = true
futexsleep(key32(&.key), 0, )
if *cgo_yield != nil {
asmcgocall(*cgo_yield, nil)
}
.m.blocked = false
if atomic.Load(key32(&.key)) != 0 {
break
}
:= nanotime()
if >= {
break
}
= -
}
return atomic.Load(key32(&.key)) != 0
}
func ( *note, int64) bool {
:= getg()
if != .m.g0 && .m.preemptoff != "" {
throw("notetsleep not on g0")
}
return notetsleep_internal(, )
}
func ( *note, int64) bool {
:= getg()
if == .m.g0 {
throw("notetsleepg on g0")
}
entersyscallblock()
:= notetsleep_internal(, )
exitsyscall()
return
}
func (int64) (*g, bool) {
return nil, false
}
func () {}