]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add new resettimer function
authorIan Lance Taylor <iant@golang.org>
Thu, 11 Apr 2019 04:16:09 +0000 (21:16 -0700)
committerIan Lance Taylor <iant@golang.org>
Tue, 22 Oct 2019 20:22:27 +0000 (20:22 +0000)
Updates #27707

Change-Id: I02f97ec7869ec8a3fb2dfc94cff246badc7ea0fa
Reviewed-on: https://go-review.googlesource.com/c/go/+/171833
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/runtime/time.go

index 54cbb0b6e469a4f23e53e2abcaff8ad1dfc529a6..4e3511eb118170e48c4224cac088e6a8e2433ea9 100644 (file)
@@ -141,6 +141,16 @@ type timersBucket struct {
 //   timerRemoving   -> wait until status changes
 //   timerDeleted    -> panic: concurrent modtimer/deltimer calls
 //   timerModifying  -> panic: concurrent modtimer calls
+// resettimer:
+//   timerNoStatus   -> timerWaiting
+//   timerRemoved    -> timerWaiting
+//   timerDeleted    -> timerModifying -> timerModifiedXX
+//   timerRemoving   -> wait until status changes
+//   timerRunning    -> wait until status changes
+//   timerWaiting    -> panic: resettimer called on active timer
+//   timerMoving     -> panic: resettimer called on active timer
+//   timerModifiedXX -> panic: resettimer called on active timer
+//   timerModifying  -> panic: resettimer called on active timer
 
 // Values for the timer status field.
 const (
@@ -573,7 +583,50 @@ func resettimer(t *timer, when int64) {
                resettimerOld(t, when)
                return
        }
-       throw("new resettimer not yet implemented")
+
+       if when < 0 {
+               when = maxWhen
+       }
+
+       for {
+               switch s := atomic.Load(&t.status); s {
+               case timerNoStatus, timerRemoved:
+                       atomic.Store(&t.status, timerWaiting)
+                       t.when = when
+                       addInitializedTimer(t)
+                       return
+               case timerDeleted:
+                       if atomic.Cas(&t.status, s, timerModifying) {
+                               t.nextwhen = when
+                               newStatus := uint32(timerModifiedLater)
+                               if when < t.when {
+                                       newStatus = timerModifiedEarlier
+                                       atomic.Xadd(&t.pp.ptr().adjustTimers, 1)
+                               }
+                               if !atomic.Cas(&t.status, timerModifying, newStatus) {
+                                       badTimer()
+                               }
+                               if newStatus == timerModifiedEarlier {
+                                       wakeNetPoller(when)
+                               }
+                               return
+                       }
+               case timerRemoving:
+                       // Wait for the removal to complete.
+                       osyield()
+               case timerRunning:
+                       // Even though the timer should not be active,
+                       // we can see timerRunning if the timer function
+                       // permits some other goroutine to call resettimer.
+                       // Wait until the run is complete.
+                       osyield()
+               case timerWaiting, timerModifying, timerModifiedEarlier, timerModifiedLater, timerMoving:
+                       // Called resettimer on active timer.
+                       badTimer()
+               default:
+                       badTimer()
+               }
+       }
 }
 
 func resettimerOld(t *timer, when int64) {