time.go 23.2 KB
Newer Older
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
1 2 3 4 5 6 7 8
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Time-related runtime and pieces of package time.

package runtime

9
import (
10
	"internal/cpu"
11
	"runtime/internal/atomic"
12 13
	"unsafe"
)
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
14

15 16 17
// Temporary scaffolding while the new timer code is added.
const oldTimers = true

Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
18
// Package time knows the layout of this structure.
19
// If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
20
type timer struct {
21 22 23 24 25 26 27
	tb *timersBucket // the bucket the timer lives in (oldTimers)
	i  int           // heap index (oldTimers)

	// If this timer is on a heap, which P's heap it is on.
	// puintptr rather than *p to match uintptr in the versions
	// of this struct defined in other packages. (!oldTimers)
	pp puintptr
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
28 29

	// Timer wakes up at when, and then at when+period, ... (period > 0 only)
Brad Fitzpatrick's avatar
Brad Fitzpatrick committed
30
	// each time calling f(arg, now) in the timer goroutine, so f must be
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
31 32 33
	// a well-behaved function and not block.
	when   int64
	period int64
34
	f      func(interface{}, uintptr)
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
35
	arg    interface{}
36
	seq    uintptr
37 38 39 40 41 42

	// What to set the when field to in timerModifiedXX status. (!oldTimers)
	nextwhen int64

	// The status field holds one of the values below. (!oldTimers)
	status uint32
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
43 44
}

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
// timersLen is the length of timers array.
//
// Ideally, this would be set to GOMAXPROCS, but that would require
// dynamic reallocation
//
// The current value is a compromise between memory usage and performance
// that should cover the majority of GOMAXPROCS values used in the wild.
const timersLen = 64

// timers contains "per-P" timer heaps.
//
// Timers are queued into timersBucket associated with the current P,
// so each P may work with its own timers independently of other P instances.
//
// Each timersBucket may be associated with multiple P
// if GOMAXPROCS > timersLen.
var timers [timersLen]struct {
	timersBucket

	// The padding should eliminate false sharing
	// between timersBucket values.
66
	pad [cpu.CacheLinePadSize - unsafe.Sizeof(timersBucket{})%cpu.CacheLinePadSize]byte
67 68 69 70 71 72 73 74
}

func (t *timer) assignBucket() *timersBucket {
	id := uint8(getg().m.p.ptr().id) % timersLen
	t.tb = &timers[id].timersBucket
	return t.tb
}

75
//go:notinheap
76
type timersBucket struct {
Russ Cox's avatar
Russ Cox committed
77
	lock         mutex
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
78 79 80 81
	gp           *g
	created      bool
	sleeping     bool
	rescheduling bool
82
	sleepUntil   int64
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
83 84 85 86
	waitnote     note
	t            []*timer
}

