]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: leave cleantimers early if G is being preempted
authorIan Lance Taylor <iant@golang.org>
Thu, 12 Mar 2020 05:03:50 +0000 (22:03 -0700)
committerIan Lance Taylor <iant@golang.org>
Thu, 12 Mar 2020 23:17:02 +0000 (23:17 +0000)
The cleantimers can run for a while in some unlikely cases.
If the GC is trying to preempt the G, it is forced to wait as the
G is holding timersLock. To avoid introducing a GC delay,
return from cleantimers if the G has a preemption request.

Fixes #37779

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

index 155e0501fe64601fd1fe2764aca27e9d3a9164ae..c62207d7f7b133533ffd67b80976b8ed749ffdfe 100644 (file)
@@ -499,10 +499,20 @@ func resettimer(t *timer, when int64) {
 // slows down addtimer. Reports whether no timer problems were found.
 // The caller must have locked the timers for pp.
 func cleantimers(pp *p) {
+       gp := getg()
        for {
                if len(pp.timers) == 0 {
                        return
                }
+
+               // This loop can theoretically run for a while, and because
+               // it is holding timersLock it cannot be preempted.
+               // If someone is trying to preempt us, just return.
+               // We can clean the timers later.
+               if gp.preemptStop {
+                       return
+               }
+
                t := pp.timers[0]
                if t.pp.ptr() != pp {
                        throw("cleantimers: bad p")