// Copyright 2023 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main // This program failed when run under the C/C++ ThreadSanitizer. // There was no TSAN synchronization for the call to the cgo // traceback routine. /* #cgo CFLAGS: -g -fsanitize=thread #cgo LDFLAGS: -g -fsanitize=thread #include #include #include #include #include struct tracebackArg { uintptr_t Context; uintptr_t SigContext; uintptr_t* Buf; uintptr_t Max; }; void tsanTraceback(struct tracebackArg *arg) { arg->Buf[0] = 0; } static void* spin(void *arg) { size_t n; struct timeval tvstart, tvnow; int diff; void *prev; void *cur; prev = NULL; gettimeofday(&tvstart, NULL); for (n = 0; n < 1<<20; n++) { cur = malloc(n); free(prev); prev = cur; gettimeofday(&tvnow, NULL); diff = (tvnow.tv_sec - tvstart.tv_sec) * 1000 * 1000 + (tvnow.tv_usec - tvstart.tv_usec); // Profile frequency is 100Hz so we should definitely // get some signals in 50 milliseconds. if (diff > 50 * 1000) { break; } } free(prev); return NULL; } static void runThreads(int n) { pthread_t ids[64]; int i; if (n > 64) { n = 64; } for (i = 0; i < n; i++) { pthread_create(&ids[i], NULL, spin, NULL); } for (i = 0; i < n; i++) { pthread_join(ids[i], NULL); } } */ import "C" import ( "io" "runtime" "runtime/pprof" "unsafe" ) func main() { runtime.SetCgoTraceback(0, unsafe.Pointer(C.tsanTraceback), nil, nil) pprof.StartCPUProfile(io.Discard) C.runThreads(C.int(runtime.GOMAXPROCS(0))) pprof.StopCPUProfile() }