github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/runtime/testdata/testprogcgo/threadpprof.go (about) 1 // Copyright 2016 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 // +build !gccgo 7 8 package main 9 10 // Run a slow C function saving a CPU profile. 11 12 /* 13 #include <stdint.h> 14 #include <time.h> 15 #include <pthread.h> 16 17 int threadSalt1; 18 int threadSalt2; 19 20 void cpuHogThread() { 21 int foo = threadSalt1; 22 int i; 23 24 for (i = 0; i < 100000; i++) { 25 if (foo > 0) { 26 foo *= foo; 27 } else { 28 foo *= foo + 1; 29 } 30 } 31 threadSalt2 = foo; 32 } 33 34 void cpuHogThread2() { 35 } 36 37 static int cpuHogThreadCount; 38 39 struct cgoTracebackArg { 40 uintptr_t context; 41 uintptr_t sigContext; 42 uintptr_t* buf; 43 uintptr_t max; 44 }; 45 46 // pprofCgoThreadTraceback is passed to runtime.SetCgoTraceback. 47 // For testing purposes it pretends that all CPU hits in C code are in cpuHog. 48 void pprofCgoThreadTraceback(void* parg) { 49 struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg); 50 arg->buf[0] = (uintptr_t)(cpuHogThread) + 0x10; 51 arg->buf[1] = (uintptr_t)(cpuHogThread2) + 0x4; 52 arg->buf[2] = 0; 53 __atomic_add_fetch(&cpuHogThreadCount, 1, __ATOMIC_SEQ_CST); 54 } 55 56 // getCPUHogThreadCount fetches the number of times we've seen cpuHogThread 57 // in the traceback. 58 int getCPUHogThreadCount() { 59 return __atomic_load(&cpuHogThreadCount, __ATOMIC_SEQ_CST); 60 } 61 62 static void* cpuHogDriver(void* arg __attribute__ ((unused))) { 63 while (1) { 64 cpuHogThread(); 65 } 66 return 0; 67 } 68 69 void runCPUHogThread(void) { 70 pthread_t tid; 71 pthread_create(&tid, 0, cpuHogDriver, 0); 72 } 73 */ 74 import "C" 75 76 import ( 77 "fmt" 78 "io/ioutil" 79 "os" 80 "runtime" 81 "runtime/pprof" 82 "time" 83 "unsafe" 84 ) 85 86 func init() { 87 register("CgoPprofThread", CgoPprofThread) 88 register("CgoPprofThreadNoTraceback", CgoPprofThreadNoTraceback) 89 } 90 91 func CgoPprofThread() { 92 runtime.SetCgoTraceback(0, unsafe.Pointer(C.pprofCgoThreadTraceback), nil, nil) 93 pprofThread() 94 } 95 96 func CgoPprofThreadNoTraceback() { 97 pprofThread() 98 } 99 100 func pprofThread() { 101 f, err := ioutil.TempFile("", "prof") 102 if err != nil { 103 fmt.Fprintln(os.Stderr, err) 104 os.Exit(2) 105 } 106 107 if err := pprof.StartCPUProfile(f); err != nil { 108 fmt.Fprintln(os.Stderr, err) 109 os.Exit(2) 110 } 111 112 C.runCPUHogThread() 113 114 t0 := time.Now() 115 for C.getCPUHogThreadCount() < 2 && time.Since(t0) < time.Second { 116 time.Sleep(100 * time.Millisecond) 117 } 118 119 pprof.StopCPUProfile() 120 121 name := f.Name() 122 if err := f.Close(); err != nil { 123 fmt.Fprintln(os.Stderr, err) 124 os.Exit(2) 125 } 126 127 fmt.Println(name) 128 }