mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
TestNetpollBreak was sometimes timing out on Plan 9, where netpoll_stub.go implements only enough of the network poller to support runtime timers, using a notetsleep / notewakeup pair. The runtime.lock which serialises the use of the note doesn't guarantee fairness, and in practice the netpoll call used by the test can be starved by the netpoll call from the scheduler which supports the overall 'go test' timeout. Calling osyield after relinquishing the lock gives the two callers a more even chance to take a turn, which prevents the test from timing out. Fixes #39437 Change-Id: Ifbe6aaf95336d162d9d0b6deba19b8debf17b071 Reviewed-on: https://go-review.googlesource.com/c/go/+/237698 Run-TryBot: David du Colombier <0intro@gmail.com> Reviewed-by: Ian Lance Taylor <iant@golang.org>
61 lines
1.4 KiB
Go
61 lines
1.4 KiB
Go
// Copyright 2013 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 plan9
|
|
|
|
package runtime
|
|
|
|
import "runtime/internal/atomic"
|
|
|
|
var netpollInited uint32
|
|
var netpollWaiters uint32
|
|
|
|
var netpollStubLock mutex
|
|
var netpollNote note
|
|
|
|
// netpollBroken, protected by netpollBrokenLock, avoids a double notewakeup.
|
|
var netpollBrokenLock mutex
|
|
var netpollBroken bool
|
|
|
|
func netpollGenericInit() {
|
|
atomic.Store(&netpollInited, 1)
|
|
}
|
|
|
|
func netpollBreak() {
|
|
lock(&netpollBrokenLock)
|
|
broken := netpollBroken
|
|
netpollBroken = true
|
|
if !broken {
|
|
notewakeup(&netpollNote)
|
|
}
|
|
unlock(&netpollBrokenLock)
|
|
}
|
|
|
|
// Polls for ready network connections.
|
|
// Returns list of goroutines that become runnable.
|
|
func netpoll(delay int64) gList {
|
|
// Implementation for platforms that do not support
|
|
// integrated network poller.
|
|
if delay != 0 {
|
|
// This lock ensures that only one goroutine tries to use
|
|
// the note. It should normally be completely uncontended.
|
|
lock(&netpollStubLock)
|
|
|
|
lock(&netpollBrokenLock)
|
|
noteclear(&netpollNote)
|
|
netpollBroken = false
|
|
unlock(&netpollBrokenLock)
|
|
|
|
notetsleep(&netpollNote, delay)
|
|
unlock(&netpollStubLock)
|
|
// Guard against starvation in case the lock is contended
|
|
// (eg when running TestNetpollBreak).
|
|
osyield()
|
|
}
|
|
return gList{}
|
|
}
|
|
|
|
func netpollinited() bool {
|
|
return atomic.Load(&netpollInited) != 0
|
|
}
|