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 8package 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 21struct cgoTracebackArg { 22 uintptr_t context; 23 uintptr_t sigContext; 24 uintptr_t* buf; 25 uintptr_t max; 26}; 27 28static 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. 34void 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 41static 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 51void runRaceprofThread() { 52 pthread_t tid; 53 pthread_create(&tid, 0, raceprofThread, 0); 54 pthread_join(tid, 0); 55} 56*/ 57import "C" 58 59import ( 60 "bytes" 61 "fmt" 62 "runtime" 63 "runtime/pprof" 64 "unsafe" 65) 66 67func init() { 68 register("CgoRaceprof", CgoRaceprof) 69} 70 71func 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