Source file
src/runtime/time.go
Documentation: runtime
1
2
3
4
5
6
7 package runtime
8
9 import (
10 "runtime/internal/atomic"
11 "runtime/internal/sys"
12 "unsafe"
13 )
14
15
16
17 type timer struct {
18
19
20
21 pp puintptr
22
23
24
25
26
27
28 when int64
29 period int64
30 f func(interface{}, uintptr)
31 arg interface{}
32 seq uintptr
33
34
35 nextwhen int64
36
37
38 status uint32
39 }
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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 const (
120
121 timerNoStatus = iota
122
123
124
125 timerWaiting
126
127
128
129 timerRunning
130
131
132
133 timerDeleted
134
135
136
137 timerRemoving
138
139
140
141 timerRemoved
142
143
144
145 timerModifying
146
147
148
149
150 timerModifiedEarlier
151
152
153
154
155 timerModifiedLater
156
157
158
159 timerMoving
160 )
161
162
163 const maxWhen = 1<<63 - 1
164
165
166
167 const verifyTimers = false
168
169
170
171
172
173
174
175
176 func timeSleep(ns int64) {
177 if ns <= 0 {
178 return
179 }
180
181 gp := getg()
182 t := gp.timer
183 if t == nil {
184 t = new(timer)
185 gp.timer = t
186 }
187 t.f = goroutineReady
188 t.arg = gp
189 t.nextwhen = nanotime() + ns
190 if t.nextwhen < 0 {
191 t.nextwhen = maxWhen
192 }
193 gopark(resetForSleep, unsafe.Pointer(t), waitReasonSleep, traceEvGoSleep, 1)
194 }
195
196
197
198
199
200 func resetForSleep(gp *g, ut unsafe.Pointer) bool {
201 t := (*timer)(ut)
202 resettimer(t, t.nextwhen)
203 return true
204 }
205
206
207
208 func startTimer(t *timer) {
209 if raceenabled {
210 racerelease(unsafe.Pointer(t))
211 }
212 addtimer(t)
213 }
214
215
216
217
218 func stopTimer(t *timer) bool {
219 return deltimer(t)
220 }
221
222
223
224
225 func resetTimer(t *timer, when int64) bool {
226 if raceenabled {
227 racerelease(unsafe.Pointer(t))
228 }
229 return resettimer(t, when)
230 }
231
232
233
234 func modTimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) {
235 modtimer(t, when, period, f, arg, seq)
236 }
237
238
239
240
241 func goroutineReady(arg interface{}, seq uintptr) {
242 goready(arg.(*g), 0)
243 }
244
245
246
247
248
249 func addtimer(t *timer) {
250
251
252
253 if t.when <= 0 {
254 throw("timer when must be positive")
255 }
256 if t.period < 0 {
257 throw("timer period must be non-negative")
258 }
259 if t.status != timerNoStatus {
260 throw("addtimer called with initialized timer")
261 }
262 t.status = timerWaiting
263
264 when := t.when
265
266
267 mp := acquirem()
268
269 pp := getg().m.p.ptr()
270 lock(&pp.timersLock)
271 cleantimers(pp)
272 doaddtimer(pp, t)
273 unlock(&pp.timersLock)
274
275 wakeNetPoller(when)
276
277 releasem(mp)
278 }
279
280
281
282 func doaddtimer(pp *p, t *timer) {
283
284
285 if netpollInited == 0 {
286 netpollGenericInit()
287 }
288
289 if t.pp != 0 {
290 throw("doaddtimer: P already set in timer")
291 }
292 t.pp.set(pp)
293 i := len(pp.timers)
294 pp.timers = append(pp.timers, t)
295 siftupTimer(pp.timers, i)
296 if t == pp.timers[0] {
297 atomic.Store64(&pp.timer0When, uint64(t.when))
298 }
299 atomic.Xadd(&pp.numTimers, 1)
300 }
301
302
303
304
305
306 func deltimer(t *timer) bool {
307 for {
308 switch s := atomic.Load(&t.status); s {
309 case timerWaiting, timerModifiedLater:
310
311
312 mp := acquirem()
313 if atomic.Cas(&t.status, s, timerModifying) {
314
315
316
317 tpp := t.pp.ptr()
318 if !atomic.Cas(&t.status, timerModifying, timerDeleted) {
319 badTimer()
320 }
321 releasem(mp)
322 atomic.Xadd(&tpp.deletedTimers, 1)
323
324 return true
325 } else {
326 releasem(mp)
327 }
328 case timerModifiedEarlier:
329
330
331 mp := acquirem()
332 if atomic.Cas(&t.status, s, timerModifying) {
333
334
335 tpp := t.pp.ptr()
336 if !atomic.Cas(&t.status, timerModifying, timerDeleted) {
337 badTimer()
338 }
339 releasem(mp)
340 atomic.Xadd(&tpp.deletedTimers, 1)
341
342 return true
343 } else {
344 releasem(mp)
345 }
346 case timerDeleted, timerRemoving, timerRemoved:
347
348 return false
349 case timerRunning, timerMoving:
350
351
352 osyield()
353 case timerNoStatus:
354
355
356 return false
357 case timerModifying:
358
359
360 osyield()
361 default:
362 badTimer()
363 }
364 }
365 }
366
367
368
369
370
371 func dodeltimer(pp *p, i int) int {
372 if t := pp.timers[i]; t.pp.ptr() != pp {
373 throw("dodeltimer: wrong P")
374 } else {
375 t.pp = 0
376 }
377 last := len(pp.timers) - 1
378 if i != last {
379 pp.timers[i] = pp.timers[last]
380 }
381 pp.timers[last] = nil
382 pp.timers = pp.timers[:last]
383 smallestChanged := i
384 if i != last {
385
386
387 smallestChanged = siftupTimer(pp.timers, i)
388 siftdownTimer(pp.timers, i)
389 }
390 if i == 0 {
391 updateTimer0When(pp)
392 }
393 n := atomic.Xadd(&pp.numTimers, -1)
394 if n == 0 {
395
396 atomic.Store64(&pp.timerModifiedEarliest, 0)
397 }
398 return smallestChanged
399 }
400
401
402
403
404
405 func dodeltimer0(pp *p) {
406 if t := pp.timers[0]; t.pp.ptr() != pp {
407 throw("dodeltimer0: wrong P")
408 } else {
409 t.pp = 0
410 }
411 last := len(pp.timers) - 1
412 if last > 0 {
413 pp.timers[0] = pp.timers[last]
414 }
415 pp.timers[last] = nil
416 pp.timers = pp.timers[:last]
417 if last > 0 {
418 siftdownTimer(pp.timers, 0)
419 }
420 updateTimer0When(pp)
421 n := atomic.Xadd(&pp.numTimers, -1)
422 if n == 0 {
423
424 atomic.Store64(&pp.timerModifiedEarliest, 0)
425 }
426 }
427
428
429
430
431 func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) bool {
432 if when <= 0 {
433 throw("timer when must be positive")
434 }
435 if period < 0 {
436 throw("timer period must be non-negative")
437 }
438
439 status := uint32(timerNoStatus)
440 wasRemoved := false
441 var pending bool
442 var mp *m
443 loop:
444 for {
445 switch status = atomic.Load(&t.status); status {
446 case timerWaiting, timerModifiedEarlier, timerModifiedLater:
447
448
449 mp = acquirem()
450 if atomic.Cas(&t.status, status, timerModifying) {
451 pending = true
452 break loop
453 }
454 releasem(mp)
455 case timerNoStatus, timerRemoved:
456
457
458 mp = acquirem()
459
460
461
462 if atomic.Cas(&t.status, status, timerModifying) {
463 wasRemoved = true
464 pending = false
465 break loop
466 }
467 releasem(mp)
468 case timerDeleted:
469
470
471 mp = acquirem()
472 if atomic.Cas(&t.status, status, timerModifying) {
473 atomic.Xadd(&t.pp.ptr().deletedTimers, -1)
474 pending = false
475 break loop
476 }
477 releasem(mp)
478 case timerRunning, timerRemoving, timerMoving:
479
480
481 osyield()
482 case timerModifying:
483
484
485 osyield()
486 default:
487 badTimer()
488 }
489 }
490
491 t.period = period
492 t.f = f
493 t.arg = arg
494 t.seq = seq
495
496 if wasRemoved {
497 t.when = when
498 pp := getg().m.p.ptr()
499 lock(&pp.timersLock)
500 doaddtimer(pp, t)
501 unlock(&pp.timersLock)
502 if !atomic.Cas(&t.status, timerModifying, timerWaiting) {
503 badTimer()
504 }
505 releasem(mp)
506 wakeNetPoller(when)
507 } else {
508
509
510
511
512
513 t.nextwhen = when
514
515 newStatus := uint32(timerModifiedLater)
516 if when < t.when {
517 newStatus = timerModifiedEarlier
518 }
519
520 tpp := t.pp.ptr()
521
522 if newStatus == timerModifiedEarlier {
523 updateTimerModifiedEarliest(tpp, when)
524 }
525
526
527 if !atomic.Cas(&t.status, timerModifying, newStatus) {
528 badTimer()
529 }
530 releasem(mp)
531
532
533 if newStatus == timerModifiedEarlier {
534 wakeNetPoller(when)
535 }
536 }
537
538 return pending
539 }
540
541
542
543
544
545
546 func resettimer(t *timer, when int64) bool {
547 return modtimer(t, when, t.period, t.f, t.arg, t.seq)
548 }
549
550
551
552
553
554 func cleantimers(pp *p) {
555 gp := getg()
556 for {
557 if len(pp.timers) == 0 {
558 return
559 }
560
561
562
563
564
565 if gp.preemptStop {
566 return
567 }
568
569 t := pp.timers[0]
570 if t.pp.ptr() != pp {
571 throw("cleantimers: bad p")
572 }
573 switch s := atomic.Load(&t.status); s {
574 case timerDeleted:
575 if !atomic.Cas(&t.status, s, timerRemoving) {
576 continue
577 }
578 dodeltimer0(pp)
579 if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
580 badTimer()
581 }
582 atomic.Xadd(&pp.deletedTimers, -1)
583 case timerModifiedEarlier, timerModifiedLater:
584 if !atomic.Cas(&t.status, s, timerMoving) {
585 continue
586 }
587
588 t.when = t.nextwhen
589
590 dodeltimer0(pp)
591 doaddtimer(pp, t)
592 if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
593 badTimer()
594 }
595 default:
596
597 return
598 }
599 }
600 }
601
602
603
604
605
606 func moveTimers(pp *p, timers []*timer) {
607 for _, t := range timers {
608 loop:
609 for {
610 switch s := atomic.Load(&t.status); s {
611 case timerWaiting:
612 if !atomic.Cas(&t.status, s, timerMoving) {
613 continue
614 }
615 t.pp = 0
616 doaddtimer(pp, t)
617 if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
618 badTimer()
619 }
620 break loop
621 case timerModifiedEarlier, timerModifiedLater:
622 if !atomic.Cas(&t.status, s, timerMoving) {
623 continue
624 }
625 t.when = t.nextwhen
626 t.pp = 0
627 doaddtimer(pp, t)
628 if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
629 badTimer()
630 }
631 break loop
632 case timerDeleted:
633 if !atomic.Cas(&t.status, s, timerRemoved) {
634 continue
635 }
636 t.pp = 0
637
638 break loop
639 case timerModifying:
640
641 osyield()
642 case timerNoStatus, timerRemoved:
643
644 badTimer()
645 case timerRunning, timerRemoving, timerMoving:
646
647
648 badTimer()
649 default:
650 badTimer()
651 }
652 }
653 }
654 }
655
656
657
658
659
660
661 func adjusttimers(pp *p, now int64) {
662
663
664
665
666
667 first := atomic.Load64(&pp.timerModifiedEarliest)
668 if first == 0 || int64(first) > now {
669 if verifyTimers {
670 verifyTimerHeap(pp)
671 }
672 return
673 }
674
675
676 atomic.Store64(&pp.timerModifiedEarliest, 0)
677
678 var moved []*timer
679 for i := 0; i < len(pp.timers); i++ {
680 t := pp.timers[i]
681 if t.pp.ptr() != pp {
682 throw("adjusttimers: bad p")
683 }
684 switch s := atomic.Load(&t.status); s {
685 case timerDeleted:
686 if atomic.Cas(&t.status, s, timerRemoving) {
687 changed := dodeltimer(pp, i)
688 if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
689 badTimer()
690 }
691 atomic.Xadd(&pp.deletedTimers, -1)
692
693
694 i = changed - 1
695 }
696 case timerModifiedEarlier, timerModifiedLater:
697 if atomic.Cas(&t.status, s, timerMoving) {
698
699 t.when = t.nextwhen
700
701
702
703
704 changed := dodeltimer(pp, i)
705 moved = append(moved, t)
706
707
708 i = changed - 1
709 }
710 case timerNoStatus, timerRunning, timerRemoving, timerRemoved, timerMoving:
711 badTimer()
712 case timerWaiting:
713
714 case timerModifying:
715
716 osyield()
717 i--
718 default:
719 badTimer()
720 }
721 }
722
723 if len(moved) > 0 {
724 addAdjustedTimers(pp, moved)
725 }
726
727 if verifyTimers {
728 verifyTimerHeap(pp)
729 }
730 }
731
732
733
734 func addAdjustedTimers(pp *p, moved []*timer) {
735 for _, t := range moved {
736 doaddtimer(pp, t)
737 if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
738 badTimer()
739 }
740 }
741 }
742
743
744
745
746
747
748 func nobarrierWakeTime(pp *p) int64 {
749 next := int64(atomic.Load64(&pp.timer0When))
750 nextAdj := int64(atomic.Load64(&pp.timerModifiedEarliest))
751 if next == 0 || (nextAdj != 0 && nextAdj < next) {
752 next = nextAdj
753 }
754 return next
755 }
756
757
758
759
760
761
762
763
764 func runtimer(pp *p, now int64) int64 {
765 for {
766 t := pp.timers[0]
767 if t.pp.ptr() != pp {
768 throw("runtimer: bad p")
769 }
770 switch s := atomic.Load(&t.status); s {
771 case timerWaiting:
772 if t.when > now {
773
774 return t.when
775 }
776
777 if !atomic.Cas(&t.status, s, timerRunning) {
778 continue
779 }
780
781
782 runOneTimer(pp, t, now)
783 return 0
784
785 case timerDeleted:
786 if !atomic.Cas(&t.status, s, timerRemoving) {
787 continue
788 }
789 dodeltimer0(pp)
790 if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
791 badTimer()
792 }
793 atomic.Xadd(&pp.deletedTimers, -1)
794 if len(pp.timers) == 0 {
795 return -1
796 }
797
798 case timerModifiedEarlier, timerModifiedLater:
799 if !atomic.Cas(&t.status, s, timerMoving) {
800 continue
801 }
802 t.when = t.nextwhen
803 dodeltimer0(pp)
804 doaddtimer(pp, t)
805 if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
806 badTimer()
807 }
808
809 case timerModifying:
810
811 osyield()
812
813 case timerNoStatus, timerRemoved:
814
815 badTimer()
816 case timerRunning, timerRemoving, timerMoving:
817
818
819 badTimer()
820 default:
821 badTimer()
822 }
823 }
824 }
825
826
827
828
829
830 func runOneTimer(pp *p, t *timer, now int64) {
831 if raceenabled {
832 ppcur := getg().m.p.ptr()
833 if ppcur.timerRaceCtx == 0 {
834 ppcur.timerRaceCtx = racegostart(funcPC(runtimer) + sys.PCQuantum)
835 }
836 raceacquirectx(ppcur.timerRaceCtx, unsafe.Pointer(t))
837 }
838
839 f := t.f
840 arg := t.arg
841 seq := t.seq
842
843 if t.period > 0 {
844
845 delta := t.when - now
846 t.when += t.period * (1 + -delta/t.period)
847 if t.when < 0 {
848 t.when = maxWhen
849 }
850 siftdownTimer(pp.timers, 0)
851 if !atomic.Cas(&t.status, timerRunning, timerWaiting) {
852 badTimer()
853 }
854 updateTimer0When(pp)
855 } else {
856
857 dodeltimer0(pp)
858 if !atomic.Cas(&t.status, timerRunning, timerNoStatus) {
859 badTimer()
860 }
861 }
862
863 if raceenabled {
864
865 gp := getg()
866 if gp.racectx != 0 {
867 throw("runOneTimer: unexpected racectx")
868 }
869 gp.racectx = gp.m.p.ptr().timerRaceCtx
870 }
871
872 unlock(&pp.timersLock)
873
874 f(arg, seq)
875
876 lock(&pp.timersLock)
877
878 if raceenabled {
879 gp := getg()
880 gp.racectx = 0
881 }
882 }
883
884
885
886
887
888
889
890
891
892
893 func clearDeletedTimers(pp *p) {
894
895
896 atomic.Store64(&pp.timerModifiedEarliest, 0)
897
898 cdel := int32(0)
899 to := 0
900 changedHeap := false
901 timers := pp.timers
902 nextTimer:
903 for _, t := range timers {
904 for {
905 switch s := atomic.Load(&t.status); s {
906 case timerWaiting:
907 if changedHeap {
908 timers[to] = t
909 siftupTimer(timers, to)
910 }
911 to++
912 continue nextTimer
913 case timerModifiedEarlier, timerModifiedLater:
914 if atomic.Cas(&t.status, s, timerMoving) {
915 t.when = t.nextwhen
916 timers[to] = t
917 siftupTimer(timers, to)
918 to++
919 changedHeap = true
920 if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
921 badTimer()
922 }
923 continue nextTimer
924 }
925 case timerDeleted:
926 if atomic.Cas(&t.status, s, timerRemoving) {
927 t.pp = 0
928 cdel++
929 if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
930 badTimer()
931 }
932 changedHeap = true
933 continue nextTimer
934 }
935 case timerModifying:
936
937 osyield()
938 case timerNoStatus, timerRemoved:
939
940 badTimer()
941 case timerRunning, timerRemoving, timerMoving:
942
943
944 badTimer()
945 default:
946 badTimer()
947 }
948 }
949 }
950
951
952
953 for i := to; i < len(timers); i++ {
954 timers[i] = nil
955 }
956
957 atomic.Xadd(&pp.deletedTimers, -cdel)
958 atomic.Xadd(&pp.numTimers, -cdel)
959
960 timers = timers[:to]
961 pp.timers = timers
962 updateTimer0When(pp)
963
964 if verifyTimers {
965 verifyTimerHeap(pp)
966 }
967 }
968
969
970
971
972 func verifyTimerHeap(pp *p) {
973 for i, t := range pp.timers {
974 if i == 0 {
975
976 continue
977 }
978
979
980 p := (i - 1) / 4
981 if t.when < pp.timers[p].when {
982 print("bad timer heap at ", i, ": ", p, ": ", pp.timers[p].when, ", ", i, ": ", t.when, "\n")
983 throw("bad timer heap")
984 }
985 }
986 if numTimers := int(atomic.Load(&pp.numTimers)); len(pp.timers) != numTimers {
987 println("timer heap len", len(pp.timers), "!= numTimers", numTimers)
988 throw("bad timer heap len")
989 }
990 }
991
992
993
994 func updateTimer0When(pp *p) {
995 if len(pp.timers) == 0 {
996 atomic.Store64(&pp.timer0When, 0)
997 } else {
998 atomic.Store64(&pp.timer0When, uint64(pp.timers[0].when))
999 }
1000 }
1001
1002
1003
1004
1005 func updateTimerModifiedEarliest(pp *p, nextwhen int64) {
1006 for {
1007 old := atomic.Load64(&pp.timerModifiedEarliest)
1008 if old != 0 && int64(old) < nextwhen {
1009 return
1010 }
1011 if atomic.Cas64(&pp.timerModifiedEarliest, old, uint64(nextwhen)) {
1012 return
1013 }
1014 }
1015 }
1016
1017
1018
1019
1020 func timeSleepUntil() (int64, *p) {
1021 next := int64(maxWhen)
1022 var pret *p
1023
1024
1025 lock(&allpLock)
1026 for _, pp := range allp {
1027 if pp == nil {
1028
1029
1030 continue
1031 }
1032
1033 w := int64(atomic.Load64(&pp.timer0When))
1034 if w != 0 && w < next {
1035 next = w
1036 pret = pp
1037 }
1038
1039 w = int64(atomic.Load64(&pp.timerModifiedEarliest))
1040 if w != 0 && w < next {
1041 next = w
1042 pret = pp
1043 }
1044 }
1045 unlock(&allpLock)
1046
1047 return next, pret
1048 }
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061 func siftupTimer(t []*timer, i int) int {
1062 if i >= len(t) {
1063 badTimer()
1064 }
1065 when := t[i].when
1066 if when <= 0 {
1067 badTimer()
1068 }
1069 tmp := t[i]
1070 for i > 0 {
1071 p := (i - 1) / 4
1072 if when >= t[p].when {
1073 break
1074 }
1075 t[i] = t[p]
1076 i = p
1077 }
1078 if tmp != t[i] {
1079 t[i] = tmp
1080 }
1081 return i
1082 }
1083
1084
1085
1086 func siftdownTimer(t []*timer, i int) {
1087 n := len(t)
1088 if i >= n {
1089 badTimer()
1090 }
1091 when := t[i].when
1092 if when <= 0 {
1093 badTimer()
1094 }
1095 tmp := t[i]
1096 for {
1097 c := i*4 + 1
1098 c3 := c + 2
1099 if c >= n {
1100 break
1101 }
1102 w := t[c].when
1103 if c+1 < n && t[c+1].when < w {
1104 w = t[c+1].when
1105 c++
1106 }
1107 if c3 < n {
1108 w3 := t[c3].when
1109 if c3+1 < n && t[c3+1].when < w3 {
1110 w3 = t[c3+1].when
1111 c3++
1112 }
1113 if w3 < w {
1114 w = w3
1115 c = c3
1116 }
1117 }
1118 if w >= when {
1119 break
1120 }
1121 t[i] = t[c]
1122 i = c
1123 }
1124 if tmp != t[i] {
1125 t[i] = tmp
1126 }
1127 }
1128
1129
1130
1131
1132
1133 func badTimer() {
1134 throw("timer data corruption")
1135 }
1136
View as plain text