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