Skip to content

Commit

Permalink
runtime: use current P's race context in timer code
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ianlancetaylor committed Dec 2, 2019
1 parent a18608a commit 94f4686
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 5 deletions.
33 changes: 33 additions & 0 deletions src/runtime/race/timer_test.go
Original file line number Diff line number Diff line change
@@ -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()
}
11 changes: 6 additions & 5 deletions src/runtime/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 94f4686

Please sign in to comment.