1
2
3
4
5
6
7
8 package main
9
10
29 import "C"
30
31 import (
32 "fmt"
33 "os"
34 "runtime"
35 "sync/atomic"
36 _ "unsafe"
37 )
38
39 func init() {
40 register("CgoCallbackGC", CgoCallbackGC)
41 register("CgoToGoCallGoexit", CgoToGoCallGoexit)
42 }
43
44 func CgoToGoCallGoexit() {
45 goexit = true
46 C.foo()
47 }
48
49 var goexit = false
50
51
52 func go_callback() {
53 if goexit {
54 runtime.Goexit()
55 }
56 if e := extraMInUse.Load(); e == 0 {
57 fmt.Printf("in callback extraMInUse got %d want >0\n", e)
58 os.Exit(1)
59 }
60
61 runtime.GC()
62 grow()
63 runtime.GC()
64 }
65
66 var cnt int
67
68 func grow() {
69 x := 10000
70 sum := 0
71 if grow1(&x, &sum) == 0 {
72 panic("bad")
73 }
74 }
75
76 func grow1(x, sum *int) int {
77 if *x == 0 {
78 return *sum + 1
79 }
80 *x--
81 sum1 := *sum + *x
82 return grow1(x, &sum1)
83 }
84
85 func CgoCallbackGC() {
86 P := 100
87 if os.Getenv("RUNTIME_TEST_SHORT") != "" {
88 P = 10
89 }
90
91 if e := extraMInUse.Load(); e != 0 {
92 fmt.Printf("before testing extraMInUse got %d want 0\n", e)
93 os.Exit(1)
94 }
95
96 done := make(chan bool)
97
98 for i := 0; i < P; i++ {
99 go func() {
100 grow()
101 done <- true
102 }()
103 }
104 for i := 0; i < P; i++ {
105 <-done
106 }
107
108 for i := 0; i < P; i++ {
109 go func() {
110 C.foo()
111 done <- true
112 }()
113 }
114 for i := 0; i < P; i++ {
115 <-done
116 }
117
118 if e := extraMInUse.Load(); e != 0 {
119 fmt.Printf("after testing extraMInUse got %d want 0\n", e)
120 os.Exit(1)
121 }
122
123 fmt.Printf("OK\n")
124 }
125
126
127 var extraMInUse atomic.Uint32
128
View as plain text