File size: 1,653 Bytes
e36aeda | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | // 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)
// Out of an abundance of caution, also make sure that there are
// no GCs actively in progress. The sweep phase of a GC cycle
// for instance tries to preempt Ps at the very beginning.
runtime.GC()
// Start a goroutine with no sync safe-points.
var ready, ready2 uint32
go func() {
for {
atomic.StoreUint32(&ready, 1)
dummy()
dummy()
}
}()
// Also start one with a frameless function.
// This is an especially interesting case for
// LR machines.
go func() {
atomic.AddUint32(&ready2, 1)
frameless()
}()
// Also test empty infinite loop.
go func() {
atomic.AddUint32(&ready2, 1)
for {
}
}()
// Wait for the goroutine to stop passing through sync
// safe-points.
for atomic.LoadUint32(&ready) == 0 || atomic.LoadUint32(&ready2) < 2 {
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")
}
//go:noinline
func frameless() {
for i := int64(0); i < 1<<62; i++ {
out += i * i * i * i * i * 12345
}
}
var out int64
//go:noinline
func dummy() {}
|