Skip to content

Commit 0050c07

Browse files
runtime, syscall, time: prepare for adding timers to P's
Add new fields to runtime.timer, and adjust the various timer functions in preparation for adding timers to P's. This continues to use the old timer code. Updates #6239 Updates #27707 Change-Id: I9adb3814f657e083ec5e22736c4b5b52b77b6a3f Reviewed-on: https://go-review.googlesource.com/c/go/+/171829 Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Michael Knyszek <[email protected]>
1 parent a59808e commit 0050c07

File tree

2 files changed

+143
-8
lines changed

2 files changed

+143
-8
lines changed

src/runtime/time.go

+135-3
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,19 @@ import (
1111
"unsafe"
1212
)
1313

14+
// Temporary scaffolding while the new timer code is added.
15+
const oldTimers = true
16+
1417
// Package time knows the layout of this structure.
1518
// If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
1619
type timer struct {
17-
tb *timersBucket // the bucket the timer lives in
18-
i int // heap index
20+
tb *timersBucket // the bucket the timer lives in (oldTimers)
21+
i int // heap index (oldTimers)
22+
23+
// If this timer is on a heap, which P's heap it is on.
24+
// puintptr rather than *p to match uintptr in the versions
25+
// of this struct defined in other packages. (!oldTimers)
26+
pp puintptr
1927

2028
// Timer wakes up at when, and then at when+period, ... (period > 0 only)
2129
// each time calling f(arg, now) in the timer goroutine, so f must be
@@ -25,6 +33,12 @@ type timer struct {
2533
f func(interface{}, uintptr)
2634
arg interface{}
2735
seq uintptr
36+
37+
// What to set the when field to in timerModifiedXX status. (!oldTimers)
38+
nextwhen int64
39+
40+
// The status field holds one of the values below. (!oldTimers)
41+
status uint32
2842
}
2943

3044
// timersLen is the length of timers array.
@@ -69,6 +83,84 @@ type timersBucket struct {
6983
t []*timer
7084
}
7185

86+
// Code outside this file has to be careful in using a timer value.
87+
//
88+
// The pp, status, and nextwhen fields may only be used by code in this file.
89+
//
90+
// Code that creates a new timer value can set the when, period, f,
91+
// arg, and seq fields.
92+
// A new timer value may be passed to addtimer (called by time.startTimer).
93+
// After doing that no fields may be touched.
94+
//
95+
// An active timer (one that has been passed to addtimer) may be
96+
// passed to deltimer (time.stopTimer), after which it is no longer an
97+
// active timer. It is an inactive timer.
98+
// In an inactive timer the period, f, arg, and seq fields may be modified,
99+
// but not the when field.
100+
// It's OK to just drop an inactive timer and let the GC collect it.
101+
// It's not OK to pass an inactive timer to addtimer.
102+
// Only newly allocated timer values may be passed to addtimer.
103+
//
104+
// An active timer may be passed to modtimer. No fields may be touched.
105+
// It remains an active timer.
106+
//
107+
// An inactive timer may be passed to resettimer to turn into an
108+
// active timer with an updated when field.
109+
// It's OK to pass a newly allocated timer value to resettimer.
110+
//
111+
// Timer operations are addtimer, deltimer, modtimer, resettimer,
112+
// cleantimers, adjusttimers, and runtimer.
113+
//
114+
// We don't permit calling addtimer/deltimer/modtimer/resettimer simultaneously,
115+
// but adjusttimers and runtimer can be called at the same time as any of those.
116+
//
117+
// Active timers live in heaps attached to P, in the timers field.
118+
// Inactive timers live there too temporarily, until they are removed.
119+
120+
// Values for the timer status field.
121+
const (
122+
// Timer has no status set yet.
123+
timerNoStatus = iota
124+
125+
// Waiting for timer to fire.
126+
// The timer is in some P's heap.
127+
timerWaiting
128+
129+
// Running the timer function.
130+
// A timer will only have this status briefly.
131+
timerRunning
132+
133+
// The timer is deleted and should be removed.
134+
// It should not be run, but it is still in some P's heap.
135+
timerDeleted
136+
137+
// The timer is being removed.
138+
// The timer will only have this status briefly.
139+
timerRemoving
140+
141+
// The timer has been stopped.
142+
// It is not in any P's heap.
143+
timerRemoved
144+
145+
// The timer is being modified.
146+
// The timer will only have this status briefly.
147+
timerModifying
148+
149+
// The timer has been modified to an earlier time.
150+
// The new when value is in the nextwhen field.
151+
// The timer is in some P's heap, possibly in the wrong place.
152+
timerModifiedEarlier
153+
154+
// The timer has been modified to the same or a later time.
155+
// The new when value is in the nextwhen field.
156+
// The timer is in some P's heap, possibly in the wrong place.
157+
timerModifiedLater
158+
159+
// The timer has been modified and is being moved.
160+
// The timer will only have this status briefly.
161+
timerMoving
162+
)
163+
72164
// Package time APIs.
73165
// Godoc uses the comments in package time, not these.
74166

@@ -77,6 +169,14 @@ type timersBucket struct {
77169
// timeSleep puts the current goroutine to sleep for at least ns nanoseconds.
78170
//go:linkname timeSleep time.Sleep
79171
func timeSleep(ns int64) {
172+
if oldTimers {
173+
timeSleepOld(ns)
174+
return
175+
}
176+
throw("new timeSleep not yet implemented")
177+
}
178+
179+
func timeSleepOld(ns int64) {
80180
if ns <= 0 {
81181
return
82182
}
@@ -97,7 +197,7 @@ func timeSleep(ns int64) {
97197
unlock(&tb.lock)
98198
badTimer()
99199
}
100-
goparkunlock(&tb.lock, waitReasonSleep, traceEvGoSleep, 2)
200+
goparkunlock(&tb.lock, waitReasonSleep, traceEvGoSleep, 3)
101201
}
102202

103203
// startTimer adds t to the timer heap.
@@ -133,6 +233,14 @@ func goroutineReady(arg interface{}, seq uintptr) {
133233
}
134234

135235
func addtimer(t *timer) {
236+
if oldTimers {
237+
addtimerOld(t)
238+
return
239+
}
240+
throw("new addtimer not yet implemented")
241+
}
242+
243+
func addtimerOld(t *timer) {
136244
tb := t.assignBucket()
137245
lock(&tb.lock)
138246
ok := tb.addtimerLocked(t)
@@ -179,6 +287,14 @@ func (tb *timersBucket) addtimerLocked(t *timer) bool {
179287
// Delete timer t from the heap.
180288
// Do not need to update the timerproc: if it wakes up early, no big deal.
181289
func deltimer(t *timer) bool {
290+
if oldTimers {
291+
return deltimerOld(t)
292+
}
293+
throw("no deltimer not yet implemented")
294+
return false
295+
}
296+
297+
func deltimerOld(t *timer) bool {
182298
if t.tb == nil {
183299
// t.tb can be nil if the user created a timer
184300
// directly, without invoking startTimer e.g
@@ -227,6 +343,14 @@ func (tb *timersBucket) deltimerLocked(t *timer) (removed, ok bool) {
227343
}
228344

229345
func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) {
346+
if oldTimers {
347+
modtimerOld(t, when, period, f, arg, seq)
348+
return
349+
}
350+
throw("new modtimer not yet implemented")
351+
}
352+
353+
func modtimerOld(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) {
230354
tb := t.tb
231355

232356
lock(&tb.lock)
@@ -250,6 +374,14 @@ func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg in
250374
// This should be called instead of addtimer if the timer value has been,
251375
// or may have been, used previously.
252376
func resettimer(t *timer, when int64) {
377+
if oldTimers {
378+
resettimerOld(t, when)
379+
return
380+
}
381+
throw("new resettimer not yet implemented")
382+
}
383+
384+
func resettimerOld(t *timer, when int64) {
253385
t.when = when
254386
addtimer(t)
255387
}

src/time/sleep.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ func Sleep(d Duration)
1313
type runtimeTimer struct {
1414
tb uintptr
1515
i int
16+
pp uintptr
1617

17-
when int64
18-
period int64
19-
f func(interface{}, uintptr) // NOTE: must not be closure
20-
arg interface{}
21-
seq uintptr
18+
when int64
19+
period int64
20+
f func(interface{}, uintptr) // NOTE: must not be closure
21+
arg interface{}
22+
seq uintptr
23+
nextwhen int64
24+
status uint32
2225
}
2326

2427
// when is a helper function for setting the 'when' field of a runtimeTimer.

0 commit comments

Comments
 (0)