| // Copyright 2016 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. The | |
| // TSAN library was not keeping track of whether signals should be | |
| // delivered on the alternate signal stack, and the Go signal handler | |
| // was not preserving callee-saved registers from C callers. | |
| /* | |
| #cgo CFLAGS: -g -fsanitize=thread | |
| #cgo LDFLAGS: -g -fsanitize=thread | |
| #include <stdlib.h> | |
| #include <sys/time.h> | |
| void spin() { | |
| size_t n; | |
| struct timeval tvstart, tvnow; | |
| int diff; | |
| void *prev = NULL, *cur; | |
| 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 a signal in 50 milliseconds. | |
| if (diff > 50 * 1000) { | |
| break; | |
| } | |
| } | |
| free(prev); | |
| } | |
| */ | |
| import "C" | |
| import ( | |
| "io/ioutil" | |
| "runtime/pprof" | |
| "time" | |
| ) | |
| func goSpin() { | |
| start := time.Now() | |
| for n := 0; n < 1<<20; n++ { | |
| _ = make([]byte, n) | |
| if time.Since(start) > 50*time.Millisecond { | |
| break | |
| } | |
| } | |
| } | |
| func main() { | |
| pprof.StartCPUProfile(ioutil.Discard) | |
| go C.spin() | |
| goSpin() | |
| pprof.StopCPUProfile() | |
| } |