87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
// Code outside this file has to be careful in using a timer value.
//
// The pp, status, and nextwhen fields may only be used by code in this file.
//
// Code that creates a new timer value can set the when, period, f,
// arg, and seq fields.
// A new timer value may be passed to addtimer (called by time.startTimer).
// After doing that no fields may be touched.
//
// An active timer (one that has been passed to addtimer) may be
// passed to deltimer (time.stopTimer), after which it is no longer an
// active timer. It is an inactive timer.
// In an inactive timer the period, f, arg, and seq fields may be modified,
// but not the when field.
// It's OK to just drop an inactive timer and let the GC collect it.
// It's not OK to pass an inactive timer to addtimer.
// Only newly allocated timer values may be passed to addtimer.
//
// An active timer may be passed to modtimer. No fields may be touched.
// It remains an active timer.
//
// An inactive timer may be passed to resettimer to turn into an
// active timer with an updated when field.
// It's OK to pass a newly allocated timer value to resettimer.
//
// Timer operations are addtimer, deltimer, modtimer, resettimer,
// cleantimers, adjusttimers, and runtimer.
//
// We don't permit calling addtimer/deltimer/modtimer/resettimer simultaneously,
// but adjusttimers and runtimer can be called at the same time as any of those.
//
// Active timers live in heaps attached to P, in the timers field.
// Inactive timers live there too temporarily, until they are removed.
120 121 122 123
//
// addtimer:
//   timerNoStatus   -> timerWaiting
//   anything else   -> panic: invalid value
124 125 126 127 128 129 130 131 132 133
// deltimer:
//   timerWaiting    -> timerDeleted
//   timerModifiedXX -> timerDeleted
//   timerNoStatus   -> do nothing
//   timerDeleted    -> do nothing
//   timerRemoving   -> do nothing
//   timerRemoved    -> do nothing
//   timerRunning    -> wait until status changes
//   timerMoving     -> wait until status changes
//   timerModifying  -> panic: concurrent deltimer/modtimer calls
134 135 136 137 138 139 140 141 142 143
// modtimer:
//   timerWaiting    -> timerModifying -> timerModifiedXX
//   timerModifiedXX -> timerModifying -> timerModifiedYY
//   timerNoStatus   -> timerWaiting
//   timerRemoved    -> timerWaiting
//   timerRunning    -> wait until status changes
//   timerMoving     -> wait until status changes
//   timerRemoving   -> wait until status changes
//   timerDeleted    -> panic: concurrent modtimer/deltimer calls
//   timerModifying  -> panic: concurrent modtimer calls
144 145 146 147 148 149 150 151 152 153
// resettimer:
//   timerNoStatus   -> timerWaiting
//   timerRemoved    -> timerWaiting
//   timerDeleted    -> timerModifying -> timerModifiedXX
//   timerRemoving   -> wait until status changes
//   timerRunning    -> wait until status changes
//   timerWaiting    -> panic: resettimer called on active timer
//   timerMoving     -> panic: resettimer called on active timer
//   timerModifiedXX -> panic: resettimer called on active timer
//   timerModifying  -> panic: resettimer called on active timer
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198

// Values for the timer status field.
const (
	// Timer has no status set yet.
	timerNoStatus = iota

	// Waiting for timer to fire.
	// The timer is in some P's heap.
	timerWaiting

	// Running the timer function.
	// A timer will only have this status briefly.
	timerRunning

	// The timer is deleted and should be removed.
	// It should not be run, but it is still in some P's heap.
	timerDeleted

	// The timer is being removed.
	// The timer will only have this status briefly.
	timerRemoving

	// The timer has been stopped.
	// It is not in any P's heap.
	timerRemoved

	// The timer is being modified.
	// The timer will only have this status briefly.
	timerModifying

	// The timer has been modified to an earlier time.
	// The new when value is in the nextwhen field.
	// The timer is in some P's heap, possibly in the wrong place.
	timerModifiedEarlier

	// The timer has been modified to the same or a later time.
	// The new when value is in the nextwhen field.
	// The timer is in some P's heap, possibly in the wrong place.
	timerModifiedLater

	// The timer has been modified and is being moved.
	// The timer will only have this status briefly.
	timerMoving
)

199 200 201
// maxWhen is the maximum value for timer's when field.
const maxWhen = 1<<63 - 1

Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
202 203 204 205 206
// Package time APIs.
// Godoc uses the comments in package time, not these.

// time.now is implemented in assembly.

Russ Cox's avatar
Russ Cox committed
207 208
// timeSleep puts the current goroutine to sleep for at least ns nanoseconds.
//go:linkname timeSleep time.Sleep
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
209
func timeSleep(ns int64) {
210 211 212 213 214 215 216 217
	if oldTimers {
		timeSleepOld(ns)
		return
	}
	throw("new timeSleep not yet implemented")
}

func timeSleepOld(ns int64) {
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
218 219 220 221
	if ns <= 0 {
		return
	}

222 223
	gp := getg()
	t := gp.timer
224 225
	if t == nil {
		t = new(timer)
226
		gp.timer = t
227 228
	}
	*t = timer{}
229
	t.when = nanotime() + ns
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
230
	t.f = goroutineReady
231 232 233
	t.arg = gp
	tb := t.assignBucket()
	lock(&tb.lock)
234 235 236 237
	if !tb.addtimerLocked(t) {
		unlock(&tb.lock)
		badTimer()
	}
238
	goparkunlock(&tb.lock, waitReasonSleep, traceEvGoSleep, 3)
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
239 240 241
}

