Skip to content

Commit 94f4686

Browse files
runtime: use current P's race context in timer code
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Keith Randall <[email protected]> Reviewed-by: Michael Knyszek <[email protected]>
1 parent a18608a commit 94f4686

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

src/runtime/race/timer_test.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2019 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// +build race
6+
7+
package race_test
8+
9+
import (
10+
"sync"
11+
"testing"
12+
"time"
13+
)
14+
15+
func TestTimers(t *testing.T) {
16+
const goroutines = 8
17+
var wg sync.WaitGroup
18+
wg.Add(goroutines)
19+
var mu sync.Mutex
20+
for i := 0; i < goroutines; i++ {
21+
go func() {
22+
defer wg.Done()
23+
ticker := time.NewTicker(1)
24+
defer ticker.Stop()
25+
for c := 0; c < 1000; c++ {
26+
<-ticker.C
27+
mu.Lock()
28+
mu.Unlock()
29+
}
30+
}()
31+
}
32+
wg.Wait()
33+
}

src/runtime/time.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -805,10 +805,11 @@ func runtimer(pp *p, now int64) int64 {
805805
//go:systemstack
806806
func runOneTimer(pp *p, t *timer, now int64) {
807807
if raceenabled {
808-
if pp.timerRaceCtx == 0 {
809-
pp.timerRaceCtx = racegostart(funcPC(runtimer) + sys.PCQuantum)
808+
ppcur := getg().m.p.ptr()
809+
if ppcur.timerRaceCtx == 0 {
810+
ppcur.timerRaceCtx = racegostart(funcPC(runtimer) + sys.PCQuantum)
810811
}
811-
raceacquirectx(pp.timerRaceCtx, unsafe.Pointer(t))
812+
raceacquirectx(ppcur.timerRaceCtx, unsafe.Pointer(t))
812813
}
813814

814815
f := t.f
@@ -836,12 +837,12 @@ func runOneTimer(pp *p, t *timer, now int64) {
836837
}
837838

838839
if raceenabled {
839-
// Temporarily use the P's racectx for g0.
840+
// Temporarily use the current P's racectx for g0.
840841
gp := getg()
841842
if gp.racectx != 0 {
842843
throw("runOneTimer: unexpected racectx")
843844
}
844-
gp.racectx = pp.timerRaceCtx
845+
gp.racectx = gp.m.p.ptr().timerRaceCtx
845846
}
846847

847848
unlock(&pp.timersLock)

0 commit comments

Comments
 (0)