1// run
2
3// Copyright 2023 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7package main
8
9import (
10	"sync"
11	"time"
12)
13
14type B struct {
15	pid int
16	f   func() (uint64, error)
17	wg  sync.WaitGroup
18	v   uint64
19}
20
21func newB(pid int) *B {
22	return &B{
23		pid: pid,
24	}
25}
26
27//go:noinline
28func Sq(i int) uint64 {
29	S++
30	return uint64(i * i)
31}
32
33type RO func(*B)
34
35var ROSL = []RO{
36	Bad(),
37}
38
39func Bad() RO {
40	return func(b *B) {
41		b.f = func() (uint64, error) {
42			return Sq(b.pid), nil
43		}
44	}
45}
46
47func (b *B) startit() chan<- struct{} {
48	stop := make(chan struct{})
49	b.wg.Add(1)
50	go func() {
51		defer b.wg.Done()
52		var v uint64
53		for {
54			select {
55			case <-stop:
56				b.v = v
57				return
58			case <-time.After(1 * time.Millisecond):
59				r, err := b.f()
60				if err != nil {
61					panic("bad")
62				}
63				v = r
64			}
65		}
66	}()
67	return stop
68}
69
70var S, G int
71
72//go:noinline
73func rec(x int) int {
74	if x == 0 {
75		return 9
76	}
77	return rec(x-1) + 1
78}
79
80//go:noinline
81func recur(x int) {
82	for i := 0; i < x; i++ {
83		G = rec(i)
84	}
85}
86
87func main() {
88	b := newB(17)
89	for _, opt := range ROSL {
90		opt(b)
91	}
92	stop := b.startit()
93
94	// see if we can get some stack growth/moving
95	recur(10101)
96
97	if stop != nil {
98		stop <- struct{}{}
99	}
100}
101