// startTimer adds t to the timer heap.
Russ Cox's avatar
Russ Cox committed
242
//go:linkname startTimer time.startTimer
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
243 244 245 246 247 248 249
func startTimer(t *timer) {
	if raceenabled {
		racerelease(unsafe.Pointer(t))
	}
	addtimer(t)
}

250 251
// stopTimer stops a timer.
// It reports whether t was stopped before being run.
Russ Cox's avatar
Russ Cox committed
252
//go:linkname stopTimer time.stopTimer
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
253 254 255 256
func stopTimer(t *timer) bool {
	return deltimer(t)
}

257 258 259 260 261 262 263 264 265
// resetTimer resets an inactive timer, adding it to the heap.
//go:linkname resetTimer time.resetTimer
func resetTimer(t *timer, when int64) {
	if raceenabled {
		racerelease(unsafe.Pointer(t))
	}
	resettimer(t, when)
}

Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
266 267 268
// Go runtime.

// Ready the goroutine arg.
269
func goroutineReady(arg interface{}, seq uintptr) {
270
	goready(arg.(*g), 0)
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
271 272
}

273 274 275 276
// addtimer adds a timer to the current P.
// This should only be called with a newly created timer.
// That avoids the risk of changing the when field of a timer in some P's heap,
// which could cause the heap to become unsorted.
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
277
func addtimer(t *timer) {
278 279 280 281
	if oldTimers {
		addtimerOld(t)
		return
	}
282 283 284 285 286 287 288 289 290 291 292

	// when must never be negative; otherwise runtimer will overflow
	// during its delta calculation and never expire other runtime timers.
	if t.when < 0 {
		t.when = maxWhen
	}
	if t.status != timerNoStatus {
		badTimer()
	}
	t.status = timerWaiting

293 294 295 296 297
	addInitializedTimer(t)
}

// addInitializedTimer adds an initialized timer to the current P.
func addInitializedTimer(t *timer) {
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
	when := t.when

	pp := getg().m.p.ptr()
	lock(&pp.timersLock)
	ok := cleantimers(pp) && doaddtimer(pp, t)
	unlock(&pp.timersLock)
	if !ok {
		badTimer()
	}

	wakeNetPoller(when)
}

// doaddtimer adds t to the current P's heap.
// It reports whether it saw no problems due to races.
// The caller must have locked the timers for pp.
func doaddtimer(pp *p, t *timer) bool {
	// Timers rely on the network poller, so make sure the poller
	// has started.
	if netpollInited == 0 {
		netpollGenericInit()
	}

	if t.pp != 0 {
		throw("doaddtimer: P already set in timer")
	}
	t.pp.set(pp)
	i := len(pp.timers)
	pp.timers = append(pp.timers, t)
	return siftupTimer(pp.timers, i)
328 329 330
}

func addtimerOld(t *timer) {
331 332
	tb := t.assignBucket()
	lock(&tb.lock)
333
	ok := tb.addtimerLocked(t)
334
	unlock(&tb.lock)
335 336 337
	if !ok {
		badTimer()
	}
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
338 339
}

340 341
// Add a timer to the heap and start or kick timerproc if the new timer is
// earlier than any of the others.
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
342
// Timers are locked.
343 344 345
// Returns whether all is well: false if the data structure is corrupt
// due to user-level races.
func (tb *timersBucket) addtimerLocked(t *timer) bool {
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
346
	// when must never be negative; otherwise timerproc will overflow
347
	// during its delta calculation and never expire other runtime timers.
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
348 349 350
	if t.when < 0 {
		t.when = 1<<63 - 1
	}
351 352
	t.i = len(tb.t)
	tb.t = append(tb.t, t)
353 354 355
	if !siftupTimer(tb.t, t.i) {
		return false
	}
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
356 357
	if t.i == 0 {
		// siftup moved to top: new earliest deadline.
358
		if tb.sleeping && tb.sleepUntil > t.when {
359 360
			tb.sleeping = false
			notewakeup(&tb.waitnote)
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
361
		}
362 363 364
		if tb.rescheduling {
			tb.rescheduling = false
			goready(tb.gp, 0)
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
365
		}
366 367 368 369
		if !tb.created {
			tb.created = true
			go timerproc(tb)
		}
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
370
	}
371
	return true
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
372 373
}

