github.com/s1s1ty/go@v0.0.0-20180207192209-104445e3140f/src/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  // +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  	"os"
    33  	"runtime"
    34  )
    35  
    36  func init() {
    37  	register("CgoCallbackGC", CgoCallbackGC)
    38  }
    39  
    40  //export go_callback
    41  func go_callback() {
    42  	runtime.GC()
    43  	grow()
    44  	runtime.GC()
    45  }
    46  
    47  var cnt int
    48  
    49  func grow() {
    50  	x := 10000
    51  	sum := 0
    52  	if grow1(&x, &sum) == 0 {
    53  		panic("bad")
    54  	}
    55  }
    56  
    57  func grow1(x, sum *int) int {
    58  	if *x == 0 {
    59  		return *sum + 1
    60  	}
    61  	*x--
    62  	sum1 := *sum + *x
    63  	return grow1(x, &sum1)
    64  }
    65  
    66  func CgoCallbackGC() {
    67  	P := 100
    68  	if os.Getenv("RUNTIME_TESTING_SHORT") != "" {
    69  		P = 10
    70  	}
    71  	done := make(chan bool)
    72  	// allocate a bunch of stack frames and spray them with pointers
    73  	for i := 0; i < P; i++ {
    74  		go func() {
    75  			grow()
    76  			done <- true
    77  		}()
    78  	}
    79  	for i := 0; i < P; i++ {
    80  		<-done
    81  	}
    82  	// now give these stack frames to cgo callbacks
    83  	for i := 0; i < P; i++ {
    84  		go func() {
    85  			C.foo()
    86  			done <- true
    87  		}()
    88  	}
    89  	for i := 0; i < P; i++ {
    90  		<-done
    91  	}
    92  	fmt.Printf("OK\n")
    93  }