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 7package main 8 9/* 10#include <pthread.h> 11 12void go_callback(); 13 14static void *thr(void *arg) { 15 go_callback(); 16 return 0; 17} 18 19static 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*/ 28import "C" 29 30import ( 31 "fmt" 32 "runtime" 33) 34 35func init() { 36 register("CgoCallbackGC", CgoCallbackGC) 37} 38 39//export go_callback 40func go_callback() { 41 runtime.GC() 42 grow() 43 runtime.GC() 44} 45 46var cnt int 47 48func grow() { 49 x := 10000 50 sum := 0 51 if grow1(&x, &sum) == 0 { 52 panic("bad") 53 } 54} 55 56func 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 65func 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