374 375 376 377
// deltimer deletes the timer t. It may be on some other P, so we can't
// actually remove it from the timers heap. We can only mark it as deleted.
// It will be removed in due course by the P whose heap it is on.
// Reports whether the timer was removed before it was run.
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
378
func deltimer(t *timer) bool {
379 380 381
	if oldTimers {
		return deltimerOld(t)
	}
382 383 384 385 386 387 388 389 390

	for {
		switch s := atomic.Load(&t.status); s {
		case timerWaiting, timerModifiedLater:
			if atomic.Cas(&t.status, s, timerDeleted) {
				// Timer was not yet run.
				return true
			}
		case timerModifiedEarlier:
391
			tpp := t.pp.ptr()
392
			if atomic.Cas(&t.status, s, timerModifying) {
393
				atomic.Xadd(&tpp.adjustTimers, -1)
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
				if !atomic.Cas(&t.status, timerModifying, timerDeleted) {
					badTimer()
				}
				// Timer was not yet run.
				return true
			}
		case timerDeleted, timerRemoving, timerRemoved:
			// Timer was already run.
			return false
		case timerRunning, timerMoving:
			// The timer is being run or moved, by a different P.
			// Wait for it to complete.
			osyield()
		case timerNoStatus:
			// Removing timer that was never added or
			// has already been run. Also see issue 21874.
			return false
		case timerModifying:
			// Simultaneous calls to deltimer and modtimer.
			badTimer()
		default:
			badTimer()
		}
	}
418 419
}

420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
// dodeltimer removes timer i from the current P's heap.
// We are locked on the P when this is called.
// It reports whether it saw no problems due to races.
// The caller must have locked the timers for pp.
func dodeltimer(pp *p, i int) bool {
	if t := pp.timers[i]; t.pp.ptr() != pp {
		throw("dodeltimer: wrong P")
	} else {
		t.pp = 0
	}
	last := len(pp.timers) - 1
	if i != last {
		pp.timers[i] = pp.timers[last]
	}
	pp.timers[last] = nil
	pp.timers = pp.timers[:last]
	ok := true
	if i != last {
		// Moving to i may have moved the last timer to a new parent,
		// so sift up to preserve the heap guarantee.
		if !siftupTimer(pp.timers, i) {
			ok = false
		}
		if !siftdownTimer(pp.timers, i) {
			ok = false
		}
	}
	return ok
}

// dodeltimer0 removes timer 0 from the current P's heap.
// We are locked on the P when this is called.
// It reports whether it saw no problems due to races.
// The caller must have locked the timers for pp.
func dodeltimer0(pp *p) bool {
	if t := pp.timers[0]; t.pp.ptr() != pp {
		throw("dodeltimer0: wrong P")
	} else {
		t.pp = 0
	}
	last := len(pp.timers) - 1
	if last > 0 {
		pp.timers[0] = pp.timers[last]
	}
	pp.timers[last] = nil
	pp.timers = pp.timers[:last]
	ok := true
	if last > 0 {
		ok = siftdownTimer(pp.timers, 0)
	}
	return ok
}

473
func deltimerOld(t *timer) bool {
474 475 476 477 478 479 480 481 482
	if t.tb == nil {
		// t.tb can be nil if the user created a timer
		// directly, without invoking startTimer e.g
		//    time.Ticker{C: c}
		// In this case, return early without any deletion.
		// See Issue 21874.
		return false
	}

483
	tb := t.tb
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
484

485
	lock(&tb.lock)
486 487 488 489 490 491 492 493 494
	removed, ok := tb.deltimerLocked(t)
	unlock(&tb.lock)
	if !ok {
		badTimer()
	}
	return removed
}

func (tb *timersBucket) deltimerLocked(t *timer) (removed, ok bool) {
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
495 496 497 498
	// t may not be registered anymore and may have
	// a bogus i (typically 0, if generated by Go).
	// Verify it before proceeding.
	i := t.i
499 500
	last := len(tb.t) - 1
	if i < 0 || i > last || tb.t[i] != t {
501
		return false, true
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
502 503
	}
	if i != last {
504 505
		tb.t[i] = tb.t[last]
		tb.t[i].i = i
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
506
	}
507 508
	tb.t[last] = nil
	tb.t = tb.t[:last]
509
	ok = true
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
510
	if i != last {
511 512 513 514 515 516
		if !siftupTimer(tb.t, i) {
			ok = false
		}
		if !siftdownTimer(tb.t, i) {
			ok = false
		}
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
517
	}
518 519 520
	return true, ok
}

