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