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,