521 522
// modtimer modifies an existing timer.
// This is called by the netpoll code.
523
func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) {
524 525 526 527
	if oldTimers {
		modtimerOld(t, when, period, f, arg, seq)
		return
	}
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608

	if when < 0 {
		when = maxWhen
	}

	status := uint32(timerNoStatus)
	wasRemoved := false
loop:
	for {
		switch status = atomic.Load(&t.status); status {
		case timerWaiting, timerModifiedEarlier, timerModifiedLater:
			if atomic.Cas(&t.status, status, timerModifying) {
				break loop
			}
		case timerNoStatus, timerRemoved:
			// Timer was already run and t is no longer in a heap.
			// Act like addtimer.
			wasRemoved = true
			atomic.Store(&t.status, timerWaiting)
			break loop
		case timerRunning, timerRemoving, timerMoving:
			// The timer is being run or moved, by a different P.
			// Wait for it to complete.
			osyield()
		case timerDeleted:
			// Simultaneous calls to modtimer and deltimer.
			badTimer()
		case timerModifying:
			// Multiple simultaneous calls to modtimer.
			badTimer()
		default:
			badTimer()
		}
	}

	t.period = period
	t.f = f
	t.arg = arg
	t.seq = seq

	if wasRemoved {
		t.when = when
		addInitializedTimer(t)
	} else {
		// The timer is in some other P's heap, so we can't change
		// the when field. If we did, the other P's heap would
		// be out of order. So we put the new when value in the
		// nextwhen field, and let the other P set the when field
		// when it is prepared to resort the heap.
		t.nextwhen = when

		newStatus := uint32(timerModifiedLater)
		if when < t.when {
			newStatus = timerModifiedEarlier
		}

		// Update the adjustTimers field.  Subtract one if we
		// are removing a timerModifiedEarlier, add one if we
		// are adding a timerModifiedEarlier.
		tpp := t.pp.ptr()
		adjust := int32(0)
		if status == timerModifiedEarlier {
			adjust--
		}
		if newStatus == timerModifiedEarlier {
			adjust++
		}
		if adjust != 0 {
			atomic.Xadd(&tpp.adjustTimers, adjust)
		}

		// Set the new status of the timer.
		if !atomic.Cas(&t.status, timerModifying, newStatus) {
			badTimer()
		}

		// If the new status is earlier, wake up the poller.
		if newStatus == timerModifiedEarlier {
			wakeNetPoller(when)
		}
	}
609 610 611
}

func modtimerOld(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) {
612 613 614 615 616 617 618 619 620 621 622 623
	tb := t.tb

	lock(&tb.lock)
	_, ok := tb.deltimerLocked(t)
	if ok {
		t.when = when
		t.period = period
		t.f = f
		t.arg = arg
		t.seq = seq
		ok = tb.addtimerLocked(t)
	}
624
	unlock(&tb.lock)
625 626 627
	if !ok {
		badTimer()
	}
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
628 629
}

630 631 632 633 634
// resettimer resets an existing inactive timer to turn it into an active timer,
// with a new time for when the timer should fire.
// This should be called instead of addtimer if the timer value has been,
// or may have been, used previously.
func resettimer(t *timer, when int64) {
635 636 637 638
	if oldTimers {
		resettimerOld(t, when)
		return
	}
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682

	if when < 0 {
		when = maxWhen
	}

	for {
		switch s := atomic.Load(&t.status); s {
		case timerNoStatus, timerRemoved:
			atomic.Store(&t.status, timerWaiting)
			t.when = when
			addInitializedTimer(t)
			return
		case timerDeleted:
			if atomic.Cas(&t.status, s, timerModifying) {
				t.nextwhen = when
				newStatus := uint32(timerModifiedLater)
				if when < t.when {
					newStatus = timerModifiedEarlier
					atomic.Xadd(&t.pp.ptr().adjustTimers, 1)
				}
				if !atomic.Cas(&t.status, timerModifying, newStatus) {
					badTimer()
				}
				if newStatus == timerModifiedEarlier {
					wakeNetPoller(when)
				}
				return
			}
		case timerRemoving:
			// Wait for the removal to complete.
			osyield()
		case timerRunning:
			// Even though the timer should not be active,
			// we can see timerRunning if the timer function
			// permits some other goroutine to call resettimer.
			// Wait until the run is complete.
			osyield()
		case timerWaiting, timerModifying, timerModifiedEarlier, timerModifiedLater, timerMoving:
			// Called resettimer on active timer.
			badTimer()
		default:
			badTimer()
		}
	}
683 684 685
}

