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 5 package 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 21 struct tracebackArg { 22 uintptr_t Context; 23 uintptr_t SigContext; 24 uintptr_t* Buf; 25 uintptr_t Max; 26 }; 27 28 void tsanTraceback(struct tracebackArg *arg) { 29 arg->Buf[0] = 0; 30 } 31 32 static 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 61 static 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 */ 76 import "C" 77 78 import ( 79 "io" 80 "runtime" 81 "runtime/pprof" 82 "unsafe" 83 ) 84 85 func 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