1 /* $NetBSD: kern_runq.c,v 1.27 2009/10/21 21:12:06 rmind Exp $ */
4 * Copyright (c) 2007, 2008 Mindaugas Rasiukevicius <rmind at NetBSD org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: kern_runq.c,v 1.27 2009/10/21 21:12:06 rmind Exp $");
32 #include <sys/param.h>
33 #include <sys/kernel.h>
34 #include <sys/bitops.h>
40 #include <sys/mutex.h>
42 #include <sys/sched.h>
43 #include <sys/syscallargs.h>
44 #include <sys/sysctl.h>
45 #include <sys/systm.h>
46 #include <sys/types.h>
47 #include <sys/evcnt.h>
50 * Priority related defintions.
52 #define PRI_TS_COUNT (NPRI_USER)
53 #define PRI_RT_COUNT (PRI_COUNT - PRI_TS_COUNT)
54 #define PRI_HTS_RANGE (PRI_TS_COUNT / 10)
56 #define PRI_HIGHEST_TS (MAXPRI_USER)
61 #define BITMAP_BITS (32)
62 #define BITMAP_SHIFT (5)
63 #define BITMAP_MSB (0x80000000U)
64 #define BITMAP_MASK (BITMAP_BITS - 1)
67 * Structures, runqueue.
70 const int schedppq
= 1;
73 TAILQ_HEAD(, lwp
) q_head
;
78 uint32_t r_bitmap
[PRI_COUNT
>> BITMAP_SHIFT
];
80 u_int r_count
; /* Count of the threads */
81 u_int r_avgcount
; /* Average count of threads */
82 u_int r_mcount
; /* Count of migratable threads */
84 queue_t r_rt_queue
[PRI_RT_COUNT
];
85 queue_t r_ts_queue
[PRI_TS_COUNT
];
87 struct evcnt r_ev_pull
;
88 struct evcnt r_ev_push
;
89 struct evcnt r_ev_stay
;
90 struct evcnt r_ev_localize
;
93 static void * sched_getrq(runqueue_t
*, const pri_t
);
95 static lwp_t
* sched_catchlwp(struct cpu_info
*);
96 static void sched_balance(void *);
100 * Preemption control.
102 int sched_upreempt_pri
= PRI_KERNEL
;
103 #ifdef __HAVE_PREEMPTION
105 int sched_kpreempt_pri
= 0;
107 int sched_kpreempt_pri
= PRI_USER_RT
;
110 int sched_kpreempt_pri
= 1000;
114 * Migration and balancing.
116 static u_int cacheht_time
; /* Cache hotness time */
117 static u_int min_catch
; /* Minimal LWP count for catching */
118 static u_int balance_period
; /* Balance period */
119 static struct cpu_info
*worker_ci
; /* Victim CPU */
120 #ifdef MULTIPROCESSOR
121 static struct callout balance_ch
; /* Callout of balancer */
129 worker_ci
= curcpu();
130 cacheht_time
= mstohz(3); /* ~3 ms */
131 balance_period
= mstohz(300); /* ~300 ms */
133 /* Minimal count of LWPs for catching */
136 /* Initialize balancing callout and run it */
137 #ifdef MULTIPROCESSOR
138 callout_init(&balance_ch
, CALLOUT_MPSAFE
);
139 callout_setfunc(&balance_ch
, sched_balance
, NULL
);
140 callout_schedule(&balance_ch
, balance_period
);
145 sched_cpuattach(struct cpu_info
*ci
)
152 if (ci
->ci_schedstate
.spc_lwplock
== NULL
) {
153 ci
->ci_schedstate
.spc_lwplock
=
154 mutex_obj_alloc(MUTEX_DEFAULT
, IPL_SCHED
);
156 if (ci
== lwp0
.l_cpu
) {
157 /* Initialize the scheduler structure of the primary LWP */
158 lwp0
.l_mutex
= ci
->ci_schedstate
.spc_lwplock
;
160 if (ci
->ci_schedstate
.spc_mutex
!= NULL
) {
161 /* Already initialized. */
165 /* Allocate the run queue */
166 size
= roundup2(sizeof(runqueue_t
), coherency_unit
) + coherency_unit
;
167 rq_ptr
= kmem_zalloc(size
, KM_SLEEP
);
168 if (rq_ptr
== NULL
) {
169 panic("sched_cpuattach: could not allocate the runqueue");
171 ci_rq
= (void *)(roundup2((uintptr_t)(rq_ptr
), coherency_unit
));
173 /* Initialize run queues */
174 ci
->ci_schedstate
.spc_mutex
=
175 mutex_obj_alloc(MUTEX_DEFAULT
, IPL_SCHED
);
176 for (i
= 0; i
< PRI_RT_COUNT
; i
++)
177 TAILQ_INIT(&ci_rq
->r_rt_queue
[i
].q_head
);
178 for (i
= 0; i
< PRI_TS_COUNT
; i
++)
179 TAILQ_INIT(&ci_rq
->r_ts_queue
[i
].q_head
);
181 ci
->ci_schedstate
.spc_sched_info
= ci_rq
;
183 cpuname
= kmem_alloc(8, KM_SLEEP
);
184 snprintf(cpuname
, 8, "cpu%d", cpu_index(ci
));
186 evcnt_attach_dynamic(&ci_rq
->r_ev_pull
, EVCNT_TYPE_MISC
, NULL
,
187 cpuname
, "runqueue pull");
188 evcnt_attach_dynamic(&ci_rq
->r_ev_push
, EVCNT_TYPE_MISC
, NULL
,
189 cpuname
, "runqueue push");
190 evcnt_attach_dynamic(&ci_rq
->r_ev_stay
, EVCNT_TYPE_MISC
, NULL
,
191 cpuname
, "runqueue stay");
192 evcnt_attach_dynamic(&ci_rq
->r_ev_localize
, EVCNT_TYPE_MISC
, NULL
,
193 cpuname
, "runqueue localize");
197 * Control of the runqueue.
201 sched_getrq(runqueue_t
*ci_rq
, const pri_t prio
)
204 KASSERT(prio
< PRI_COUNT
);
205 return (prio
<= PRI_HIGHEST_TS
) ?
206 &ci_rq
->r_ts_queue
[prio
].q_head
:
207 &ci_rq
->r_rt_queue
[prio
- PRI_HIGHEST_TS
- 1].q_head
;
211 sched_enqueue(struct lwp
*l
, bool swtch
)
214 struct schedstate_percpu
*spc
;
215 TAILQ_HEAD(, lwp
) *q_head
;
216 const pri_t eprio
= lwp_eprio(l
);
221 spc
= &ci
->ci_schedstate
;
222 ci_rq
= spc
->spc_sched_info
;
223 KASSERT(lwp_locked(l
, l
->l_cpu
->ci_schedstate
.spc_mutex
));
225 /* Update the last run time on switch */
226 if (__predict_true(swtch
== true))
227 l
->l_rticksum
+= (hardclock_ticks
- l
->l_rticks
);
228 else if (l
->l_rticks
== 0)
229 l
->l_rticks
= hardclock_ticks
;
231 /* Enqueue the thread */
232 q_head
= sched_getrq(ci_rq
, eprio
);
233 if (TAILQ_EMPTY(q_head
)) {
238 i
= eprio
>> BITMAP_SHIFT
;
239 q
= BITMAP_MSB
>> (eprio
& BITMAP_MASK
);
240 KASSERT((ci_rq
->r_bitmap
[i
] & q
) == 0);
241 ci_rq
->r_bitmap
[i
] |= q
;
243 TAILQ_INSERT_TAIL(q_head
, l
, l_runq
);
245 if ((l
->l_pflag
& LP_BOUND
) == 0)
249 * Update the value of highest priority in the runqueue,
250 * if priority of this thread is higher.
252 if (eprio
> spc
->spc_maxpriority
)
253 spc
->spc_maxpriority
= eprio
;
258 * Wake the chosen CPU or cause a preemption if the newly
259 * enqueued thread has higher priority. Don't cause a
260 * preemption if the thread is yielding (swtch).
262 if (!swtch
&& eprio
> spc
->spc_curpriority
) {
263 if (eprio
>= sched_kpreempt_pri
)
264 type
= RESCHED_KPREEMPT
;
265 else if (eprio
>= sched_upreempt_pri
)
266 type
= RESCHED_IMMED
;
269 cpu_need_resched(ci
, type
);
274 sched_dequeue(struct lwp
*l
)
277 TAILQ_HEAD(, lwp
) *q_head
;
278 struct schedstate_percpu
*spc
;
279 const pri_t eprio
= lwp_eprio(l
);
281 spc
= & l
->l_cpu
->ci_schedstate
;
282 ci_rq
= spc
->spc_sched_info
;
283 KASSERT(lwp_locked(l
, spc
->spc_mutex
));
285 KASSERT(eprio
<= spc
->spc_maxpriority
);
286 KASSERT(ci_rq
->r_bitmap
[eprio
>> BITMAP_SHIFT
] != 0);
287 KASSERT(ci_rq
->r_count
> 0);
289 if (spc
->spc_migrating
== l
)
290 spc
->spc_migrating
= NULL
;
293 if ((l
->l_pflag
& LP_BOUND
) == 0)
296 q_head
= sched_getrq(ci_rq
, eprio
);
297 TAILQ_REMOVE(q_head
, l
, l_runq
);
298 if (TAILQ_EMPTY(q_head
)) {
303 i
= eprio
>> BITMAP_SHIFT
;
304 q
= BITMAP_MSB
>> (eprio
& BITMAP_MASK
);
305 KASSERT((ci_rq
->r_bitmap
[i
] & q
) != 0);
306 ci_rq
->r_bitmap
[i
] &= ~q
;
309 * Update the value of highest priority in the runqueue, in a
310 * case it was a last thread in the queue of highest priority.
312 if (eprio
!= spc
->spc_maxpriority
)
316 if (ci_rq
->r_bitmap
[i
] != 0) {
317 q
= ffs(ci_rq
->r_bitmap
[i
]);
318 spc
->spc_maxpriority
=
319 (i
<< BITMAP_SHIFT
) + (BITMAP_BITS
- q
);
324 /* If not found - set the lowest value */
325 spc
->spc_maxpriority
= 0;
330 * Migration and balancing.
333 #ifdef MULTIPROCESSOR
335 /* Estimate if LWP is cache-hot */
337 lwp_cache_hot(const struct lwp
*l
)
340 if (__predict_false(l
->l_slptime
|| l
->l_rticks
== 0))
343 return (hardclock_ticks
- l
->l_rticks
<= cacheht_time
);
346 /* Check if LWP can migrate to the chosen CPU */
348 sched_migratable(const struct lwp
*l
, struct cpu_info
*ci
)
350 const struct schedstate_percpu
*spc
= &ci
->ci_schedstate
;
351 KASSERT(lwp_locked(__UNCONST(l
), NULL
));
354 if (__predict_false(spc
->spc_flags
& SPCF_OFFLINE
))
358 if (__predict_false(l
->l_flag
& LW_AFFINITY
))
359 return kcpuset_isset(cpu_index(ci
), l
->l_affinity
);
362 return (spc
->spc_psid
== l
->l_psid
);
366 * Estimate the migration of LWP to the other CPU.
367 * Take and return the CPU, if migration is needed.
370 sched_takecpu(struct lwp
*l
)
372 struct cpu_info
*ci
, *tci
, *first
, *next
;
373 struct schedstate_percpu
*spc
;
374 runqueue_t
*ci_rq
, *ici_rq
;
375 pri_t eprio
, lpri
, pri
;
377 KASSERT(lwp_locked(l
, NULL
));
379 /* If thread is strictly bound, do not estimate other CPUs */
381 if (l
->l_pflag
& LP_BOUND
)
384 spc
= &ci
->ci_schedstate
;
385 ci_rq
= spc
->spc_sched_info
;
387 /* Make sure that thread is in appropriate processor-set */
388 if (__predict_true(spc
->spc_psid
== l
->l_psid
)) {
389 /* If CPU of this thread is idling - run there */
390 if (ci_rq
->r_count
== 0) {
391 ci_rq
->r_ev_stay
.ev_count
++;
394 /* Stay if thread is cache-hot */
395 eprio
= lwp_eprio(l
);
396 if (__predict_true(l
->l_stat
!= LSIDL
) &&
397 lwp_cache_hot(l
) && eprio
>= spc
->spc_curpriority
) {
398 ci_rq
->r_ev_stay
.ev_count
++;
402 eprio
= lwp_eprio(l
);
405 /* Run on current CPU if priority of thread is higher */
407 spc
= &ci
->ci_schedstate
;
408 if (eprio
> spc
->spc_curpriority
&& sched_migratable(l
, ci
)) {
409 ci_rq
= spc
->spc_sched_info
;
410 ci_rq
->r_ev_localize
.ev_count
++;
415 * Look for the CPU with the lowest priority thread. In case of
416 * equal priority, choose the CPU with the fewest of threads.
423 next
= CIRCLEQ_LOOP_NEXT(&cpu_queue
, ci
, ci_data
.cpu_qchain
);
424 spc
= &ci
->ci_schedstate
;
425 ici_rq
= spc
->spc_sched_info
;
426 pri
= max(spc
->spc_curpriority
, spc
->spc_maxpriority
);
430 if (pri
== lpri
&& ci_rq
->r_count
< ici_rq
->r_count
)
433 if (!sched_migratable(l
, ci
))
439 } while (ci
= next
, ci
!= first
);
441 ci_rq
= tci
->ci_schedstate
.spc_sched_info
;
442 ci_rq
->r_ev_push
.ev_count
++;
448 * Tries to catch an LWP from the runqueue of other CPU.
451 sched_catchlwp(struct cpu_info
*ci
)
453 struct cpu_info
*curci
= curcpu();
454 struct schedstate_percpu
*spc
, *curspc
;
455 TAILQ_HEAD(, lwp
) *q_head
;
459 curspc
= &curci
->ci_schedstate
;
460 spc
= &ci
->ci_schedstate
;
461 KASSERT(curspc
->spc_psid
== spc
->spc_psid
);
463 ci_rq
= spc
->spc_sched_info
;
464 if (ci_rq
->r_mcount
< min_catch
) {
469 /* Take the highest priority thread */
470 q_head
= sched_getrq(ci_rq
, spc
->spc_maxpriority
);
471 l
= TAILQ_FIRST(q_head
);
474 /* Check the first and next result from the queue */
478 KASSERT(l
->l_stat
== LSRUN
);
480 /* Look for threads, whose are allowed to migrate */
481 if ((l
->l_pflag
& LP_BOUND
) || lwp_cache_hot(l
) ||
482 !sched_migratable(l
, curci
)) {
483 l
= TAILQ_NEXT(l
, l_runq
);
487 /* Grab the thread, and move to the local run queue */
491 * If LWP is still context switching, we may need to
492 * spin-wait before changing its CPU.
494 if (__predict_false(l
->l_ctxswtch
!= 0)) {
496 count
= SPINLOCK_BACKOFF_MIN
;
497 while (l
->l_ctxswtch
)
498 SPINLOCK_BACKOFF(count
);
501 ci_rq
->r_ev_pull
.ev_count
++;
502 lwp_unlock_to(l
, curspc
->spc_mutex
);
503 sched_enqueue(l
, false);
512 * Periodical calculations for balancing.
515 sched_balance(void *nocallout
)
517 struct cpu_info
*ci
, *hci
;
519 CPU_INFO_ITERATOR cii
;
525 /* Make lockless countings */
526 for (CPU_INFO_FOREACH(cii
, ci
)) {
527 ci_rq
= ci
->ci_schedstate
.spc_sched_info
;
529 /* Average count of the threads */
530 ci_rq
->r_avgcount
= (ci_rq
->r_avgcount
+ ci_rq
->r_mcount
) >> 1;
532 /* Look for CPU with the highest average */
533 if (ci_rq
->r_avgcount
> highest
) {
535 highest
= ci_rq
->r_avgcount
;
539 /* Update the worker */
542 if (nocallout
== NULL
)
543 callout_schedule(&balance_ch
, balance_period
);
547 * Called from each CPU's idle loop.
552 struct cpu_info
*ci
= curcpu(), *tci
= NULL
;
553 struct schedstate_percpu
*spc
, *tspc
;
557 /* Check if there is a migrating LWP */
558 spc
= &ci
->ci_schedstate
;
559 if (spc
->spc_migrating
== NULL
)
566 l
= spc
->spc_migrating
;
571 * If second attempt, and target CPU has changed,
574 if (dlock
== true && tci
!= l
->l_target_cpu
) {
575 KASSERT(tci
!= NULL
);
581 * Nothing to do if destination has changed to the
582 * local CPU, or migration was done by other CPU.
584 tci
= l
->l_target_cpu
;
585 if (tci
== NULL
|| tci
== ci
) {
586 spc
->spc_migrating
= NULL
;
587 l
->l_target_cpu
= NULL
;
590 tspc
= &tci
->ci_schedstate
;
593 * Double-lock the runqueues.
594 * We do that only once.
596 if (dlock
== false) {
600 } else if (!mutex_tryenter(tspc
->spc_mutex
)) {
604 /* Check the situation again.. */
609 /* Migrate the thread */
610 KASSERT(l
->l_stat
== LSRUN
);
611 spc
->spc_migrating
= NULL
;
612 l
->l_target_cpu
= NULL
;
615 lwp_setlock(l
, tspc
->spc_mutex
);
616 sched_enqueue(l
, false);
620 KASSERT(tci
!= NULL
);
626 ci_rq
= spc
->spc_sched_info
;
627 if ((spc
->spc_flags
& SPCF_OFFLINE
) != 0 || ci_rq
->r_count
!= 0) {
631 /* Reset the counter, and call the balancer */
632 ci_rq
->r_avgcount
= 0;
635 tspc
= &tci
->ci_schedstate
;
636 if (ci
== tci
|| spc
->spc_psid
!= tspc
->spc_psid
)
639 (void)sched_catchlwp(tci
);
646 sched_takecpu(struct lwp
*l
)
657 #endif /* MULTIPROCESSOR */
660 * Scheduling statistics and balancing.
663 sched_lwp_stats(struct lwp
*l
)
667 KASSERT(lwp_locked(l
, NULL
));
669 /* Update sleep time */
670 if (l
->l_stat
== LSSLEEP
|| l
->l_stat
== LSSTOP
||
671 l
->l_stat
== LSSUSPENDED
)
675 * Set that thread is more CPU-bound, if sum of run time exceeds the
676 * sum of sleep time. Check if thread is CPU-bound a first time.
678 batch
= (l
->l_rticksum
> l
->l_slpticksum
);
680 if ((l
->l_flag
& LW_BATCH
) == 0)
682 l
->l_flag
|= LW_BATCH
;
684 l
->l_flag
&= ~LW_BATCH
;
687 * If thread is CPU-bound and never sleeps, it would occupy the CPU.
688 * In such case reset the value of last sleep, and check it later, if
689 * it is still zero - perform the migration, unmark the batch flag.
691 if (batch
&& (l
->l_slptime
+ l
->l_slpticksum
) == 0) {
692 if (l
->l_slpticks
== 0) {
693 if (l
->l_target_cpu
== NULL
&&
694 (l
->l_stat
== LSRUN
|| l
->l_stat
== LSONPROC
)) {
695 struct cpu_info
*ci
= sched_takecpu(l
);
696 l
->l_target_cpu
= (ci
!= l
->l_cpu
) ? ci
: NULL
;
698 l
->l_flag
&= ~LW_BATCH
;
704 /* Reset the time sums */
708 /* Scheduler-specific hook */
709 sched_pstats_hook(l
, batch
);
718 struct cpu_info
*ci
= curcpu();
719 struct schedstate_percpu
*spc
;
720 TAILQ_HEAD(, lwp
) *q_head
;
724 /* Return to idle LWP if there is a migrating thread */
725 spc
= &ci
->ci_schedstate
;
726 if (__predict_false(spc
->spc_migrating
!= NULL
))
728 ci_rq
= spc
->spc_sched_info
;
730 #ifdef MULTIPROCESSOR
731 /* If runqueue is empty, try to catch some thread from other CPU */
732 if (__predict_false(ci_rq
->r_count
== 0)) {
733 struct schedstate_percpu
*cspc
;
734 struct cpu_info
*cci
;
736 /* Offline CPUs should not perform this, however */
737 if (__predict_false(spc
->spc_flags
& SPCF_OFFLINE
))
740 /* Reset the counter, and call the balancer */
741 ci_rq
->r_avgcount
= 0;
744 cspc
= &cci
->ci_schedstate
;
745 if (ci
== cci
|| spc
->spc_psid
!= cspc
->spc_psid
||
746 !mutex_tryenter(cci
->ci_schedstate
.spc_mutex
))
748 return sched_catchlwp(cci
);
751 if (__predict_false(ci_rq
->r_count
== 0))
755 /* Take the highest priority thread */
756 KASSERT(ci_rq
->r_bitmap
[spc
->spc_maxpriority
>> BITMAP_SHIFT
]);
757 q_head
= sched_getrq(ci_rq
, spc
->spc_maxpriority
);
758 l
= TAILQ_FIRST(q_head
);
762 l
->l_rticks
= hardclock_ticks
;
768 sched_curcpu_runnable_p(void)
770 const struct cpu_info
*ci
;
771 const struct schedstate_percpu
*spc
;
772 const runqueue_t
*ci_rq
;
777 spc
= &ci
->ci_schedstate
;
778 ci_rq
= spc
->spc_sched_info
;
780 #ifndef __HAVE_FAST_SOFTINTS
781 if (ci
->ci_data
.cpu_softints
) {
787 rv
= (ci_rq
->r_count
!= 0) ? true : false;
794 * Sysctl nodes and initialization.
797 SYSCTL_SETUP(sysctl_sched_setup
, "sysctl sched setup")
799 const struct sysctlnode
*node
= NULL
;
801 sysctl_createv(clog
, 0, NULL
, NULL
,
803 CTLTYPE_NODE
, "kern", NULL
,
806 sysctl_createv(clog
, 0, NULL
, &node
,
808 CTLTYPE_NODE
, "sched",
809 SYSCTL_DESCR("Scheduler options"),
811 CTL_KERN
, CTL_CREATE
, CTL_EOL
);
816 sysctl_createv(clog
, 0, &node
, NULL
,
817 CTLFLAG_PERMANENT
| CTLFLAG_READWRITE
,
818 CTLTYPE_INT
, "cacheht_time",
819 SYSCTL_DESCR("Cache hotness time (in ticks)"),
820 NULL
, 0, &cacheht_time
, 0,
821 CTL_CREATE
, CTL_EOL
);
822 sysctl_createv(clog
, 0, &node
, NULL
,
823 CTLFLAG_PERMANENT
| CTLFLAG_READWRITE
,
824 CTLTYPE_INT
, "balance_period",
825 SYSCTL_DESCR("Balance period (in ticks)"),
826 NULL
, 0, &balance_period
, 0,
827 CTL_CREATE
, CTL_EOL
);
828 sysctl_createv(clog
, 0, &node
, NULL
,
829 CTLFLAG_PERMANENT
| CTLFLAG_READWRITE
,
830 CTLTYPE_INT
, "min_catch",
831 SYSCTL_DESCR("Minimal count of threads for catching"),
832 NULL
, 0, &min_catch
, 0,
833 CTL_CREATE
, CTL_EOL
);
834 sysctl_createv(clog
, 0, &node
, NULL
,
835 CTLFLAG_PERMANENT
| CTLFLAG_READWRITE
,
836 CTLTYPE_INT
, "timesoftints",
837 SYSCTL_DESCR("Track CPU time for soft interrupts"),
838 NULL
, 0, &softint_timing
, 0,
839 CTL_CREATE
, CTL_EOL
);
840 sysctl_createv(clog
, 0, &node
, NULL
,
841 CTLFLAG_PERMANENT
| CTLFLAG_READWRITE
,
842 CTLTYPE_INT
, "kpreempt_pri",
843 SYSCTL_DESCR("Minimum priority to trigger kernel preemption"),
844 NULL
, 0, &sched_kpreempt_pri
, 0,
845 CTL_CREATE
, CTL_EOL
);
846 sysctl_createv(clog
, 0, &node
, NULL
,
847 CTLFLAG_PERMANENT
| CTLFLAG_READWRITE
,
848 CTLTYPE_INT
, "upreempt_pri",
849 SYSCTL_DESCR("Minimum priority to trigger user preemption"),
850 NULL
, 0, &sched_upreempt_pri
, 0,
851 CTL_CREATE
, CTL_EOL
);
861 sched_print_runqueue(void (*pr
)(const char *, ...)
862 __attribute__((__format__(__printf__
,1,2))))
865 struct cpu_info
*ci
, *tci
;
866 struct schedstate_percpu
*spc
;
869 CPU_INFO_ITERATOR cii
;
871 for (CPU_INFO_FOREACH(cii
, ci
)) {
874 spc
= &ci
->ci_schedstate
;
875 ci_rq
= spc
->spc_sched_info
;
877 (*pr
)("Run-queue (CPU = %u):\n", ci
->ci_index
);
878 (*pr
)(" pid.lid = %d.%d, r_count = %u, r_avgcount = %u, "
879 "maxpri = %d, mlwp = %p\n",
880 #ifdef MULTIPROCESSOR
881 ci
->ci_curlwp
->l_proc
->p_pid
, ci
->ci_curlwp
->l_lid
,
883 curlwp
->l_proc
->p_pid
, curlwp
->l_lid
,
885 ci_rq
->r_count
, ci_rq
->r_avgcount
, spc
->spc_maxpriority
,
887 i
= (PRI_COUNT
>> BITMAP_SHIFT
) - 1;
890 q
= ci_rq
->r_bitmap
[i
];
891 (*pr
)(" bitmap[%d] => [ %d (0x%x) ]\n", i
, ffs(q
), q
);
895 (*pr
)(" %5s %4s %4s %10s %3s %18s %4s %4s %s\n",
896 "LID", "PRI", "EPRI", "FL", "ST", "LWP", "CPU", "TCI", "LRTICKS");
898 PROCLIST_FOREACH(p
, &allproc
) {
899 if ((p
->p_flag
& PK_MARKER
) != 0)
901 (*pr
)(" /- %d (%s)\n", (int)p
->p_pid
, p
->p_comm
);
902 LIST_FOREACH(l
, &p
->p_lwps
, l_sibling
) {
904 tci
= l
->l_target_cpu
;
905 (*pr
)(" | %5d %4u %4u 0x%8.8x %3s %18p %4u %4d %u\n",
906 (int)l
->l_lid
, l
->l_priority
, lwp_eprio(l
),
907 l
->l_flag
, l
->l_stat
== LSRUN
? "RQ" :
908 (l
->l_stat
== LSSLEEP
? "SQ" : "-"),
909 l
, ci
->ci_index
, (tci
? tci
->ci_index
: -1),
910 (u_int
)(hardclock_ticks
- l
->l_rticks
));