func resettimerOld(t *timer, when int64) {
686 687 688 689
	t.when = when
	addtimer(t)
}

Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
690
// Timerproc runs the time-driven events.
691
// It sleeps until the next event in the tb heap.
692
// If addtimer inserts a new earlier event, it wakes timerproc early.
693 694
func timerproc(tb *timersBucket) {
	tb.gp = getg()
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
695
	for {
696 697
		lock(&tb.lock)
		tb.sleeping = false
698
		now := nanotime()
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
699 700
		delta := int64(-1)
		for {
701
			if len(tb.t) == 0 {
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
702 703 704
				delta = -1
				break
			}
705
			t := tb.t[0]
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
706 707 708 709
			delta = t.when - now
			if delta > 0 {
				break
			}
710
			ok := true
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
711 712 713
			if t.period > 0 {
				// leave in heap but adjust next time to fire
				t.when += t.period * (1 + -delta/t.period)
714 715 716
				if !siftdownTimer(tb.t, 0) {
					ok = false
				}
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
717 718
			} else {
				// remove from heap
719
				last := len(tb.t) - 1
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
720
				if last > 0 {
721 722
					tb.t[0] = tb.t[last]
					tb.t[0].i = 0
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
723
				}
724 725
				tb.t[last] = nil
				tb.t = tb.t[:last]
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
726
				if last > 0 {
727 728 729
					if !siftdownTimer(tb.t, 0) {
						ok = false
					}
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
730 731 732 733 734
				}
				t.i = -1 // mark as removed
			}
			f := t.f
			arg := t.arg
735
			seq := t.seq
736
			unlock(&tb.lock)
737 738 739
			if !ok {
				badTimer()
			}
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
740 741 742
			if raceenabled {
				raceacquire(unsafe.Pointer(t))
			}
743
			f(arg, seq)
744
			lock(&tb.lock)
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
745
		}
746
		if delta < 0 || faketime > 0 {
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
747
			// No timers left - put goroutine to sleep.
748
			tb.rescheduling = true
749
			goparkunlock(&tb.lock, waitReasonTimerGoroutineIdle, traceEvGoBlock, 1)
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
750 751
			continue
		}
752
		// At least one timer pending. Sleep until then.
753 754 755 756 757
		tb.sleeping = true
		tb.sleepUntil = now + delta
		noteclear(&tb.waitnote)
		unlock(&tb.lock)
		notetsleepg(&tb.waitnote, delta)
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
758 759 760
	}
}

761 762 763 764 765 766 767 768 769 770
// cleantimers cleans up the head of the timer queue. This speeds up
// programs that create and delete timers; leaving them in the heap
// slows down addtimer. Reports whether no timer problems were found.
// The caller must have locked the timers for pp.
func cleantimers(pp *p) bool {
	// TODO: write this.
	throw("cleantimers")
	return true
}

771 772 773 774 775 776 777 778
// moveTimers moves a slice of timers to pp. The slice has been taken
// from a different P.
// This is currently called when the world is stopped, but it could
// work as long as the timers for pp are locked.
func moveTimers(pp *p, timers []*timer) {
	throw("movetimers: not yet implemented")
}

779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799
// adjusttimers looks through the timers in the current P's heap for
// any timers that have been modified to run earlier, and puts them in
// the correct place in the heap.
// The caller must have locked the timers for pp.
func adjusttimers(pp *p) {
	if len(pp.timers) == 0 {
		return
	}
	throw("adjusttimers: not yet implemented")
}

