summaryrefslogtreecommitdiff
path: root/libgo/go/runtime/pprof/pprof.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/runtime/pprof/pprof.go')
-rw-r--r--libgo/go/runtime/pprof/pprof.go38
1 files changed, 38 insertions, 0 deletions
diff --git a/libgo/go/runtime/pprof/pprof.go b/libgo/go/runtime/pprof/pprof.go
index a8e78e0ea75..42f04f320a7 100644
--- a/libgo/go/runtime/pprof/pprof.go
+++ b/libgo/go/runtime/pprof/pprof.go
@@ -110,6 +110,44 @@ func WriteHeapProfile(w io.Writer) error {
return b.Flush()
}
+// WriteThreadProfile writes a pprof-formatted thread creation profile to w.
+// If a write to w returns an error, WriteThreadProfile returns that error.
+// Otherwise, WriteThreadProfile returns nil.
+func WriteThreadProfile(w io.Writer) error {
+ // Find out how many records there are (ThreadProfile(nil)),
+ // allocate that many records, and get the data.
+ // There's a race—more records (threads) might be added between
+ // the two calls—so allocate a few extra records for safety
+ // and also try again if we're very unlucky.
+ // The loop should only execute one iteration in the common case.
+ var p []runtime.ThreadProfileRecord
+ n, ok := runtime.ThreadProfile(nil)
+ for {
+ // Allocate room for a slightly bigger profile,
+ // in case a few more entries have been added
+ // since the call to ThreadProfile.
+ p = make([]runtime.ThreadProfileRecord, n+10)
+ n, ok = runtime.ThreadProfile(p)
+ if ok {
+ p = p[0:n]
+ break
+ }
+ // Profile grew; try again.
+ }
+
+ b := bufio.NewWriter(w)
+ fmt.Fprintf(b, "thread creation profile: %d threads\n", n)
+ for i := range p {
+ r := &p[i]
+ fmt.Fprintf(b, "@")
+ for _, pc := range r.Stack() {
+ fmt.Fprintf(b, " %#x", pc)
+ }
+ fmt.Fprintf(b, "\n")
+ }
+ return b.Flush()
+}
+
var cpu struct {
sync.Mutex
profiling bool