aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorRhys Hiltner <rhys@justin.tv>2021-08-13 08:51:46 -0700
committerMichael Pratt <mpratt@google.com>2021-09-27 18:58:20 +0000
commitf9e90f7e7401b7222ea10420140dc43687e4017f (patch)
treee51340bd926fdcab69e2e966646815d40001bf55 /src/runtime
parent3d795ea798edf0f9da4d2e33e15a58e59aa42e83 (diff)
downloadgo-f9e90f7e7401b7222ea10420140dc43687e4017f.tar.xz
runtime: allow per-OS changes to unix profiler
Updates #35057 Change-Id: I56ea8f4750022847f0866c85e237a2cea40e0ff7 Reviewed-on: https://go-review.googlesource.com/c/go/+/342053 Run-TryBot: Rhys Hiltner <rhys@justin.tv> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com> Trust: Michael Knyszek <mknyszek@google.com>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/os3_solaris.go13
-rw-r--r--src/runtime/os_aix.go13
-rw-r--r--src/runtime/os_darwin.go13
-rw-r--r--src/runtime/os_dragonfly.go13
-rw-r--r--src/runtime/os_freebsd.go13
-rw-r--r--src/runtime/os_linux.go16
-rw-r--r--src/runtime/os_netbsd.go13
-rw-r--r--src/runtime/os_openbsd.go13
-rw-r--r--src/runtime/signal_unix.go25
9 files changed, 124 insertions, 8 deletions
diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go
index 84194a3050..3149d13869 100644
--- a/src/runtime/os3_solaris.go
+++ b/src/runtime/os3_solaris.go
@@ -289,6 +289,19 @@ func sigdelset(mask *sigset, i int) {
func (c *sigctxt) fixsigcode(sig uint32) {
}
+func setProcessCPUProfiler(hz int32) {
+ setProcessCPUProfilerTimer(hz)
+}
+
+func setThreadCPUProfiler(hz int32) {
+ setThreadCPUProfilerHz(hz)
+}
+
+//go:nosplit
+func validSIGPROF(mp *m, c *sigctxt) bool {
+ return true
+}
+
//go:nosplit
func semacreate(mp *m) {
if mp.waitsema != 0 {
diff --git a/src/runtime/os_aix.go b/src/runtime/os_aix.go
index 478dde2fc3..54e0cfbb8d 100644
--- a/src/runtime/os_aix.go
+++ b/src/runtime/os_aix.go
@@ -323,6 +323,19 @@ func sigdelset(mask *sigset, i int) {
(*mask)[(i-1)/64] &^= 1 << ((uint32(i) - 1) & 63)
}
+func setProcessCPUProfiler(hz int32) {
+ setProcessCPUProfilerTimer(hz)
+}
+
+func setThreadCPUProfiler(hz int32) {
+ setThreadCPUProfilerHz(hz)
+}
+
+//go:nosplit
+func validSIGPROF(mp *m, c *sigctxt) bool {
+ return true
+}
+
const (
_CLOCK_REALTIME = 9
_CLOCK_MONOTONIC = 10
diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go
index ca61f20e8a..0f0eb6c6fd 100644
--- a/src/runtime/os_darwin.go
+++ b/src/runtime/os_darwin.go
@@ -425,6 +425,19 @@ func sigdelset(mask *sigset, i int) {
*mask &^= 1 << (uint32(i) - 1)
}
+func setProcessCPUProfiler(hz int32) {
+ setProcessCPUProfilerTimer(hz)
+}
+
+func setThreadCPUProfiler(hz int32) {
+ setThreadCPUProfilerHz(hz)
+}
+
+//go:nosplit
+func validSIGPROF(mp *m, c *sigctxt) bool {
+ return true
+}
+
//go:linkname executablePath os.executablePath
var executablePath string
diff --git a/src/runtime/os_dragonfly.go b/src/runtime/os_dragonfly.go
index 191a560667..cba2e42ab0 100644
--- a/src/runtime/os_dragonfly.go
+++ b/src/runtime/os_dragonfly.go
@@ -268,6 +268,19 @@ func sigdelset(mask *sigset, i int) {
func (c *sigctxt) fixsigcode(sig uint32) {
}
+func setProcessCPUProfiler(hz int32) {
+ setProcessCPUProfilerTimer(hz)
+}
+
+func setThreadCPUProfiler(hz int32) {
+ setThreadCPUProfilerHz(hz)
+}
+
+//go:nosplit
+func validSIGPROF(mp *m, c *sigctxt) bool {
+ return true
+}
+
func sysargs(argc int32, argv **byte) {
n := argc + 1
diff --git a/src/runtime/os_freebsd.go b/src/runtime/os_freebsd.go
index 5a8121a420..c63b0e3d69 100644
--- a/src/runtime/os_freebsd.go
+++ b/src/runtime/os_freebsd.go
@@ -380,6 +380,19 @@ func sigdelset(mask *sigset, i int) {
func (c *sigctxt) fixsigcode(sig uint32) {
}
+func setProcessCPUProfiler(hz int32) {
+ setProcessCPUProfilerTimer(hz)
+}
+
+func setThreadCPUProfiler(hz int32) {
+ setThreadCPUProfilerHz(hz)
+}
+
+//go:nosplit
+func validSIGPROF(mp *m, c *sigctxt) bool {
+ return true
+}
+
func sysargs(argc int32, argv **byte) {
n := argc + 1
diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go
index b60dc9ea01..d307c472b8 100644
--- a/src/runtime/os_linux.go
+++ b/src/runtime/os_linux.go
@@ -517,3 +517,19 @@ func tgkill(tgid, tid, sig int)
func signalM(mp *m, sig int) {
tgkill(getpid(), int(mp.procid), sig)
}
+
+func setProcessCPUProfiler(hz int32) {
+ setProcessCPUProfilerTimer(hz)
+}
+
+func setThreadCPUProfiler(hz int32) {
+ setThreadCPUProfilerHz(hz)
+}
+
+//go:nosplit
+func validSIGPROF(mp *m, c *sigctxt) bool {
+ // Once the profiler for Linux uses timer_create, this function will need to
+ // do more than return true. But so long as the only profiling timer in use
+ // is setitimer, returning true is correct.
+ return true
+}
diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go
index 0b95fa7a6e..cd9508c706 100644
--- a/src/runtime/os_netbsd.go
+++ b/src/runtime/os_netbsd.go
@@ -371,6 +371,19 @@ func sigdelset(mask *sigset, i int) {
func (c *sigctxt) fixsigcode(sig uint32) {
}
+func setProcessCPUProfiler(hz int32) {
+ setProcessCPUProfilerTimer(hz)
+}
+
+func setThreadCPUProfiler(hz int32) {
+ setThreadCPUProfilerHz(hz)
+}
+
+//go:nosplit
+func validSIGPROF(mp *m, c *sigctxt) bool {
+ return true
+}
+
func sysargs(argc int32, argv **byte) {
n := argc + 1
diff --git a/src/runtime/os_openbsd.go b/src/runtime/os_openbsd.go
index 54f36c6ebf..2d0e71de53 100644
--- a/src/runtime/os_openbsd.go
+++ b/src/runtime/os_openbsd.go
@@ -233,6 +233,19 @@ func sigdelset(mask *sigset, i int) {
func (c *sigctxt) fixsigcode(sig uint32) {
}
+func setProcessCPUProfiler(hz int32) {
+ setProcessCPUProfilerTimer(hz)
+}
+
+func setThreadCPUProfiler(hz int32) {
+ setThreadCPUProfilerHz(hz)
+}
+
+//go:nosplit
+func validSIGPROF(mp *m, c *sigctxt) bool {
+ return true
+}
+
var haveMapStack = false
func osStackAlloc(s *mspan) {
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go
index cab5c879d3..228497c508 100644
--- a/src/runtime/signal_unix.go
+++ b/src/runtime/signal_unix.go
@@ -263,11 +263,11 @@ func clearSignalHandlers() {
}
}
-// setProcessCPUProfiler is called when the profiling timer changes.
-// It is called with prof.lock held. hz is the new timer, and is 0 if
+// setProcessCPUProfilerTimer is called when the profiling timer changes.
+// It is called with prof.signalLock held. hz is the new timer, and is 0 if
// profiling is being disabled. Enable or disable the signal as
// required for -buildmode=c-archive.
-func setProcessCPUProfiler(hz int32) {
+func setProcessCPUProfilerTimer(hz int32) {
if hz != 0 {
// Enable the Go signal handler if not enabled.
if atomic.Cas(&handlingSig[_SIGPROF], 0, 1) {
@@ -309,10 +309,10 @@ func setProcessCPUProfiler(hz int32) {
}
}
-// setThreadCPUProfiler makes any thread-specific changes required to
+// setThreadCPUProfilerHz makes any thread-specific changes required to
// implement profiling at a rate of hz.
-// No changes required on Unix systems.
-func setThreadCPUProfiler(hz int32) {
+// No changes required on Unix systems when using setitimer.
+func setThreadCPUProfilerHz(hz int32) {
getg().m.profilehz = hz
}
@@ -423,7 +423,11 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
setg(g)
if g == nil {
if sig == _SIGPROF {
- sigprofNonGoPC(c.sigpc())
+ // Some platforms (Linux) have per-thread timers, which we use in
+ // combination with the process-wide timer. Avoid double-counting.
+ if validSIGPROF(nil, c) {
+ sigprofNonGoPC(c.sigpc())
+ }
return
}
if sig == sigPreempt && preemptMSupported && debug.asyncpreemptoff == 0 {
@@ -540,7 +544,12 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
c := &sigctxt{info, ctxt}
if sig == _SIGPROF {
- sigprof(c.sigpc(), c.sigsp(), c.siglr(), gp, _g_.m)
+ mp := _g_.m
+ // Some platforms (Linux) have per-thread timers, which we use in
+ // combination with the process-wide timer. Avoid double-counting.
+ if validSIGPROF(mp, c) {
+ sigprof(c.sigpc(), c.sigsp(), c.siglr(), gp, mp)
+ }
return
}