// runtimer examines the first timer in timers. If it is ready based on now,
// it runs the timer and removes or updates it.
// Returns 0 if it ran a timer, -1 if there are no more timers, or the time
// when the first timer should run.
// The caller must have locked the timers for pp.
func runtimer(pp *p, now int64) int64 {
	throw("runtimer: not yet implemented")
	return -1
}

800 801 802 803 804
func timejump() *g {
	if faketime == 0 {
		return nil
	}

805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835
	for i := range timers {
		lock(&timers[i].lock)
	}
	gp := timejumpLocked()
	for i := range timers {
		unlock(&timers[i].lock)
	}

	return gp
}

func timejumpLocked() *g {
	// Determine a timer bucket with minimum when.
	var minT *timer
	for i := range timers {
		tb := &timers[i]
		if !tb.created || len(tb.t) == 0 {
			continue
		}
		t := tb.t[0]
		if minT == nil || t.when < minT.when {
			minT = t
		}
	}
	if minT == nil || minT.when <= faketime {
		return nil
	}

	faketime = minT.when
	tb := minT.tb
	if !tb.rescheduling {
836 837
		return nil
	}
838 839 840 841 842 843
	tb.rescheduling = false
	return tb.gp
}

func timeSleepUntil() int64 {
	next := int64(1<<63 - 1)
844

845 846 847 848 849 850 851 852 853 854 855
	// Determine minimum sleepUntil across all the timer buckets.
	//
	// The function can not return a precise answer,
	// as another timer may pop in as soon as timers have been unlocked.
	// So lock the timers one by one instead of all at once.
	for i := range timers {
		tb := &timers[i]

		lock(&tb.lock)
		if tb.sleeping && tb.sleepUntil < next {
			next = tb.sleepUntil
856
		}
857
		unlock(&tb.lock)
858
	}
859 860

	return next
861 862
}

Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
863
// Heap maintenance algorithms.
864 865 866 867 868 869 870 871 872 873 874 875 876 877
// These algorithms check for slice index errors manually.
// Slice index error can happen if the program is using racy
// access to timers. We don't want to panic here, because
// it will cause the program to crash with a mysterious
// "panic holding locks" message. Instead, we panic while not
// holding a lock.
// The races can occur despite the bucket locks because assignBucket
// itself is called without locks, so racy calls can cause a timer to
// change buckets while executing these functions.

func siftupTimer(t []*timer, i int) bool {
	if i >= len(t) {
		return false
	}
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
878 879 880 881 882 883 884 885 886 887 888
	when := t[i].when
	tmp := t[i]
	for i > 0 {
		p := (i - 1) / 4 // parent
		if when >= t[p].when {
			break
		}
		t[i] = t[p]
		t[i].i = i
		i = p
	}
889 890 891 892
	if tmp != t[i] {
		t[i] = tmp
		t[i].i = i
	}
893
	return true
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
894 895
}

896
func siftdownTimer(t []*timer, i int) bool {
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
897
	n := len(t)
898 899 900
	if i >= n {
		return false
	}
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931
	when := t[i].when
	tmp := t[i]
	for {
		c := i*4 + 1 // left child
		c3 := c + 2  // mid child
		if c >= n {
			break
		}
		w := t[c].when
		if c+1 < n && t[c+1].when < w {
			w = t[c+1].when
			c++
		}
		if c3 < n {
			w3 := t[c3].when
			if c3+1 < n && t[c3+1].when < w3 {
				w3 = t[c3+1].when
				c3++
			}
			if w3 < w {
				w = w3
				c = c3
			}
		}
		if w >= when {
			break
		}
		t[i] = t[c]
		t[i].i = i
		i = c
	}
932 933 934 935
	if tmp != t[i] {
		t[i] = tmp
		t[i].i = i
	}
936 937 938 939 940 941 942 943 944
	return true
}

// badTimer is called if the timer data structures have been corrupted,
// presumably due to racy use by the program. We panic here rather than
// panicing due to invalid slice access while holding locks.
// See issue #25686.
func badTimer() {
	panic(errorString("racy use of timers"))
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
945
}