• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2023 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
5package main
6
7// This program failed when run under the C/C++ ThreadSanitizer.
8// There was no TSAN synchronization for the call to the cgo
9// traceback routine.
10
11/*
12#cgo CFLAGS: -g -fsanitize=thread
13#cgo LDFLAGS: -g -fsanitize=thread
14
15#include <pthread.h>
16#include <stdint.h>
17#include <stdlib.h>
18#include <sys/time.h>
19#include <unistd.h>
20
21struct tracebackArg {
22	uintptr_t  Context;
23	uintptr_t  SigContext;
24	uintptr_t* Buf;
25	uintptr_t  Max;
26};
27
28void tsanTraceback(struct tracebackArg *arg) {
29	arg->Buf[0] = 0;
30}
31
32static void* spin(void *arg) {
33	size_t n;
34	struct timeval tvstart, tvnow;
35	int diff;
36	void *prev;
37	void *cur;
38
39	prev = NULL;
40	gettimeofday(&tvstart, NULL);
41	for (n = 0; n < 1<<20; n++) {
42		cur = malloc(n);
43		free(prev);
44		prev = cur;
45
46		gettimeofday(&tvnow, NULL);
47		diff = (tvnow.tv_sec - tvstart.tv_sec) * 1000 * 1000 + (tvnow.tv_usec - tvstart.tv_usec);
48
49		// Profile frequency is 100Hz so we should definitely
50		// get some signals in 50 milliseconds.
51		if (diff > 50 * 1000) {
52			break;
53		}
54	}
55
56	free(prev);
57
58	return NULL;
59}
60
61static void runThreads(int n) {
62	pthread_t ids[64];
63	int i;
64
65	if (n > 64) {
66		n = 64;
67	}
68	for (i = 0; i < n; i++) {
69		pthread_create(&ids[i], NULL, spin, NULL);
70	}
71	for (i = 0; i < n; i++) {
72		pthread_join(ids[i], NULL);
73	}
74}
75*/
76import "C"
77
78import (
79	"io"
80	"runtime"
81	"runtime/pprof"
82	"unsafe"
83)
84
85func main() {
86	runtime.SetCgoTraceback(0, unsafe.Pointer(C.tsanTraceback), nil, nil)
87	pprof.StartCPUProfile(io.Discard)
88	C.runThreads(C.int(runtime.GOMAXPROCS(0)))
89	pprof.StopCPUProfile()
90}
91