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 @@ -143,3 +143,39 @@ func debugPinnerV1() *Pinner {
143143 }
144144 return p
145145}
146+
147+ // NumRunnableGoroutines returns the number of goroutines that are in a runnable
148+ // state (i.e. waiting for a chance to run) and the current value of GOMAXPROCS.
149+ //
150+ // The ratio between the two can be used as a rough measure of CPU overload (if
151+ // sampled with enough frequency).
152+ func NumRunnableGoroutines () (numRunnable int , numProcs int ) {
153+ mp := acquirem ()
154+ lock (& sched .lock )
155+ numRunnable = int (sched .runqsize )
156+ numProcs = len (allp )
157+
158+ // Note that holding sched.lock prevents the number of Ps from changing, so
159+ // it's safe to loop over allp.
160+ for _ , p := range allp {
161+ // Retry loop for concurrent updates.
162+ for {
163+ h := atomic .Load (& p .runqhead )
164+ t := atomic .Load (& p .runqtail )
165+ next := atomic .Loaduintptr ((* uintptr )(unsafe .Pointer (& p .runnext )))
166+ runnable := int32 (t - h )
167+ if atomic .Load (& p .runqhead ) != h || runnable < 0 {
168+ // A concurrent update messed with us; try again.
169+ continue
170+ }
171+ if next != 0 {
172+ runnable ++
173+ }
174+ numRunnable += int (runnable )
175+ break
176+ }
177+ }
178+ unlock (& sched .lock )
179+ releasem (mp )
180+ return numRunnable , numProcs
181+ }
You can’t perform that action at this time.
0 commit comments