]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use current P's race context in timer code
authorIan Lance Taylor <iant@golang.org>
Mon, 2 Dec 2019 20:07:22 +0000 (12:07 -0800)
committerIan Lance Taylor <iant@golang.org>
Mon, 2 Dec 2019 22:42:22 +0000 (22:42 +0000)
We were using the race context of the P that held the timer,
but since we unlock the P's timers while executing a timer
that could lead to a race on the race context itself.

Updates #6239
Updates #27707
Fixes #35906

Change-Id: I5f9d5f52d8e28dffb88c3327301071b16ed1a913
Reviewed-on: https://go-review.googlesource.com/c/go/+/209580
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/runtime/race/timer_test.go [new file with mode: 0644]
src/runtime/time.go

diff --git a/src/runtime/race/timer_test.go b/src/runtime/race/timer_test.go
new file mode 100644 (file)
index 0000000..a6c34a8
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build race
+
+package race_test
+
+import (
+       "sync"
+       "testing"
+       "time"
+)
+
+func TestTimers(t *testing.T) {
+       const goroutines = 8
+       var wg sync.WaitGroup
+       wg.Add(goroutines)
+       var mu sync.Mutex
+       for i := 0; i < goroutines; i++ {
+               go func() {
+                       defer wg.Done()
+                       ticker := time.NewTicker(1)
+                       defer ticker.Stop()
+                       for c := 0; c < 1000; c++ {
+                               <-ticker.C
+                               mu.Lock()
+                               mu.Unlock()
+                       }
+               }()
+       }
+       wg.Wait()
+}
index a7d14cf8777931b2a9939ba778cb458ef9184564..d64bea814fd82a8e84f399a955bf76d2fd1aefb5 100644 (file)
@@ -805,10 +805,11 @@ func runtimer(pp *p, now int64) int64 {
 //go:systemstack
 func runOneTimer(pp *p, t *timer, now int64) {
        if raceenabled {
-               if pp.timerRaceCtx == 0 {
-                       pp.timerRaceCtx = racegostart(funcPC(runtimer) + sys.PCQuantum)
+               ppcur := getg().m.p.ptr()
+               if ppcur.timerRaceCtx == 0 {
+                       ppcur.timerRaceCtx = racegostart(funcPC(runtimer) + sys.PCQuantum)
                }
-               raceacquirectx(pp.timerRaceCtx, unsafe.Pointer(t))
+               raceacquirectx(ppcur.timerRaceCtx, unsafe.Pointer(t))
        }
 
        f := t.f
@@ -836,12 +837,12 @@ func runOneTimer(pp *p, t *timer, now int64) {
        }
 
        if raceenabled {
-               // Temporarily use the P's racectx for g0.
+               // Temporarily use the current P's racectx for g0.
                gp := getg()
                if gp.racectx != 0 {
                        throw("runOneTimer: unexpected racectx")
                }
-               gp.racectx = pp.timerRaceCtx
+               gp.racectx = gp.m.p.ptr().timerRaceCtx
        }
 
        unlock(&pp.timersLock)