Repository: go
Issue: time: add ExternalNow, etc for external time and timers
Labels: Proposal,Proposal-Accepted

**Update May 5 2021**: The current proposed API is in https://github.com/golang/go/issues/36141#issuecomment-828667067.  - rsc
- - -

### Vocabulary:

- Program time: monotonic, but stops when the computer is in S3 sleep.
- Real time: monotonic, but continues to advance when the computer is in S3 sleep.
- Wall time: non-monotonic thing on your wristwatch or wall clock that NTP messes with. This one plays no role in this discussion here at all.
- Operating system: this always refers to the tuple of OS+ParticularVersion+ParticularConfiguration.

(These vocabulary terms can be nitpicked - maybe program time should be cpu time or something - but we've been using them prior in discussion, so let's continue to use them so as not to introduce confusion.)

### Proposal:

- Find some way to introduce "real time" semantics into Go, which currently mostly uses "program time", except on Windows, where it's always been "real time" for historical reasons.

### Motivation:

- Network protocols need to keep track of timeouts independent of whether a computer is asleep, since parties on a network exist in the real world, rather than virtualized on a CPU.

### Landscape:

- On some operating systems, the poll/select/kqueue/WaitFor*Object/futex family of functions takes a timeout that is measured in "real time", and on others measured in "program time".
- Most operating systems support a "program time" counter. Some support a "real time" counter, but some do not, depending on configuration or existence of S3.
- Most operating systems offer a notifier for resuming from sleep, though some may not, depending on configuration or existence of S3.
- Important observation: operating systems that do not offer a notifier support "program time" rather than "real time".

### Possibilities:

a. Make the existing `time.` and `time.Timer.` functions use "real time" exclusively, when possible. Introduce a function `runtime.RealtimeTimers() bool` to indicate whether Go successfully enabled "real time" timers rather than "program time" timers, the fallback.

b. Introduce additional duplicated functions to `time.` and `time.Timer.` that use "real time" rather than "program time". Introduce a function `time.RealtimeTimersAreRealTime() bool` to indicate whether Go successfully enabled "real time" timers on this new set of functions, or if the new set of functions behave identically to the old.

c. Introduce additional duplicated functions to `time.` and `time.Timer.` that use "real time" rather than "program time", and throw an error if "real time" capabilities aren't available, forcing users to introduce verbose fallback code if they only want to support "real time" opportunistically.

d. Add a function `runtime.UseRealtimeTimers() error` that attempts to change the runtime to use "real time" timers everywhere, like (a).

e. Add runtime function `runtime.UseRealtimeTimers(yes bool) error` that attempts to change the runtime to use "real time" or "program time" timers everywhere, like (a) but the ability to toggle. Add runtime function `runtime.RealtimeTimers() bool` to indicate the current state. The default start-state would be either OS-defined or "real time" or "program time", depending on what we decide.

f. Other options?

My personal preference would be (a) or (e), but I'm open to discussion.

CC @ianlancetaylor @bradfitz @aclements @rsc