Source File
time.go
Belonging Package
runtime
package runtime
import (
)
const maxWhen = 1<<63 - 1
const verifyTimers = false
func ( *timer) {
if raceenabled {
racerelease(unsafe.Pointer())
}
addtimer()
}
func ( *timer, int64) bool {
if raceenabled {
racerelease(unsafe.Pointer())
}
return resettimer(, )
}
if .when <= 0 {
throw("timer when must be positive")
}
if .period < 0 {
throw("timer period must be non-negative")
}
if .status != timerNoStatus {
throw("addtimer called with initialized timer")
}
.status = timerWaiting
:= .when
:= acquirem()
:= getg().m.p.ptr()
lock(&.timersLock)
cleantimers()
doaddtimer(, )
unlock(&.timersLock)
wakeNetPoller()
releasem()
}
:= acquirem()
:= .pp.ptr()
if !atomic.Cas(&.status, timerModifying, timerDeleted) {
badTimer()
}
releasem()
:= acquirem()
:= .pp.ptr()
atomic.Xadd(&.adjustTimers, -1)
if !atomic.Cas(&.status, timerModifying, timerDeleted) {
badTimer()
}
releasem()
return false
osyield()
return false
siftupTimer(.timers, )
siftdownTimer(.timers, )
}
if == 0 {
updateTimer0When()
}
atomic.Xadd(&.numTimers, -1)
}
= acquirem()
osyield()
osyield()
default:
badTimer()
}
}
.period =
.f =
.arg =
.seq =
if {
.when =
:= getg().m.p.ptr()
lock(&.timersLock)
doaddtimer(, )
unlock(&.timersLock)
if !atomic.Cas(&.status, timerModifying, timerWaiting) {
badTimer()
}
releasem()
wakeNetPoller()
.nextwhen =
:= uint32(timerModifiedLater)
if < .when {
= timerModifiedEarlier
}
:= .pp.ptr()
:= int32(0)
if == timerModifiedEarlier {
--
}
if == timerModifiedEarlier {
++
updateTimerModifiedEarliest(, )
}
if != 0 {
atomic.Xadd(&.adjustTimers, )
}
if == timerModifiedEarlier {
wakeNetPoller()
}
}
return
}
if .preemptStop {
return
}
:= .timers[0]
if .pp.ptr() != {
throw("cleantimers: bad p")
}
switch := atomic.Load(&.status); {
case timerDeleted:
if !atomic.Cas(&.status, , timerRemoving) {
continue
}
dodeltimer0()
if !atomic.Cas(&.status, timerRemoving, timerRemoved) {
badTimer()
}
atomic.Xadd(&.deletedTimers, -1)
case timerModifiedEarlier, timerModifiedLater:
if !atomic.Cas(&.status, , timerMoving) {
continue
dodeltimer0()
doaddtimer(, )
if == timerModifiedEarlier {
atomic.Xadd(&.adjustTimers, -1)
}
if !atomic.Cas(&.status, timerMoving, timerWaiting) {
badTimer()
}
return
}
}
}
func ( *p, []*timer) {
for , := range {
:
for {
switch := atomic.Load(&.status); {
case timerWaiting:
if !atomic.Cas(&.status, , timerMoving) {
continue
}
.pp = 0
doaddtimer(, )
if !atomic.Cas(&.status, timerMoving, timerWaiting) {
badTimer()
}
break
case timerModifiedEarlier, timerModifiedLater:
if !atomic.Cas(&.status, , timerMoving) {
continue
}
.when = .nextwhen
.pp = 0
doaddtimer(, )
if !atomic.Cas(&.status, timerMoving, timerWaiting) {
badTimer()
}
break
case timerDeleted:
if !atomic.Cas(&.status, , timerRemoved) {
continue
}
break
osyield()
badTimer()
func ( *p, int64) {
if atomic.Load(&.adjustTimers) == 0 {
if verifyTimers {
verifyTimerHeap()
atomic.Store64(&.timerModifiedEarliest, 0)
return
}
if := atomic.Load64(&.timerModifiedEarliest); != 0 {
if int64() > {
if verifyTimers {
verifyTimerHeap()
}
return
}
atomic.Store64(&.timerModifiedEarliest, 0)
}
var []*timer
:
for := 0; < len(.timers); ++ {
:= .timers[]
if .pp.ptr() != {
throw("adjusttimers: bad p")
}
switch := atomic.Load(&.status); {
case timerDeleted:
if atomic.Cas(&.status, , timerRemoving) {
dodeltimer(, )
if !atomic.Cas(&.status, timerRemoving, timerRemoved) {
badTimer()
}
--
}
case timerModifiedEarlier, timerModifiedLater:
dodeltimer(, )
= append(, )
if == timerModifiedEarlier {
if := atomic.Xadd(&.adjustTimers, -1); int32() <= 0 {
break
}
--
}
case timerNoStatus, timerRunning, timerRemoving, timerRemoved, timerMoving:
badTimer()
osyield()
--
default:
badTimer()
}
}
if len() > 0 {
addAdjustedTimers(, )
}
if verifyTimers {
verifyTimerHeap()
}
}
func ( *p, []*timer) {
for , := range {
doaddtimer(, )
if !atomic.Cas(&.status, timerMoving, timerWaiting) {
badTimer()
}
}
}
func ( *p) int64 {
:= int64(atomic.Load64(&.timer0When))
:= int64(atomic.Load64(&.timerModifiedEarliest))
if == 0 || ( != 0 && < ) {
=
}
return
}
return .when
}
if !atomic.Cas(&.status, , timerRunning) {
continue
runOneTimer(, , )
return 0
case timerDeleted:
if !atomic.Cas(&.status, , timerRemoving) {
continue
}
dodeltimer0()
if !atomic.Cas(&.status, timerRemoving, timerRemoved) {
badTimer()
}
atomic.Xadd(&.deletedTimers, -1)
if len(.timers) == 0 {
return -1
}
case timerModifiedEarlier, timerModifiedLater:
if !atomic.Cas(&.status, , timerMoving) {
continue
}
.when = .nextwhen
dodeltimer0()
doaddtimer(, )
if == timerModifiedEarlier {
atomic.Xadd(&.adjustTimers, -1)
}
if !atomic.Cas(&.status, timerMoving, timerWaiting) {
badTimer()
}
osyield()
badTimer()
func ( *p, *timer, int64) {
if raceenabled {
:= getg().m.p.ptr()
if .timerRaceCtx == 0 {
.timerRaceCtx = racegostart(funcPC(runtimer) + sys.PCQuantum)
}
raceacquirectx(.timerRaceCtx, unsafe.Pointer())
}
:= .f
:= .arg
:= .seq
:= .when -
.when += .period * (1 + -/.period)
if .when < 0 { // check for overflow.
.when = maxWhen
}
siftdownTimer(.timers, 0)
if !atomic.Cas(&.status, timerRunning, timerWaiting) {
badTimer()
}
updateTimer0When()
dodeltimer0()
if !atomic.Cas(&.status, timerRunning, timerNoStatus) {
badTimer()
}
}
:= getg()
if .racectx != 0 {
throw("runOneTimer: unexpected racectx")
}
.racectx = .m.p.ptr().timerRaceCtx
}
unlock(&.timersLock)
(, )
lock(&.timersLock)
if raceenabled {
:= getg()
.racectx = 0
}
}
atomic.Store64(&.timerModifiedEarliest, 0)
:= int32(0)
:= int32(0)
:= 0
:= false
:= .timers
:
for , := range {
for {
switch := atomic.Load(&.status); {
case timerWaiting:
if {
[] =
siftupTimer(, )
}
++
continue
case timerModifiedEarlier, timerModifiedLater:
if atomic.Cas(&.status, , timerMoving) {
.when = .nextwhen
[] =
siftupTimer(, )
++
= true
if !atomic.Cas(&.status, timerMoving, timerWaiting) {
badTimer()
}
if == timerModifiedEarlier {
++
}
continue
}
case timerDeleted:
if atomic.Cas(&.status, , timerRemoving) {
.pp = 0
++
if !atomic.Cas(&.status, timerRemoving, timerRemoved) {
badTimer()
}
= true
continue
}
osyield()
badTimer()
for := ; < len(); ++ {
[] = nil
}
atomic.Xadd(&.deletedTimers, -)
atomic.Xadd(&.numTimers, -)
atomic.Xadd(&.adjustTimers, -)
= [:]
.timers =
updateTimer0When()
if verifyTimers {
verifyTimerHeap()
}
}
continue
}
:= ( - 1) / 4
if .when < .timers[].when {
print("bad timer heap at ", , ": ", , ": ", .timers[].when, ", ", , ": ", .when, "\n")
throw("bad timer heap")
}
}
if := int(atomic.Load(&.numTimers)); len(.timers) != {
println("timer heap len", len(.timers), "!= numTimers", )
throw("bad timer heap len")
}
}
func ( *p, int64) {
for {
:= atomic.Load64(&.timerModifiedEarliest)
if != 0 && int64() < {
return
}
if atomic.Cas64(&.timerModifiedEarliest, , uint64()) {
return
}
}
}
continue
}
:= int64(atomic.Load64(&.timer0When))
if != 0 && < {
=
=
}
= int64(atomic.Load64(&.timerModifiedEarliest))
if != 0 && < {
=
=
}
}
unlock(&allpLock)
return ,
}
func ( []*timer, int) {
if >= len() {
badTimer()
}
:= [].when
if <= 0 {
badTimer()
}
:= []
for > 0 {
:= ( - 1) / 4 // parent
if >= [].when {
break
}
[] = []
=
}
if != [] {
[] =
}
}
func ( []*timer, int) {
:= len()
if >= {
badTimer()
}
:= [].when
if <= 0 {
badTimer()
}
:= []
for {
:= *4 + 1 // left child
:= + 2 // mid child
if >= {
break
}
:= [].when
if +1 < && [+1].when < {
= [+1].when
++
}
if < {
:= [].when
if +1 < && [+1].when < {
= [+1].when
++
}
if < {
=
=
}
}
if >= {
break
}
[] = []
=
}
if != [] {
[] =
}
}
func () {
throw("timer data corruption")
![]() |
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. |