...
Source file src/runtime/time.go
1
2
3
4
5
6
7 package runtime
8
9 import (
10 "internal/cpu"
11 "unsafe"
12 )
13
14
15
16
17
18 type timer struct {
19 tb *timersBucket
20 i int
21
22
23
24
25 when int64
26 period int64
27 f func(interface{}, uintptr)
28 arg interface{}
29 seq uintptr
30 }
31
32
33
34
35
36
37
38
39 const timersLen = 64
40
41
42
43
44
45
46
47
48 var timers [timersLen]struct {
49 timersBucket
50
51
52
53 pad [cpu.CacheLinePadSize - unsafe.Sizeof(timersBucket{})%cpu.CacheLinePadSize]byte
54 }
55
56 func (t *timer) assignBucket() *timersBucket {
57 id := uint8(getg().m.p.ptr().id) % timersLen
58 t.tb = &timers[id].timersBucket
59 return t.tb
60 }
61
62
63 type timersBucket struct {
64 lock mutex
65 gp *g
66 created bool
67 sleeping bool
68 rescheduling bool
69 sleepUntil int64
70 waitnote note
71 t []*timer
72 }
73
74
75 var faketime int64
76
77
78
79
80
81
82
83
84 func timeSleep(ns int64) {
85 if ns <= 0 {
86 return
87 }
88
89 gp := getg()
90 t := gp.timer
91 if t == nil {
92 t = new(timer)
93 gp.timer = t
94 }
95 *t = timer{}
96 t.when = nanotime() + ns
97 t.f = goroutineReady
98 t.arg = gp
99 tb := t.assignBucket()
100 lock(&tb.lock)
101 if !tb.addtimerLocked(t) {
102 unlock(&tb.lock)
103 badTimer()
104 }
105 goparkunlock(&tb.lock, waitReasonSleep, traceEvGoSleep, 2)
106 }
107
108
109
110 func startTimer(t *timer) {
111 if raceenabled {
112 racerelease(unsafe.Pointer(t))
113 }
114 addtimer(t)
115 }
116
117
118
119
120 func stopTimer(t *timer) bool {
121 return deltimer(t)
122 }
123
124
125
126
127 func goroutineReady(arg interface{}, seq uintptr) {
128 goready(arg.(*g), 0)
129 }
130
131 func addtimer(t *timer) {
132 tb := t.assignBucket()
133 lock(&tb.lock)
134 ok := tb.addtimerLocked(t)
135 unlock(&tb.lock)
136 if !ok {
137 badTimer()
138 }
139 }
140
141
142
143
144
145
146 func (tb *timersBucket) addtimerLocked(t *timer) bool {
147
148
149 if t.when < 0 {
150 t.when = 1<<63 - 1
151 }
152 t.i = len(tb.t)
153 tb.t = append(tb.t, t)
154 if !siftupTimer(tb.t, t.i) {
155 return false
156 }
157 if t.i == 0 {
158
159 if tb.sleeping && tb.sleepUntil > t.when {
160 tb.sleeping = false
161 notewakeup(&tb.waitnote)
162 }
163 if tb.rescheduling {
164 tb.rescheduling = false
165 goready(tb.gp, 0)
166 }
167 if !tb.created {
168 tb.created = true
169 go timerproc(tb)
170 }
171 }
172 return true
173 }
174
175
176
177 func deltimer(t *timer) bool {
178 if t.tb == nil {
179
180
181
182
183
184 return false
185 }
186
187 tb := t.tb
188
189 lock(&tb.lock)
190 removed, ok := tb.deltimerLocked(t)
191 unlock(&tb.lock)
192 if !ok {
193 badTimer()
194 }
195 return removed
196 }
197
198 func (tb *timersBucket) deltimerLocked(t *timer) (removed, ok bool) {
199
200
201
202 i := t.i
203 last := len(tb.t) - 1
204 if i < 0 || i > last || tb.t[i] != t {
205 return false, true
206 }
207 if i != last {
208 tb.t[i] = tb.t[last]
209 tb.t[i].i = i
210 }
211 tb.t[last] = nil
212 tb.t = tb.t[:last]
213 ok = true
214 if i != last {
215 if !siftupTimer(tb.t, i) {
216 ok = false
217 }
218 if !siftdownTimer(tb.t, i) {
219 ok = false
220 }
221 }
222 return true, ok
223 }
224
225 func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) {
226 tb := t.tb
227
228 lock(&tb.lock)
229 _, ok := tb.deltimerLocked(t)
230 if ok {
231 t.when = when
232 t.period = period
233 t.f = f
234 t.arg = arg
235 t.seq = seq
236 ok = tb.addtimerLocked(t)
237 }
238 unlock(&tb.lock)
239 if !ok {
240 badTimer()
241 }
242 }
243
244
245
246
247 func timerproc(tb *timersBucket) {
248 tb.gp = getg()
249 for {
250 lock(&tb.lock)
251 tb.sleeping = false
252 now := nanotime()
253 delta := int64(-1)
254 for {
255 if len(tb.t) == 0 {
256 delta = -1
257 break
258 }
259 t := tb.t[0]
260 delta = t.when - now
261 if delta > 0 {
262 break
263 }
264 ok := true
265 if t.period > 0 {
266
267 t.when += t.period * (1 + -delta/t.period)
268 if !siftdownTimer(tb.t, 0) {
269 ok = false
270 }
271 } else {
272
273 last := len(tb.t) - 1
274 if last > 0 {
275 tb.t[0] = tb.t[last]
276 tb.t[0].i = 0
277 }
278 tb.t[last] = nil
279 tb.t = tb.t[:last]
280 if last > 0 {
281 if !siftdownTimer(tb.t, 0) {
282 ok = false
283 }
284 }
285 t.i = -1
286 }
287 f := t.f
288 arg := t.arg
289 seq := t.seq
290 unlock(&tb.lock)
291 if !ok {
292 badTimer()
293 }
294 if raceenabled {
295 raceacquire(unsafe.Pointer(t))
296 }
297 f(arg, seq)
298 lock(&tb.lock)
299 }
300 if delta < 0 || faketime > 0 {
301
302 tb.rescheduling = true
303 goparkunlock(&tb.lock, waitReasonTimerGoroutineIdle, traceEvGoBlock, 1)
304 continue
305 }
306
307 tb.sleeping = true
308 tb.sleepUntil = now + delta
309 noteclear(&tb.waitnote)
310 unlock(&tb.lock)
311 notetsleepg(&tb.waitnote, delta)
312 }
313 }
314
315 func timejump() *g {
316 if faketime == 0 {
317 return nil
318 }
319
320 for i := range timers {
321 lock(&timers[i].lock)
322 }
323 gp := timejumpLocked()
324 for i := range timers {
325 unlock(&timers[i].lock)
326 }
327
328 return gp
329 }
330
331 func timejumpLocked() *g {
332
333 var minT *timer
334 for i := range timers {
335 tb := &timers[i]
336 if !tb.created || len(tb.t) == 0 {
337 continue
338 }
339 t := tb.t[0]
340 if minT == nil || t.when < minT.when {
341 minT = t
342 }
343 }
344 if minT == nil || minT.when <= faketime {
345 return nil
346 }
347
348 faketime = minT.when
349 tb := minT.tb
350 if !tb.rescheduling {
351 return nil
352 }
353 tb.rescheduling = false
354 return tb.gp
355 }
356
357 func timeSleepUntil() int64 {
358 next := int64(1<<63 - 1)
359
360
361
362
363
364
365 for i := range timers {
366 tb := &timers[i]
367
368 lock(&tb.lock)
369 if tb.sleeping && tb.sleepUntil < next {
370 next = tb.sleepUntil
371 }
372 unlock(&tb.lock)
373 }
374
375 return next
376 }
377
378
379
380
381
382
383
384
385
386
387
388
389 func siftupTimer(t []*timer, i int) bool {
390 if i >= len(t) {
391 return false
392 }
393 when := t[i].when
394 tmp := t[i]
395 for i > 0 {
396 p := (i - 1) / 4
397 if when >= t[p].when {
398 break
399 }
400 t[i] = t[p]
401 t[i].i = i
402 i = p
403 }
404 if tmp != t[i] {
405 t[i] = tmp
406 t[i].i = i
407 }
408 return true
409 }
410
411 func siftdownTimer(t []*timer, i int) bool {
412 n := len(t)
413 if i >= n {
414 return false
415 }
416 when := t[i].when
417 tmp := t[i]
418 for {
419 c := i*4 + 1
420 c3 := c + 2
421 if c >= n {
422 break
423 }
424 w := t[c].when
425 if c+1 < n && t[c+1].when < w {
426 w = t[c+1].when
427 c++
428 }
429 if c3 < n {
430 w3 := t[c3].when
431 if c3+1 < n && t[c3+1].when < w3 {
432 w3 = t[c3+1].when
433 c3++
434 }
435 if w3 < w {
436 w = w3
437 c = c3
438 }
439 }
440 if w >= when {
441 break
442 }
443 t[i] = t[c]
444 t[i].i = i
445 i = c
446 }
447 if tmp != t[i] {
448 t[i] = tmp
449 t[i].i = i
450 }
451 return true
452 }
453
454
455
456
457
458 func badTimer() {
459 panic(errorString("racy use of timers"))
460 }
461
View as plain text