File tree Expand file tree Collapse file tree 2 files changed +37
-0
lines changed Expand file tree Collapse file tree 2 files changed +37
-0
lines changed Original file line number Diff line number Diff line change @@ -30871,3 +30871,4 @@ pkg unicode/utf8, func Valid([]uint8) bool
3087130871pkg unicode/utf8, func ValidString(string) bool
3087230872pkg context, func PropagateCancel(Context, func()) bool
3087330873pkg runtime, func Grunningnanos() int64
30874+ pkg runtime, func NumRunnableGoroutines() (int, int)
Original file line number Diff line number Diff line change @@ -255,3 +255,39 @@ func debugPinnerV1() *Pinner {
255255 }
256256 return p
257257}
258+
259+ // NumRunnableGoroutines returns the number of goroutines that are in a runnable
260+ // state (i.e. waiting for a chance to run) and the current value of GOMAXPROCS.
261+ //
262+ // The ratio between the two can be used as a rough measure of CPU overload (if
263+ // sampled with enough frequency).
264+ func NumRunnableGoroutines () (numRunnable int , numProcs int ) {
265+ mp := acquirem ()
266+ lock (& sched .lock )
267+ numRunnable = int (sched .runq .size )
268+ numProcs = len (allp )
269+
270+ // Note that holding sched.lock prevents the number of Ps from changing, so
271+ // it's safe to loop over allp.
272+ for _ , p := range allp {
273+ // Retry loop for concurrent updates.
274+ for {
275+ h := atomic .Load (& p .runqhead )
276+ t := atomic .Load (& p .runqtail )
277+ next := atomic .Loaduintptr ((* uintptr )(unsafe .Pointer (& p .runnext )))
278+ runnable := int32 (t - h )
279+ if atomic .Load (& p .runqhead ) != h || runnable < 0 {
280+ // A concurrent update messed with us; try again.
281+ continue
282+ }
283+ if next != 0 {
284+ runnable ++
285+ }
286+ numRunnable += int (runnable )
287+ break
288+ }
289+ }
290+ unlock (& sched .lock )
291+ releasem (mp )
292+ return numRunnable , numProcs
293+ }
You can’t perform that action at this time.
0 commit comments