github.com/s1s1ty/go@v0.0.0-20180207192209-104445e3140f/src/runtime/testdata/testprogcgo/numgoroutine.go (about)

     1  // Copyright 2017 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 <stddef.h>
    11  #include <pthread.h>
    12  
    13  extern void CallbackNumGoroutine();
    14  
    15  static void* thread2(void* arg __attribute__ ((unused))) {
    16  	CallbackNumGoroutine();
    17  	return NULL;
    18  }
    19  
    20  static void CheckNumGoroutine() {
    21  	pthread_t tid;
    22  	pthread_create(&tid, NULL, thread2, NULL);
    23  	pthread_join(tid, NULL);
    24  }
    25  */
    26  import "C"
    27  
    28  import (
    29  	"fmt"
    30  	"runtime"
    31  	"strings"
    32  )
    33  
    34  var baseGoroutines int
    35  
    36  func init() {
    37  	register("NumGoroutine", NumGoroutine)
    38  }
    39  
    40  func NumGoroutine() {
    41  	// Test that there are just the expected number of goroutines
    42  	// running. Specifically, test that the spare M's goroutine
    43  	// doesn't show up.
    44  	//
    45  	// On non-Windows platforms there's a signal handling thread
    46  	// started by os/signal.init in addition to the main
    47  	// goroutine.
    48  	if runtime.GOOS != "windows" {
    49  		baseGoroutines = 1
    50  	}
    51  	if _, ok := checkNumGoroutine("first", 1+baseGoroutines); !ok {
    52  		return
    53  	}
    54  
    55  	// Test that the goroutine for a callback from C appears.
    56  	if C.CheckNumGoroutine(); !callbackok {
    57  		return
    58  	}
    59  
    60  	// Make sure we're back to the initial goroutines.
    61  	if _, ok := checkNumGoroutine("third", 1+baseGoroutines); !ok {
    62  		return
    63  	}
    64  
    65  	fmt.Println("OK")
    66  }
    67  
    68  func checkNumGoroutine(label string, want int) (string, bool) {
    69  	n := runtime.NumGoroutine()
    70  	if n != want {
    71  		fmt.Printf("%s NumGoroutine: want %d; got %d\n", label, want, n)
    72  		return "", false
    73  	}
    74  
    75  	sbuf := make([]byte, 32<<10)
    76  	sbuf = sbuf[:runtime.Stack(sbuf, true)]
    77  	n = strings.Count(string(sbuf), "goroutine ")
    78  	if n != want {
    79  		fmt.Printf("%s Stack: want %d; got %d:\n%s\n", label, want, n, string(sbuf))
    80  		return "", false
    81  	}
    82  	return string(sbuf), true
    83  }
    84  
    85  var callbackok bool
    86  
    87  //export CallbackNumGoroutine
    88  func CallbackNumGoroutine() {
    89  	stk, ok := checkNumGoroutine("second", 2+baseGoroutines)
    90  	if !ok {
    91  		return
    92  	}
    93  	if !strings.Contains(stk, "CallbackNumGoroutine") {
    94  		fmt.Printf("missing CallbackNumGoroutine from stack:\n%s\n", stk)
    95  		return
    96  	}
    97  
    98  	callbackok = true
    99  }