aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/runtime/export_test.go2
-rw-r--r--src/runtime/proc_test.go11
-rw-r--r--src/runtime/testdata/testprog/preempt.go44
3 files changed, 57 insertions, 0 deletions
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index 831f3f13d4..3c1b4db750 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -42,6 +42,8 @@ var PhysHugePageSize = physHugePageSize
var NetpollGenericInit = netpollGenericInit
+const PreemptMSupported = preemptMSupported
+
type LFNode struct {
Next uint64
Pushcnt uintptr
diff --git a/src/runtime/proc_test.go b/src/runtime/proc_test.go
index 9b80ce31e5..acee7a1819 100644
--- a/src/runtime/proc_test.go
+++ b/src/runtime/proc_test.go
@@ -356,6 +356,17 @@ func TestPreemptionGC(t *testing.T) {
atomic.StoreUint32(&stop, 1)
}
+func TestAsyncPreempt(t *testing.T) {
+ if !runtime.PreemptMSupported {
+ t.Skip("asynchronous preemption not supported on this platform")
+ }
+ output := runTestProg(t, "testprog", "AsyncPreempt")
+ want := "OK\n"
+ if output != want {
+ t.Fatalf("want %s, got %s\n", want, output)
+ }
+}
+
func TestGCFairness(t *testing.T) {
output := runTestProg(t, "testprog", "GCFairness")
want := "OK\n"
diff --git a/src/runtime/testdata/testprog/preempt.go b/src/runtime/testdata/testprog/preempt.go
new file mode 100644
index 0000000000..cf004fcb28
--- /dev/null
+++ b/src/runtime/testdata/testprog/preempt.go
@@ -0,0 +1,44 @@
+// 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.
+
+package main
+
+import (
+ "runtime"
+ "runtime/debug"
+ "sync/atomic"
+)
+
+func init() {
+ register("AsyncPreempt", AsyncPreempt)
+}
+
+func AsyncPreempt() {
+ // Run with just 1 GOMAXPROCS so the runtime is required to
+ // use scheduler preemption.
+ runtime.GOMAXPROCS(1)
+ // Disable GC so we have complete control of what we're testing.
+ debug.SetGCPercent(-1)
+
+ // Start a goroutine with no sync safe-points.
+ var ready uint32
+ go func() {
+ for {
+ atomic.StoreUint32(&ready, 1)
+ }
+ }()
+
+ // Wait for the goroutine to stop passing through sync
+ // safe-points.
+ for atomic.LoadUint32(&ready) == 0 {
+ runtime.Gosched()
+ }
+
+ // Run a GC, which will have to stop the goroutine for STW and
+ // for stack scanning. If this doesn't work, the test will
+ // deadlock and timeout.
+ runtime.GC()
+
+ println("OK")
+}