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