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