| // run | |
| // Copyright 2023 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 ( | |
| "sync" | |
| "time" | |
| ) | |
| type B struct { | |
| pid int | |
| f func() (uint64, error) | |
| wg sync.WaitGroup | |
| v uint64 | |
| } | |
| func newB(pid int) *B { | |
| return &B{ | |
| pid: pid, | |
| } | |
| } | |
| //go:noinline | |
| func Sq(i int) uint64 { | |
| S++ | |
| return uint64(i * i) | |
| } | |
| type RO func(*B) | |
| var ROSL = []RO{ | |
| Bad(), | |
| } | |
| func Bad() RO { | |
| return func(b *B) { | |
| b.f = func() (uint64, error) { | |
| return Sq(b.pid), nil | |
| } | |
| } | |
| } | |
| func (b *B) startit() chan<- struct{} { | |
| stop := make(chan struct{}) | |
| b.wg.Add(1) | |
| go func() { | |
| defer b.wg.Done() | |
| var v uint64 | |
| for { | |
| select { | |
| case <-stop: | |
| b.v = v | |
| return | |
| case <-time.After(1 * time.Millisecond): | |
| r, err := b.f() | |
| if err != nil { | |
| panic("bad") | |
| } | |
| v = r | |
| } | |
| } | |
| }() | |
| return stop | |
| } | |
| var S, G int | |
| //go:noinline | |
| func rec(x int) int { | |
| if x == 0 { | |
| return 9 | |
| } | |
| return rec(x-1) + 1 | |
| } | |
| //go:noinline | |
| func recur(x int) { | |
| for i := 0; i < x; i++ { | |
| G = rec(i) | |
| } | |
| } | |
| func main() { | |
| b := newB(17) | |
| for _, opt := range ROSL { | |
| opt(b) | |
| } | |
| stop := b.startit() | |
| // see if we can get some stack growth/moving | |
| recur(10101) | |
| if stop != nil { | |
| stop <- struct{}{} | |
| } | |
| } |