github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/runtime/testdata/testprogcgo/callback.go (about) 1 // Copyright 2015 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 //go:build !plan9 && !windows 6 // +build !plan9,!windows 7 8 package main 9 10 /* 11 #include <pthread.h> 12 13 void go_callback(); 14 15 static void *thr(void *arg) { 16 go_callback(); 17 return 0; 18 } 19 20 static void foo() { 21 pthread_t th; 22 pthread_attr_t attr; 23 pthread_attr_init(&attr); 24 pthread_attr_setstacksize(&attr, 256 << 10); 25 pthread_create(&th, &attr, thr, 0); 26 pthread_join(th, 0); 27 } 28 */ 29 import "C" 30 31 import ( 32 "fmt" 33 "os" 34 "runtime" 35 "sync/atomic" 36 _ "unsafe" // for go:linkname 37 ) 38 39 func init() { 40 register("CgoCallbackGC", CgoCallbackGC) 41 } 42 43 //export go_callback 44 func go_callback() { 45 if e := extraMInUse.Load(); e == 0 { 46 fmt.Printf("in callback extraMInUse got %d want >0\n", e) 47 os.Exit(1) 48 } 49 50 runtime.GC() 51 grow() 52 runtime.GC() 53 } 54 55 var cnt int 56 57 func grow() { 58 x := 10000 59 sum := 0 60 if grow1(&x, &sum) == 0 { 61 panic("bad") 62 } 63 } 64 65 func grow1(x, sum *int) int { 66 if *x == 0 { 67 return *sum + 1 68 } 69 *x-- 70 sum1 := *sum + *x 71 return grow1(x, &sum1) 72 } 73 74 func CgoCallbackGC() { 75 P := 100 76 if os.Getenv("RUNTIME_TEST_SHORT") != "" { 77 P = 10 78 } 79 80 if e := extraMInUse.Load(); e != 0 { 81 fmt.Printf("before testing extraMInUse got %d want 0\n", e) 82 os.Exit(1) 83 } 84 85 done := make(chan bool) 86 // allocate a bunch of stack frames and spray them with pointers 87 for i := 0; i < P; i++ { 88 go func() { 89 grow() 90 done <- true 91 }() 92 } 93 for i := 0; i < P; i++ { 94 <-done 95 } 96 // now give these stack frames to cgo callbacks 97 for i := 0; i < P; i++ { 98 go func() { 99 C.foo() 100 done <- true 101 }() 102 } 103 for i := 0; i < P; i++ { 104 <-done 105 } 106 107 if e := extraMInUse.Load(); e != 0 { 108 fmt.Printf("after testing extraMInUse got %d want 0\n", e) 109 os.Exit(1) 110 } 111 112 fmt.Printf("OK\n") 113 } 114 115 //go:linkname extraMInUse runtime.extraMInUse 116 var extraMInUse atomic.Uint32