func timerproc(tb *timersBucket) {
	setSystemGoroutine()

	tb.gp = getg()
	for {
		lock(&tb.lock)
		tb.sleeping = false
		now := nanotime()
		delta := int64(-1)
		for {
			if len(tb.t) == 0 {
				delta = -1
				break
			}
			t := tb.t[0]
			delta = t.when - now
			if delta > 0 {
				break
			}
			ok := true
			if t.period > 0 {
				// leave in heap but adjust next time to fire
				t.when += t.period * (1 + -delta/t.period)
				if !siftdownTimer(tb.t, 0) {
					ok = false
				}
			} else {
				// remove from heap
				last := len(tb.t) - 1
				if last > 0 {
					tb.t[0] = tb.t[last]
					tb.t[0].i = 0
				}
				tb.t[last] = nil
				tb.t = tb.t[:last]
				if last > 0 {
					if !siftdownTimer(tb.t, 0) {
						ok = false
					}
				}
				t.i = -1 // mark as removed
			}
			f := t.f
			arg := t.arg
			seq := t.seq
			unlock(&tb.lock)
			if !ok {
				badTimer()
			}
			if raceenabled {
				raceacquire(unsafe.Pointer(t))
			}
			f(arg, seq)
			lock(&tb.lock)
		}
		if delta < 0 || faketime > 0 {
			// No timers left - put goroutine to sleep.
			tb.rescheduling = true
			goparkunlock(&tb.lock, waitReasonTimerGoroutineIdle, traceEvGoBlock, 1)
			continue
		}
		// At least one timer pending. Sleep until then.
		tb.sleeping = true
		tb.sleepUntil = now + delta
		noteclear(&tb.waitnote)
		unlock(&tb.lock)
		notetsleepg(&tb.waitnote, delta)
	}
}
// Timerproc runs the time-driven events.
// It sleeps until the next event in the tb heap.
// If addtimer inserts a new earlier event, it wakes timerproc early.
Timerproc runs the time-driven events.
It sleeps until the next event in the tb heap.
If addtimer inserts a new earlier event, it wakes timerproc early.
// Timerproc runs the time - driven events . // It sleeps until the next event in the tb heap . // If addtimer inserts a new earlier event it wakes timerproc early .
func timerproc(tb *timersBucket) {
	setSystemGoroutine()
	tb.gp = getg()
	for {
		lock(&tb.lock)
		tb.sleeping = false
		now := nanotime()
		delta := int64(-1)
		for {
			if len(tb.t) == 0 {
				delta = -1
				break
			}
			t := tb.t[0]
			delta = t.when - now
			if delta > 0 {
				break
			}
			ok := true
			if t.period > 0 {
				t.when += t.period * (1 + -delta/t.period)
				if !siftdownTimer(tb.t, 0) {
					ok = false
				}
			} else {
				last := len(tb.t) - 1
				if last > 0 {
					tb.t[0] = tb.t[last]
					tb.t[0].i = 0
				}
				tb.t[last] = nil
				tb.t = tb.t[:last]
				if last > 0 {
					if !siftdownTimer(tb.t, 0) {
						ok = false
					}
				}
				t.i = -1 
			}
			f := t.f
			arg := t.arg
			seq := t.seq
			unlock(&tb.lock)
			if !ok {
				badTimer()
			}
			if raceenabled {
				raceacquire(unsafe.Pointer(t))
			}
			f(arg, seq)
			lock(&tb.lock)
		}
		if delta < 0 || faketime > 0 {
			tb.rescheduling = true
			goparkunlock(&tb.lock, waitReasonTimerGoroutineIdle, traceEvGoBlock, 1)
			continue
		}
		tb.sleeping = true
		tb.sleepUntil = now + delta
		noteclear(&tb.waitnote)
		unlock(&tb.lock)
		notetsleepg(&tb.waitnote, delta)
	}
}
func timerproc ( tb * timersBucket ) { setSystemGoroutine ( ) tb . gp = getg ( ) for { lock ( & tb . lock ) tb . sleeping = false now := nanotime ( ) delta := int64 ( - 1 ) for { if len ( tb . t ) == 0 { delta = - 1 break } t := tb . t [ 0 ] delta = t . when - now if delta > 0 { break } ok := true if t . period > 0 { t . when += t . period * ( 1 + - delta / t . period ) if ! siftdownTimer ( tb . t , 0 ) { ok = false } } else { last := len ( tb . t ) - 1 if last > 0 { tb . t [ 0 ] = tb . t [ last ] tb . t [ 0 ] . i = 0 } tb . t [ last ] = nil tb . t = tb . t [ : last ] if last > 0 { if ! siftdownTimer ( tb . t , 0 ) { ok = false } } t . i = - 1 } f := t . f arg := t . arg seq := t . seq unlock ( & tb . lock ) if ! ok { badTimer ( ) } if raceenabled { raceacquire ( unsafe . Pointer ( t ) ) } f ( arg , seq ) lock ( & tb . lock ) } if delta < 0 || faketime > 0 { tb . rescheduling = true goparkunlock ( & tb . lock , waitReasonTimerGoroutineIdle , traceEvGoBlock , 1 ) continue } tb . sleeping = true tb . sleepUntil = now + delta noteclear ( & tb . waitnote ) unlock ( & tb . lock ) notetsleepg ( & tb . waitnote , delta ) } }
Timerproc runs the time-driven events.
Timerproc runs the time - driven events .
// leave in heap but adjust next time to fire // remove from heap // mark as removed // No timers left - put goroutine to sleep. // At least one timer pending. Sleep until then.