return (*atomic.Uint32)(p).CompareAndSwap(uint32(old), uint32(new))
}
-//go:linkname runtime_gcount runtime/pprof.runtime_gcount
-func runtime_gcount() int {
- return int(gcount())
-}
-
func goroutineProfileWithLabelsConcurrent(p []StackRecord, labels []unsafe.Pointer) (n int, ok bool) {
+ if len(p) == 0 {
+ // An empty slice is obviously too small. Return a rough
+ // allocation estimate without bothering to STW. As long as
+ // this is close, then we'll only need to STW once (on the next
+ // call).
+ return int(gcount()), false
+ }
+
semacquire(&goroutineProfile.sema)
ourg := getg()
return err
}
-// runtime_gcount is defined in runtime/mprof.go
-func runtime_gcount() (n int)
-
func writeRuntimeProfile(w io.Writer, debug int, name string, fetch func([]runtime.StackRecord, []unsafe.Pointer) (int, bool)) error {
// Find out how many records there are (fetch(nil)),
// allocate that many records, and get the data.
// The loop should only execute one iteration in the common case.
var p []runtime.StackRecord
var labels []unsafe.Pointer
- var n, ok = 0, false
- if name == "goroutine" {
- n = runtime_gcount()
- } else {
- n, ok = fetch(nil, nil)
- }
+ n, ok := fetch(nil, nil)
for {
// Allocate room for a slightly bigger profile,