runtime: add timer support, use for package time

This looks like it is just moving some code from
time to runtime (and translating it to C), but the
runtime can do a better job managing the goroutines,
and it needs this functionality for its own maintenance
(for example, for the garbage collector to hand back
unused memory to the OS on a time delay).
Might as well have just one copy of the timer logic,
and runtime can't depend on time, so vice versa.

It also unifies Sleep, NewTicker, and NewTimer behind
one mechanism, so that there are no claims that one
is more efficient than another.  (For example, today
people recommend using time.After instead of time.Sleep
to avoid blocking an OS thread.)

Fixes #1644.
Fixes #1731.
Fixes #2190.

R=golang-dev, r, hectorchu, iant, iant, jsing, alex.brainman, dvyukov
CC=golang-dev
https://golang.org/cl/5334051
diff --git a/src/pkg/time/sleep.go b/src/pkg/time/sleep.go
index 314622d..967fca0 100644
--- a/src/pkg/time/sleep.go
+++ b/src/pkg/time/sleep.go
@@ -4,54 +4,60 @@
 
 package time
 
-import (
-	"container/heap"
-	"sync"
-)
-
-// The Timer type represents a single event.
-// When the Timer expires, the current time will be sent on C
-// unless the Timer represents an AfterFunc event.
-type Timer struct {
-	C <-chan int64
-	t int64       // The absolute time that the event should fire.
-	f func(int64) // The function to call when the event fires.
-	i int         // The event's index inside eventHeap.
+// Interface to timers implemented in package runtime.
+// Must be in sync with ../runtime/runtime.h:/^struct.Timer$
+type runtimeTimer struct {
+	i      int32
+	when   int64
+	period int64
+	f      func(int64, interface{})
+	arg    interface{}
 }
 
-type timerHeap []*Timer
+func startTimer(*runtimeTimer)
+func stopTimer(*runtimeTimer) bool
 
-// forever is the absolute time (in ns) of an event that is forever away.
-const forever = 1 << 62
+// The Timer type represents a single event.
+// When the Timer expires, the current time will be sent on C,
+// unless the Timer was created by AfterFunc.
+type Timer struct {
+	C <-chan int64
+	r runtimeTimer
+}
 
-// maxSleepTime is the maximum length of time that a sleeper
-// sleeps for before checking if it is defunct.
-const maxSleepTime = 1e9
-
-var (
-	// timerMutex guards the variables inside this var group.
-	timerMutex sync.Mutex
-
-	// timers holds a binary heap of pending events, terminated with a sentinel.
-	timers timerHeap
-
-	// currentSleeper is an ever-incrementing counter which represents
-	// the current sleeper. It allows older sleepers to detect that they are
-	// defunct and exit.
-	currentSleeper int64
-)
-
-func init() {
-	timers.Push(&Timer{t: forever}) // sentinel
+// Stop prevents the Timer from firing.
+// It returns true if the call stops the timer, false if the timer has already
+// expired or stopped.
+func (t *Timer) Stop() (ok bool) {
+	return stopTimer(&t.r)
 }
 
 // NewTimer creates a new Timer that will send
 // the current time on its channel after at least ns nanoseconds.
 func NewTimer(ns int64) *Timer {
 	c := make(chan int64, 1)
-	e := after(ns, func(t int64) { c <- t })
-	e.C = c
-	return e
+	t := &Timer{
+		C: c,
+		r: runtimeTimer{
+			when: Nanoseconds() + ns,
+			f:    sendTime,
+			arg:  c,
+		},
+	}
+	startTimer(&t.r)
+	return t
+}
+
+func sendTime(now int64, c interface{}) {
+	// Non-blocking send of time on c.
+	// Used in NewTimer, it cannot block anyway (buffer).
+	// Used in NewTicker, dropping sends on the floor is
+	// the desired behavior when the reader gets behind,
+	// because the sends are periodic.
+	select {
+	case c.(chan int64) <- now:
+	default:
+	}
 }
 
 // After waits at least ns nanoseconds before sending the current time
@@ -65,113 +71,17 @@
 // in its own goroutine. It returns a Timer that can
 // be used to cancel the call using its Stop method.
 func AfterFunc(ns int64, f func()) *Timer {
-	return after(ns, func(_ int64) {
-		go f()
-	})
-}
-
-// Stop prevents the Timer from firing.
-// It returns true if the call stops the timer, false if the timer has already
-// expired or stopped.
-func (e *Timer) Stop() (ok bool) {
-	timerMutex.Lock()
-	// Avoid removing the first event in the queue so that
-	// we don't start a new sleeper unnecessarily.
-	if e.i > 0 {
-		heap.Remove(timers, e.i)
+	t := &Timer{
+		r: runtimeTimer{
+			when: Nanoseconds() + ns,
+			f:    goFunc,
+			arg:  f,
+		},
 	}
-	ok = e.f != nil
-	e.f = nil
-	timerMutex.Unlock()
-	return
+	startTimer(&t.r)
+	return t
 }
 
-// after is the implementation of After and AfterFunc.
-// When the current time is after ns, it calls f with the current time.
-// It assumes that f will not block.
-func after(ns int64, f func(int64)) (e *Timer) {
-	now := Nanoseconds()
-	t := now + ns
-	if ns > 0 && t < now {
-		panic("time: time overflow")
-	}
-	timerMutex.Lock()
-	t0 := timers[0].t
-	e = &Timer{nil, t, f, -1}
-	heap.Push(timers, e)
-	// Start a new sleeper if the new event is before
-	// the first event in the queue. If the length of time
-	// until the new event is at least maxSleepTime,
-	// then we're guaranteed that the sleeper will wake up
-	// in time to service it, so no new sleeper is needed.
-	if t0 > t && (t0 == forever || ns < maxSleepTime) {
-		currentSleeper++
-		go sleeper(currentSleeper)
-	}
-	timerMutex.Unlock()
-	return
-}
-
-// sleeper continually looks at the earliest event in the queue, waits until it happens,
-// then removes any events in the queue that are due. It stops when the queue
-// is empty or when another sleeper has been started.
-func sleeper(sleeperId int64) {
-	timerMutex.Lock()
-	e := timers[0]
-	t := Nanoseconds()
-	for e.t != forever {
-		if dt := e.t - t; dt > 0 {
-			if dt > maxSleepTime {
-				dt = maxSleepTime
-			}
-			timerMutex.Unlock()
-			sysSleep(dt)
-			timerMutex.Lock()
-			if currentSleeper != sleeperId {
-				// Another sleeper has been started, making this one redundant.
-				break
-			}
-		}
-		e = timers[0]
-		t = Nanoseconds()
-		for t >= e.t {
-			if e.f != nil {
-				e.f(t)
-				e.f = nil
-			}
-			heap.Pop(timers)
-			e = timers[0]
-		}
-	}
-	timerMutex.Unlock()
-}
-
-func (timerHeap) Len() int {
-	return len(timers)
-}
-
-func (timerHeap) Less(i, j int) bool {
-	return timers[i].t < timers[j].t
-}
-
-func (timerHeap) Swap(i, j int) {
-	timers[i], timers[j] = timers[j], timers[i]
-	timers[i].i = i
-	timers[j].i = j
-}
-
-func (timerHeap) Push(x interface{}) {
-	e := x.(*Timer)
-	e.i = len(timers)
-	timers = append(timers, e)
-}
-
-func (timerHeap) Pop() interface{} {
-	// TODO: possibly shrink array.
-	n := len(timers) - 1
-	e := timers[n]
-	timers[n] = nil
-	timers = timers[0:n]
-	e.i = -1
-	return e
+func goFunc(now int64, arg interface{}) {
+	go arg.(func())()
 }