@@ -10,6 +10,7 @@ package runtime
10
10
import (
11
11
"internal/abi"
12
12
"runtime/internal/atomic"
13
+ "runtime/internal/sys"
13
14
"unsafe"
14
15
)
15
16
@@ -469,6 +470,45 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
469
470
}
470
471
}
471
472
473
+ // If the signal handler receives a SIGPROF signal on a non-Go thread,
474
+ // it tries to collect a traceback into sigprofCallers.
475
+ // sigprofCallersUse is set to non-zero while sigprofCallers holds a traceback.
476
+ var sigprofCallers cgoCallers
477
+ var sigprofCallersUse uint32
478
+
479
+ // sigprofNonGo is called if we receive a SIGPROF signal on a non-Go thread,
480
+ // and the signal handler collected a stack trace in sigprofCallers.
481
+ // When this is called, sigprofCallersUse will be non-zero.
482
+ // g is nil, and what we can do is very limited.
483
+ //go:nosplit
484
+ //go:nowritebarrierrec
485
+ func sigprofNonGo () {
486
+ if prof .hz != 0 {
487
+ n := 0
488
+ for n < len (sigprofCallers ) && sigprofCallers [n ] != 0 {
489
+ n ++
490
+ }
491
+ cpuprof .addNonGo (sigprofCallers [:n ])
492
+ }
493
+
494
+ atomic .Store (& sigprofCallersUse , 0 )
495
+ }
496
+
497
+ // sigprofNonGoPC is called when a profiling signal arrived on a
498
+ // non-Go thread and we have a single PC value, not a stack trace.
499
+ // g is nil, and what we can do is very limited.
500
+ //go:nosplit
501
+ //go:nowritebarrierrec
502
+ func sigprofNonGoPC (pc uintptr ) {
503
+ if prof .hz != 0 {
504
+ stk := []uintptr {
505
+ pc ,
506
+ abi .FuncPCABIInternal (_ExternalCode ) + sys .PCQuantum ,
507
+ }
508
+ cpuprof .addNonGo (stk )
509
+ }
510
+ }
511
+
472
512
// adjustSignalStack adjusts the current stack guard based on the
473
513
// stack pointer that is actually in use while handling a signal.
474
514
// We do this in case some non-Go code called sigaltstack.
0 commit comments