]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: convert timer.status to atomic type
authorcui fliter <imcusg@gmail.com>
Thu, 8 Sep 2022 11:29:09 +0000 (11:29 +0000)
committerGopher Robot <gobot@golang.org>
Tue, 13 Sep 2022 17:41:56 +0000 (17:41 +0000)
For #53821

Change-Id: I7cb6a16626964d5023b96609d9921bfe4a679d8f
GitHub-Last-Rev: ddfce125be4aa565aa4d2081841c649bf2f71459
GitHub-Pull-Request: golang/go#54865
Reviewed-on: https://go-review.googlesource.com/c/go/+/428196
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Jenny Rakoczy <jenny@golang.org>
Auto-Submit: Jenny Rakoczy <jenny@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/runtime/time.go

index 945756109a17520282a70663fe3f1ea8b2d3e646..6cd70b7aedae92be5508a3e40bddd379fa77b542 100644 (file)
@@ -36,7 +36,7 @@ type timer struct {
        nextwhen int64
 
        // The status field holds one of the values below.
-       status uint32
+       status atomic.Uint32
 }
 
 // Code outside this file has to be careful in using a timer value.
@@ -249,6 +249,7 @@ func goroutineReady(arg any, seq uintptr) {
        goready(arg.(*g), 0)
 }
 
+// Note: this changes some unsynchronized operations to synchronized operations
 // addtimer adds a timer to the current P.
 // This should only be called with a newly created timer.
 // That avoids the risk of changing the when field of a timer in some P's heap,
