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 //go:build unix 6 // +build unix 7 8 package main 9 10 // Test that we can collect a lot of colliding profiling signals from 11 // an external C thread. This used to fail when built with the race 12 // detector, because a call of the predeclared function copy was 13 // turned into a call to runtime.slicecopy, which is not marked nosplit. 14 15 /* 16 #include <signal.h> 17 #include <stdint.h> 18 #include <pthread.h> 19 #include <sched.h> 20 21 struct cgoTracebackArg { 22 uintptr_t context; 23 uintptr_t sigContext; 24 uintptr_t* buf; 25 uintptr_t max; 26 }; 27 28 static int raceprofCount; 29 30 // We want a bunch of different profile stacks that collide in the 31 // hash table maintained in runtime/cpuprof.go. This code knows the 32 // size of the hash table (1 << 10) and knows that the hash function 33 // is simply multiplicative. 34 void raceprofTraceback(void* parg) { 35 struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg); 36 raceprofCount++; 37 arg->buf[0] = raceprofCount * (1 << 10); 38 arg->buf[1] = 0; 39 } 40 41 static void* raceprofThread(void* p) { 42 int i; 43 44 for (i = 0; i < 100; i++) { 45 pthread_kill(pthread_self(), SIGPROF); 46 sched_yield(); 47 } 48 return 0; 49 } 50 51 void runRaceprofThread() { 52 pthread_t tid; 53 pthread_create(&tid, 0, raceprofThread, 0); 54 pthread_join(tid, 0); 55 } 56 */ 57 import "C" 58 59 import ( 60 "bytes" 61 "fmt" 62 "runtime" 63 "runtime/pprof" 64 "unsafe" 65 ) 66 67 func init() { 68 register("CgoRaceprof", CgoRaceprof) 69 } 70 71 func CgoRaceprof() { 72 runtime.SetCgoTraceback(0, unsafe.Pointer(C.raceprofTraceback), nil, nil) 73 74 var buf bytes.Buffer 75 pprof.StartCPUProfile(&buf) 76 77 C.runRaceprofThread() 78 fmt.Println("OK") 79 } 80