runtime: add netpollBreak

The new netpollBreak function can be used to interrupt a blocking netpoll.
This function is not currently used; it will be used by later CLs.

Updates #27707

Change-Id: I5cb936609ba13c3c127ea1368a49194fc58c9f4d
Reviewed-on: https://go-review.googlesource.com/c/go/+/171824
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
Ian Lance Taylor 2019-04-05 15:53:12 -07:00
parent 33425ab8db
commit 50f4896b72
34 changed files with 322 additions and 53 deletions

View file

@ -981,3 +981,42 @@ func TestPreemptionAfterSyscall(t *testing.T) {
func TestGetgThreadSwitch(t *testing.T) {
runtime.RunGetgThreadSwitchTest()
}
// TestNetpollBreak tests that netpollBreak can break a netpoll.
// This test is not particularly safe since the call to netpoll
// will pick up any stray files that are ready, but it should work
// OK as long it is not run in parallel.
func TestNetpollBreak(t *testing.T) {
if runtime.GOMAXPROCS(0) == 1 {
t.Skip("skipping: GOMAXPROCS=1")
}
// Make sure that netpoll is initialized.
time.Sleep(1)
start := time.Now()
c := make(chan bool, 2)
go func() {
c <- true
runtime.Netpoll(10 * time.Second.Nanoseconds())
c <- true
}()
<-c
// Loop because the break might get eaten by the scheduler.
// Break twice to break both the netpoll we started and the
// scheduler netpoll.
loop:
for {
runtime.Usleep(100)
runtime.NetpollBreak()
runtime.NetpollBreak()
select {
case <-c:
break loop
default:
}
}
if dur := time.Since(start); dur > 5*time.Second {
t.Errorf("netpollBreak did not interrupt netpoll: slept for: %v", dur)
}
}