// 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() {}