]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: allow per-OS changes to unix profiler
authorRhys Hiltner <rhys@justin.tv>
Fri, 13 Aug 2021 15:51:46 +0000 (08:51 -0700)
committerMichael Pratt <mpratt@google.com>
Mon, 27 Sep 2021 18:58:20 +0000 (18:58 +0000)
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>

src/runtime/os3_solaris.go
src/runtime/os_aix.go
src/runtime/os_darwin.go
src/runtime/os_dragonfly.go
src/runtime/os_freebsd.go
src/runtime/os_linux.go
src/runtime/os_netbsd.go
src/runtime/os_openbsd.go
src/runtime/signal_unix.go

index 84194a3050d6c99d32ce41246e43280b6b785f20..3149d13869f3fb1a7a06c4ec833418defe4363f6 100644 (file)
@@ -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 {
index 478dde2fc3ff4c1d8527c83a50fd86f19d8cbbb0..54e0cfbb8d436f0e48f4f1663df05382c2012a3b 100644 (file)
@@ -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
index ca61f20e8ac43c0d57c282c6f2f0c9cab98f8776..0f0eb6c6fdcfa609b7dc753f8ea5a526d2d1d27b 100644 (file)
@@ -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
 
index 191a560667c9cf9a2329543830d2c8855d8fee8c..cba2e42ab052d056e4e057f3d82e6059cbad0961 100644 (file)
@@ -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
 
index 5a8121a420f208fea16c4aa345380fc63afabc63..c63b0e3d69dc0609d1ca425ff0ec2cfd7b4d2630 100644 (file)
@@ -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
 
index b60dc9ea01064cad4391531ddbf901f7185c0ab4..d307c472b812af4eadf8e00cfeac100f84897cfc 100644 (file)
@@ -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
+}
index 0b95fa7a6e75c77fe49c3a535fee7d14a4472eaf..cd9508c7063f94218ff5259cb006a598b52cc944 100644 (file)
@@ -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
 
index 54f36c6ebff7a4aebfd3c2a4a2b164043e00a58c..2d0e71de53b5ee3c1851608843df511d52e6149c 100644 (file)
@@ -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) {
index cab5c879d39b6ab61de0b14757642e751935e995..228497c508f82139e21c6a8a62620495b1274c28 100644 (file)
@@ -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
        }