OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package runtime | 5 package runtime |
6 | 6 |
7 import ( | 7 import ( |
8 "unsafe" | 8 "unsafe" |
9 ) | 9 ) |
10 | 10 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 p[idx].Stack0[i] = 0 | 134 p[idx].Stack0[i] = 0 |
135 i++ | 135 i++ |
136 } | 136 } |
137 idx++ | 137 idx++ |
138 } | 138 } |
139 } | 139 } |
140 gounlock(&proflock) | 140 gounlock(&proflock) |
141 return | 141 return |
142 } | 142 } |
143 | 143 |
| 144 // Stack formats a stack trace of the calling goroutine into buf |
| 145 // and returns the number of bytes written to buf. |
| 146 // If all is true, Stack formats stack traces of all other goroutines |
| 147 // into buf after the trace for the current goroutine. |
| 148 func Stack(buf []byte, all bool) int { |
| 149 sp := gogetcallersp(unsafe.Pointer(&buf)) |
| 150 pc := gogetcallerpc(unsafe.Pointer(&buf)) |
| 151 mp := acquirem() |
| 152 gp := mp.curg |
| 153 if all { |
| 154 semacquire(&worldsema, false) |
| 155 mp.gcing = 1 |
| 156 releasem(mp) |
| 157 stoptheworld() |
| 158 if mp != acquirem() { |
| 159 gothrow("Stack: rescheduled") |
| 160 } |
| 161 } |
| 162 |
| 163 n := 0 |
| 164 if len(buf) > 0 { |
| 165 gp.writebuf = &buf[0] |
| 166 gp.writenbuf = int32(len(buf)) |
| 167 traceback(pc, sp, 0, gp) |
| 168 if all { |
| 169 tracebackothers(gp) |
| 170 } |
| 171 n = len(buf) - int(gp.writenbuf) |
| 172 gp.writebuf = nil |
| 173 gp.writenbuf = 0 |
| 174 } |
| 175 |
| 176 if all { |
| 177 mp.gcing = 0 |
| 178 semrelease(&worldsema) |
| 179 starttheworld() |
| 180 } |
| 181 releasem(mp) |
| 182 return n |
| 183 } |
| 184 |
144 // ThreadCreateProfile returns n, the number of records in the thread creation p
rofile. | 185 // ThreadCreateProfile returns n, the number of records in the thread creation p
rofile. |
145 // If len(p) >= n, ThreadCreateProfile copies the profile into p and returns n,
true. | 186 // If len(p) >= n, ThreadCreateProfile copies the profile into p and returns n,
true. |
146 // If len(p) < n, ThreadCreateProfile does not change p and returns n, false. | 187 // If len(p) < n, ThreadCreateProfile does not change p and returns n, false. |
147 // | 188 // |
148 // Most clients should use the runtime/pprof package instead | 189 // Most clients should use the runtime/pprof package instead |
149 // of calling ThreadCreateProfile directly. | 190 // of calling ThreadCreateProfile directly. |
150 func ThreadCreateProfile(p []StackRecord) (n int, ok bool) { | 191 func ThreadCreateProfile(p []StackRecord) (n int, ok bool) { |
151 first := (*m)(goatomicloadp(unsafe.Pointer(&allm))) | 192 first := (*m)(goatomicloadp(unsafe.Pointer(&allm))) |
152 for mp := first; mp != nil; mp = mp.alllink { | 193 for mp := first; mp != nil; mp = mp.alllink { |
153 n++ | 194 n++ |
154 } | 195 } |
155 if n <= len(p) { | 196 if n <= len(p) { |
156 ok = true | 197 ok = true |
157 i := 0 | 198 i := 0 |
158 for mp := first; mp != nil; mp = mp.alllink { | 199 for mp := first; mp != nil; mp = mp.alllink { |
159 for s := range mp.createstack { | 200 for s := range mp.createstack { |
160 p[i].Stack0[s] = uintptr(mp.createstack[s]) | 201 p[i].Stack0[s] = uintptr(mp.createstack[s]) |
161 } | 202 } |
162 i++ | 203 i++ |
163 } | 204 } |
164 } | 205 } |
165 return | 206 return |
166 } | 207 } |
OLD | NEW |