@@ -263,10 +264,10 @@ func addtimer(t *timer) {
        if t.period < 0 {
                throw("timer period must be non-negative")
        }
-       if t.status != timerNoStatus {
+       if t.status.Load() != timerNoStatus {
                throw("addtimer called with initialized timer")
        }
-       t.status = timerWaiting
+       t.status.Store(timerWaiting)
 
        when := t.when
 
@@ -312,17 +313,17 @@ func doaddtimer(pp *p, t *timer) {
 // Reports whether the timer was removed before it was run.
 func deltimer(t *timer) bool {
        for {
-               switch s := atomic.Load(&t.status); s {
+               switch s := t.status.Load(); s {
                case timerWaiting, timerModifiedLater:
                        // Prevent preemption while the timer is in timerModifying.
                        // This could lead to a self-deadlock. See #38070.
                        mp := acquirem()
-                       if atomic.Cas(&t.status, s, timerModifying) {
+                       if t.status.CompareAndSwap(s, timerModifying) {
                                // Must fetch t.pp before changing status,
                                // as cleantimers in another goroutine
                                // can clear t.pp of a timerDeleted timer.
                                tpp := t.pp.ptr()
-                               if !atomic.Cas(&t.status, timerModifying, timerDeleted) {
+                               if !t.status.CompareAndSwap(timerModifying, timerDeleted) {
                                        badTimer()
                                }
                                releasem(mp)
@@ -336,11 +337,11 @@ func deltimer(t *timer) bool {
                        // Prevent preemption while the timer is in timerModifying.
                        // This could lead to a self-deadlock. See #38070.
                        mp := acquirem()
-                       if atomic.Cas(&t.status, s, timerModifying) {
+                       if t.status.CompareAndSwap(s, timerModifying) {
                                // Must fetch t.pp before setting status
                                // to timerDeleted.
                                tpp := t.pp.ptr()
-                               if !atomic.Cas(&t.status, timerModifying, timerDeleted) {
+                               if !t.status.CompareAndSwap(timerModifying, timerDeleted) {
                                        badTimer()
                                }
                                releasem(mp)
@@ -449,12 +450,12 @@ func modtimer(t *timer, when, period int64, f func(any, uintptr), arg any, seq u
        var mp *m
 loop:
        for {
-               switch status = atomic.Load(&t.status); status {
+               switch status = t.status.Load(); status {
                case timerWaiting, timerModifiedEarlier, timerModifiedLater:
                        // Prevent preemption while the timer is in timerModifying.
                        // This could lead to a self-deadlock. See #38070.
                        mp = acquirem()
-                       if atomic.Cas(&t.status, status, timerModifying) {
+                       if t.status.CompareAndSwap(status, timerModifying) {
                                pending = true // timer not yet run
                                break loop
                        }
@@ -466,7 +467,7 @@ loop:
 
                        // Timer was already run and t is no longer in a heap.
                        // Act like addtimer.
-                       if atomic.Cas(&t.status, status, timerModifying) {
+                       if t.status.CompareAndSwap(status, timerModifying) {
                                wasRemoved = true
                                pending = false // timer already run or stopped
                                break loop
@@ -476,7 +477,7 @@ loop:
                        // Prevent preemption while the timer is in timerModifying.
                        // This could lead to a self-deadlock. See #38070.
                        mp = acquirem()
-                       if atomic.Cas(&t.status, status, timerModifying) {
+                       if t.status.CompareAndSwap(status, timerModifying) {
                                t.pp.ptr().deletedTimers.Add(-1)
                                pending = false // timer already stopped
                                break loop
@@ -506,7 +507,7 @@ loop:
                lock(&pp.timersLock)
                doaddtimer(pp, t)
                unlock(&pp.timersLock)
-               if !atomic.Cas(&t.status, timerModifying, timerWaiting) {
+               if !t.status.CompareAndSwap(timerModifying, timerWaiting) {
                        badTimer()
                }
                releasem(mp)
@@ -531,7 +532,7 @@ loop:
                }
 
                // Set the new status of the timer.
-               if !atomic.Cas(&t.status, timerModifying, newStatus) {
+               if !t.status.CompareAndSwap(timerModifying, newStatus) {
                        badTimer()
                }
                releasem(mp)
@@ -577,18 +578,18 @@ func cleantimers(pp *p) {
                if t.pp.ptr() != pp {
                        throw("cleantimers: bad p")
                }
-               switch s := atomic.Load(&t.status); s {
+               switch s := t.status.Load(); s {
                case timerDeleted:
-                       if !atomic.Cas(&t.status, s, timerRemoving) {
+                       if !t.status.CompareAndSwap(s, timerRemoving) {
                                continue
                        }
                        dodeltimer0(pp)
-                       if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
+                       if !t.status.CompareAndSwap(timerRemoving, timerRemoved) {
                                badTimer()
                        }
                        pp.deletedTimers.Add(-1)
                case timerModifiedEarlier, timerModifiedLater:
-                       if !atomic.Cas(&t.status, s, timerMoving) {
+                       if !t.status.CompareAndSwap(s, timerMoving) {
                                continue
                        }
                        // Now we can change the when field.
@@ -596,7 +597,7 @@ func cleantimers(pp *p) {
                        // Move t to the right position.
                        dodeltimer0(pp)
                        doaddtimer(pp, t)
-                       if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
+                       if !t.status.CompareAndSwap(timerMoving, timerWaiting) {
                                badTimer()
                        }
                default:
@@ -614,30 +615,30 @@ func moveTimers(pp *p, timers []*timer) {
        for _, t := range timers {
        loop:
                for {
-                       switch s := atomic.Load(&t.status); s {
+                       switch s := t.status.Load(); s {
                        case timerWaiting:
-                               if !atomic.Cas(&t.status, s, timerMoving) {
+                               if !t.status.CompareAndSwap(s, timerMoving) {
                                        continue
                                }
                                t.pp = 0
                                doaddtimer(pp, t)
-                               if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
+                               if !t.status.CompareAndSwap(timerMoving, timerWaiting) {
                                        badTimer()
                                }
                                break loop
                        case timerModifiedEarlier, timerModifiedLater:
-                               if !atomic.Cas(&t.status, s, timerMoving) {
+                               if !t.status.CompareAndSwap(s, timerMoving) {
                                        continue
                                }
                                t.when = t.nextwhen
                                t.pp = 0
                                doaddtimer(pp, t)
-                               if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
+                               if !t.status.CompareAndSwap(timerMoving, timerWaiting) {
                                        badTimer()
                                }
                                break loop
                        case timerDeleted:
-                               if !atomic.Cas(&t.status, s, timerRemoved) {
+                               if !t.status.CompareAndSwap(s, timerRemoved) {
                                        continue
                                }
                                t.pp = 0
@@ -688,11 +689,11 @@ func adjusttimers(pp *p, now int64) {
                if t.pp.ptr() != pp {
                        throw("adjusttimers: bad p")
                }
-               switch s := atomic.Load(&t.status); s {
+               switch s := t.status.Load(); s {
                case timerDeleted:
-                       if atomic.Cas(&t.status, s, timerRemoving) {
+                       if t.status.CompareAndSwap(s, timerRemoving) {
                                changed := dodeltimer(pp, i)
-                               if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
+                               if !t.status.CompareAndSwap(timerRemoving, timerRemoved) {
                                        badTimer()
                                }
                                pp.deletedTimers.Add(-1)
@@ -701,7 +702,7 @@ func adjusttimers(pp *p, now int64) {
                                i = changed - 1
                        }
                case timerModifiedEarlier, timerModifiedLater:
-                       if atomic.Cas(&t.status, s, timerMoving) {
+                       if t.status.CompareAndSwap(s, timerMoving) {
                                // Now we can change the when field.
                                t.when = t.nextwhen
                                // Take t off the heap, and hold onto it.
@@ -741,7 +742,7 @@ func adjusttimers(pp *p, now int64) {
 func addAdjustedTimers(pp *p, moved []*timer) {
        for _, t := range moved {
                doaddtimer(pp, t)
-               if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
+               if !t.status.CompareAndSwap(timerMoving, timerWaiting) {
                        badTimer()
                }
        }
@@ -776,14 +777,14 @@ func runtimer(pp *p, now int64) int64 {
                if t.pp.ptr() != pp {
                        throw("runtimer: bad p")
                }
-               switch s := atomic.Load(&t.status); s {
+               switch s := t.status.Load(); s {
                case timerWaiting:
                        if t.when > now {
                                // Not ready to run.
                                return t.when
                        }
 
-                       if !atomic.Cas(&t.status, s, timerRunning) {
+                       if !t.status.CompareAndSwap(s, timerRunning) {
                                continue
                        }
                        // Note that runOneTimer may temporarily unlock
@@ -792,11 +793,11 @@ func runtimer(pp *p, now int64) int64 {
                        return 0
 
                case timerDeleted:
-                       if !atomic.Cas(&t.status, s, timerRemoving) {
+                       if !t.status.CompareAndSwap(s, timerRemoving) {
                                continue
                        }
                        dodeltimer0(pp)
-                       if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
+                       if !t.status.CompareAndSwap(timerRemoving, timerRemoved) {
                                badTimer()
                        }
                        pp.deletedTimers.Add(-1)
@@ -805,13 +806,13 @@ func runtimer(pp *p, now int64) int64 {
                        }
 
                case timerModifiedEarlier, timerModifiedLater:
-                       if !atomic.Cas(&t.status, s, timerMoving) {
+                       if !t.status.CompareAndSwap(s, timerMoving) {
                                continue
                        }
                        t.when = t.nextwhen
                        dodeltimer0(pp)
                        doaddtimer(pp, t)
-                       if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
+                       if !t.status.CompareAndSwap(timerMoving, timerWaiting) {
                                badTimer()
                        }
 
@@ -858,14 +859,14 @@ func runOneTimer(pp *p, t *timer, now int64) {
                        t.when = maxWhen
                }
                siftdownTimer(pp.timers, 0)
-               if !atomic.Cas(&t.status, timerRunning, timerWaiting) {
+               if !t.status.CompareAndSwap(timerRunning, timerWaiting) {
                        badTimer()
                }
                updateTimer0When(pp)
        } else {
                // Remove from heap.
                dodeltimer0(pp)
-               if !atomic.Cas(&t.status, timerRunning, timerNoStatus) {
+               if !t.status.CompareAndSwap(timerRunning, timerNoStatus) {
                        badTimer()
                }
        }
@@ -912,7 +913,7 @@ func clearDeletedTimers(pp *p) {
 nextTimer:
        for _, t := range timers {
                for {
-                       switch s := atomic.Load(&t.status); s {
+                       switch s := t.status.Load(); s {
                        case timerWaiting:
                                if changedHeap {
                                        timers[to] = t
@@ -921,22 +922,22 @@ nextTimer:
                                to++
                                continue nextTimer
                        case timerModifiedEarlier, timerModifiedLater:
-                               if atomic.Cas(&t.status, s, timerMoving) {
+                               if t.status.CompareAndSwap(s, timerMoving) {
                                        t.when = t.nextwhen
                                        timers[to] = t
                                        siftupTimer(timers, to)
                                        to++
                                        changedHeap = true
-                                       if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
+                                       if !t.status.CompareAndSwap(timerMoving, timerWaiting) {
                                                badTimer()
                                        }
                                        continue nextTimer
                                }
                        case timerDeleted:
-                               if atomic.Cas(&t.status, s, timerRemoving) {
+                               if t.status.CompareAndSwap(s, timerRemoving) {
                                        t.pp = 0
                                        cdel++
-                                       if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
+                                       if !t.status.CompareAndSwap(timerRemoving, timerRemoved) {
                                                badTimer()
                                        }
                                        changedHeap = true