1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "runtime" 9 "runtime/debug" 10 "sync/atomic" 11 ) 12 13 func init() { 14 register("AsyncPreempt", AsyncPreempt) 15 } 16 17 func AsyncPreempt() { 18 // Run with just 1 GOMAXPROCS so the runtime is required to 19 // use scheduler preemption. 20 runtime.GOMAXPROCS(1) 21 // Disable GC so we have complete control of what we're testing. 22 debug.SetGCPercent(-1) 23 // Out of an abundance of caution, also make sure that there are 24 // no GCs actively in progress. The sweep phase of a GC cycle 25 // for instance tries to preempt Ps at the very beginning. 26 runtime.GC() 27 28 // Start a goroutine with no sync safe-points. 29 var ready, ready2 uint32 30 go func() { 31 for { 32 atomic.StoreUint32(&ready, 1) 33 dummy() 34 dummy() 35 } 36 }() 37 // Also start one with a frameless function. 38 // This is an especially interesting case for 39 // LR machines. 40 go func() { 41 atomic.AddUint32(&ready2, 1) 42 frameless() 43 }() 44 // Also test empty infinite loop. 45 go func() { 46 atomic.AddUint32(&ready2, 1) 47 for { 48 } 49 }() 50 51 // Wait for the goroutine to stop passing through sync 52 // safe-points. 53 for atomic.LoadUint32(&ready) == 0 || atomic.LoadUint32(&ready2) < 2 { 54 runtime.Gosched() 55 } 56 57 // Run a GC, which will have to stop the goroutine for STW and 58 // for stack scanning. If this doesn't work, the test will 59 // deadlock and timeout. 60 runtime.GC() 61 62 println("OK") 63 } 64 65 //go:noinline 66 func frameless() { 67 for i := int64(0); i < 1<<62; i++ { 68 out += i * i * i * i * i * 12345 69 } 70 } 71 72 var out int64 73 74 //go:noinline 75 func dummy() {} 76