github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/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  	if _, ok := checkNumGoroutine("first", 1+baseGoroutines); !ok {
    45  		return
    46  	}
    47  
    48  	// Test that the goroutine for a callback from C appears.
    49  	if C.CheckNumGoroutine(); !callbackok {
    50  		return
    51  	}
    52  
    53  	// Make sure we're back to the initial goroutines.
    54  	if _, ok := checkNumGoroutine("third", 1+baseGoroutines); !ok {
    55  		return
    56  	}
    57  
    58  	fmt.Println("OK")
    59  }
    60  
    61  func checkNumGoroutine(label string, want int) (string, bool) {
    62  	n := runtime.NumGoroutine()
    63  	if n != want {
    64  		fmt.Printf("%s NumGoroutine: want %d; got %d\n", label, want, n)
    65  		return "", false
    66  	}
    67  
    68  	sbuf := make([]byte, 32<<10)
    69  	sbuf = sbuf[:runtime.Stack(sbuf, true)]
    70  	n = strings.Count(string(sbuf), "goroutine ")
    71  	if n != want {
    72  		fmt.Printf("%s Stack: want %d; got %d:\n%s\n", label, want, n, string(sbuf))
    73  		return "", false
    74  	}
    75  	return string(sbuf), true
    76  }
    77  
    78  var callbackok bool
    79  
    80  //export CallbackNumGoroutine
    81  func CallbackNumGoroutine() {
    82  	stk, ok := checkNumGoroutine("second", 2+baseGoroutines)
    83  	if !ok {
    84  		return
    85  	}
    86  	if !strings.Contains(stk, "CallbackNumGoroutine") {
    87  		fmt.Printf("missing CallbackNumGoroutine from stack:\n%s\n", stk)
    88  		return
    89  	}
    90  
    91  	callbackok = true
    92  }