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 // +build !plan9,!windows 6 7 package main 8 9 /* 10 #include <pthread.h> 11 12 void go_callback(); 13 14 static void *thr(void *arg) { 15 go_callback(); 16 return 0; 17 } 18 19 static void foo() { 20 pthread_t th; 21 pthread_attr_t attr; 22 pthread_attr_init(&attr); 23 pthread_attr_setstacksize(&attr, 256 << 10); 24 pthread_create(&th, &attr, thr, 0); 25 pthread_join(th, 0); 26 } 27 */ 28 import "C" 29 30 import ( 31 "fmt" 32 "runtime" 33 ) 34 35 func init() { 36 register("CgoCallbackGC", CgoCallbackGC) 37 } 38 39 //export go_callback 40 func go_callback() { 41 runtime.GC() 42 grow() 43 runtime.GC() 44 } 45 46 var cnt int 47 48 func grow() { 49 x := 10000 50 sum := 0 51 if grow1(&x, &sum) == 0 { 52 panic("bad") 53 } 54 } 55 56 func grow1(x, sum *int) int { 57 if *x == 0 { 58 return *sum + 1 59 } 60 *x-- 61 sum1 := *sum + *x 62 return grow1(x, &sum1) 63 } 64 65 func CgoCallbackGC() { 66 const P = 100 67 done := make(chan bool) 68 // allocate a bunch of stack frames and spray them with pointers 69 for i := 0; i < P; i++ { 70 go func() { 71 grow() 72 done <- true 73 }() 74 } 75 for i := 0; i < P; i++ { 76 <-done 77 } 78 // now give these stack frames to cgo callbacks 79 for i := 0; i < P; i++ { 80 go func() { 81 C.foo() 82 done <- true 83 }() 84 } 85 for i := 0; i < P; i++ { 86 <-done 87 } 88 fmt.Printf("OK\n") 89 } 90