--- /dev/null
+// 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()
+}
//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
}
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)