kern_switch.c revision 112993
1117397Skan/*
2117397Skan * Copyright (c) 2001 Jake Burkholder <jake@FreeBSD.org>
3117397Skan * All rights reserved.
4117397Skan *
5117397Skan * Redistribution and use in source and binary forms, with or without
6117397Skan * modification, are permitted provided that the following conditions
7117397Skan * are met:
8117397Skan * 1. Redistributions of source code must retain the above copyright
9117397Skan *    notice, this list of conditions and the following disclaimer.
10117397Skan * 2. Redistributions in binary form must reproduce the above copyright
11117397Skan *    notice, this list of conditions and the following disclaimer in the
12117397Skan *    documentation and/or other materials provided with the distribution.
13117397Skan *
14117397Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15117397Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16117397Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17117397Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18117397Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19169691Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20117397Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21117397Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22117397Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23117397Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24117397Skan * SUCH DAMAGE.
25117397Skan *
26117397Skan * $FreeBSD: head/sys/kern/kern_switch.c 112993 2003-04-02 23:53:30Z peter $
27117397Skan */
28117397Skan
29117397Skan/***
30117397Skan
31169691SkanHere is the logic..
32169691Skan
33169691SkanIf there are N processors, then there are at most N KSEs (kernel
34169691Skanschedulable entities) working to process threads that belong to a
35169691SkanKSEGOUP (kg). If there are X of these KSEs actually running at the
36117397Skanmoment in question, then there are at most M (N-X) of these KSEs on
37117397Skanthe run queue, as running KSEs are not on the queue.
38117397Skan
39117397SkanRunnable threads are queued off the KSEGROUP in priority order.
40117397SkanIf there are M or more threads runnable, the top M threads
41117397Skan(by priority) are 'preassigned' to the M KSEs not running. The KSEs take
42117397Skantheir priority from those threads and are put on the run queue.
43117397Skan
44117397SkanThe last thread that had a priority high enough to have a KSE associated
45117397Skanwith it, AND IS ON THE RUN QUEUE is pointed to by
46117397Skankg->kg_last_assigned. If no threads queued off the KSEGROUP have KSEs
47117397Skanassigned as all the available KSEs are activly running, or because there
48132720Skanare no threads queued, that pointer is NULL.
49117397Skan
50117397SkanWhen a KSE is removed from the run queue to become runnable, we know
51132720Skanit was associated with the highest priority thread in the queue (at the head
52132720Skanof the queue). If it is also the last assigned we know M was 1 and must
53132720Skannow be 0. Since the thread is no longer queued that pointer must be
54132720Skanremoved from it. Since we know there were no more KSEs available,
55132720Skan(M was 1 and is now 0) and since we are not FREEING our KSE
56132720Skanbut using it, we know there are STILL no more KSEs available, we can prove
57117397Skanthat the next thread in the ksegrp list will not have a KSE to assign to
58117397Skanit, so we can show that the pointer must be made 'invalid' (NULL).
59132720Skan
60117397SkanThe pointer exists so that when a new thread is made runnable, it can
61117397Skanhave its priority compared with the last assigned thread to see if
62132720Skanit should 'steal' its KSE or not.. i.e. is it 'earlier'
63132720Skanon the list than that thread or later.. If it's earlier, then the KSE is
64132720Skanremoved from the last assigned (which is now not assigned a KSE)
65132720Skanand reassigned to the new thread, which is placed earlier in the list.
66132720SkanThe pointer is then backed up to the previous thread (which may or may not
67132720Skanbe the new thread).
68117397Skan
69117397SkanWhen a thread sleeps or is removed, the KSE becomes available and if there
70117397Skanare queued threads that are not assigned KSEs, the highest priority one of
71117397Skanthem is assigned the KSE, which is then placed back on the run queue at
72117397Skanthe approipriate place, and the kg->kg_last_assigned pointer is adjusted down
73117397Skanto point to it.
74117397Skan
75117397SkanThe following diagram shows 2 KSEs and 3 threads from a single process.
76117397Skan
77117397Skan RUNQ: --->KSE---KSE--...    (KSEs queued at priorities from threads)
78117397Skan              \    \____
79117397Skan               \        \
80117397Skan    KSEGROUP---thread--thread--thread    (queued in priority order)
81117397Skan        \                 /
82117397Skan         \_______________/
83117397Skan          (last_assigned)
84117397Skan
85117397SkanThe result of this scheme is that the M available KSEs are always
86117397Skanqueued at the priorities they have inherrited from the M highest priority
87117397Skanthreads for that KSEGROUP. If this situation changes, the KSEs are
88117397Skanreassigned to keep this true.
89117397Skan
90117397Skan*/
91117397Skan
92117397Skan#include <sys/param.h>
93117397Skan#include <sys/systm.h>
94117397Skan#include <sys/kernel.h>
95117397Skan#include <sys/ktr.h>
96117397Skan#include <sys/lock.h>
97117397Skan#include <sys/mutex.h>
98#include <sys/proc.h>
99#include <sys/queue.h>
100#include <sys/sched.h>
101#if defined(SMP) && defined(__i386__)
102#include <sys/smp.h>
103#endif
104#include <machine/critical.h>
105
106CTASSERT((RQB_BPW * RQB_LEN) == RQ_NQS);
107
108void panc(char *string1, char *string2);
109
110#if 0
111static void runq_readjust(struct runq *rq, struct kse *ke);
112#endif
113/************************************************************************
114 * Functions that manipulate runnability from a thread perspective.	*
115 ************************************************************************/
116/*
117 * Select the KSE that will be run next.  From that find the thread, and
118 * remove it from the KSEGRP's run queue.  If there is thread clustering,
119 * this will be what does it.
120 */
121struct thread *
122choosethread(void)
123{
124	struct kse *ke;
125	struct thread *td;
126	struct ksegrp *kg;
127
128#if defined(SMP) && defined(__i386__)
129	if (smp_active == 0 && PCPU_GET(cpuid) != 0) {
130		/* Shutting down, run idlethread on AP's */
131		td = PCPU_GET(idlethread);
132		ke = td->td_kse;
133		CTR1(KTR_RUNQ, "choosethread: td=%p (idle)", td);
134		ke->ke_flags |= KEF_DIDRUN;
135		TD_SET_RUNNING(td);
136		return (td);
137	}
138#endif
139
140retry:
141	ke = sched_choose();
142	if (ke) {
143		td = ke->ke_thread;
144		KASSERT((td->td_kse == ke), ("kse/thread mismatch"));
145		kg = ke->ke_ksegrp;
146		if (td->td_proc->p_flag & P_THREADED) {
147			if (kg->kg_last_assigned == td) {
148				kg->kg_last_assigned = TAILQ_PREV(td,
149				    threadqueue, td_runq);
150			}
151			TAILQ_REMOVE(&kg->kg_runq, td, td_runq);
152		}
153		kg->kg_runnable--;
154		CTR2(KTR_RUNQ, "choosethread: td=%p pri=%d",
155		    td, td->td_priority);
156	} else {
157		/* Simulate runq_choose() having returned the idle thread */
158		td = PCPU_GET(idlethread);
159		ke = td->td_kse;
160		CTR1(KTR_RUNQ, "choosethread: td=%p (idle)", td);
161	}
162	ke->ke_flags |= KEF_DIDRUN;
163
164	/*
165	 * Only allow non system threads to run in panic
166	 * if they are the one we are tracing.  (I think.. [JRE])
167	 */
168	if (panicstr && ((td->td_proc->p_flag & P_SYSTEM) == 0 &&
169	    (td->td_flags & TDF_INPANIC) == 0))
170		goto retry;
171
172	TD_SET_RUNNING(td);
173	return (td);
174}
175
176/*
177 * Given a surplus KSE, either assign a new runable thread to it
178 * (and put it in the run queue) or put it in the ksegrp's idle KSE list.
179 * Assumes that the original thread is not runnable.
180 */
181void
182kse_reassign(struct kse *ke)
183{
184	struct ksegrp *kg;
185	struct thread *td;
186	struct thread *original;
187
188	mtx_assert(&sched_lock, MA_OWNED);
189	original = ke->ke_thread;
190	KASSERT(original == NULL || TD_IS_INHIBITED(original),
191    	    ("reassigning KSE with runnable thread"));
192	kg = ke->ke_ksegrp;
193	if (original)
194		original->td_kse = NULL;
195
196	/*
197	 * Find the first unassigned thread
198	 */
199	if ((td = kg->kg_last_assigned) != NULL)
200		td = TAILQ_NEXT(td, td_runq);
201	else
202		td = TAILQ_FIRST(&kg->kg_runq);
203
204	/*
205	 * If we found one, assign it the kse, otherwise idle the kse.
206	 */
207	if (td) {
208		kg->kg_last_assigned = td;
209		td->td_kse = ke;
210		ke->ke_thread = td;
211		sched_add(ke);
212		CTR2(KTR_RUNQ, "kse_reassign: ke%p -> td%p", ke, td);
213		return;
214	}
215
216	ke->ke_state = KES_IDLE;
217	ke->ke_thread = NULL;
218	TAILQ_INSERT_TAIL(&kg->kg_iq, ke, ke_kgrlist);
219	kg->kg_idle_kses++;
220	CTR1(KTR_RUNQ, "kse_reassign: ke%p on idle queue", ke);
221	return;
222}
223
224#if 0
225/*
226 * Remove a thread from its KSEGRP's run queue.
227 * This in turn may remove it from a KSE if it was already assigned
228 * to one, possibly causing a new thread to be assigned to the KSE
229 * and the KSE getting a new priority.
230 */
231static void
232remrunqueue(struct thread *td)
233{
234	struct thread *td2, *td3;
235	struct ksegrp *kg;
236	struct kse *ke;
237
238	mtx_assert(&sched_lock, MA_OWNED);
239	KASSERT((TD_ON_RUNQ(td)), ("remrunqueue: Bad state on run queue"));
240	kg = td->td_ksegrp;
241	ke = td->td_kse;
242	CTR1(KTR_RUNQ, "remrunqueue: td%p", td);
243	kg->kg_runnable--;
244	TD_SET_CAN_RUN(td);
245	/*
246	 * If it is not a threaded process, take the shortcut.
247	 */
248	if ((td->td_proc->p_flag & P_THREADED) == 0) {
249		/* Bring its kse with it, leave the thread attached */
250		sched_rem(ke);
251		ke->ke_state = KES_THREAD;
252		return;
253	}
254   	td3 = TAILQ_PREV(td, threadqueue, td_runq);
255	TAILQ_REMOVE(&kg->kg_runq, td, td_runq);
256	if (ke) {
257		/*
258		 * This thread has been assigned to a KSE.
259		 * We need to dissociate it and try assign the
260		 * KSE to the next available thread. Then, we should
261		 * see if we need to move the KSE in the run queues.
262		 */
263		sched_rem(ke);
264		ke->ke_state = KES_THREAD;
265		td2 = kg->kg_last_assigned;
266		KASSERT((td2 != NULL), ("last assigned has wrong value"));
267		if (td2 == td)
268			kg->kg_last_assigned = td3;
269		kse_reassign(ke);
270	}
271}
272#endif
273
274/*
275 * Change the priority of a thread that is on the run queue.
276 */
277void
278adjustrunqueue( struct thread *td, int newpri)
279{
280	struct ksegrp *kg;
281	struct kse *ke;
282
283	mtx_assert(&sched_lock, MA_OWNED);
284	KASSERT((TD_ON_RUNQ(td)), ("adjustrunqueue: Bad state on run queue"));
285
286	ke = td->td_kse;
287	CTR1(KTR_RUNQ, "adjustrunqueue: td%p", td);
288	/*
289	 * If it is not a threaded process, take the shortcut.
290	 */
291	if ((td->td_proc->p_flag & P_THREADED) == 0) {
292		/* We only care about the kse in the run queue. */
293		td->td_priority = newpri;
294		if (ke->ke_rqindex != (newpri / RQ_PPQ)) {
295			sched_rem(ke);
296			sched_add(ke);
297		}
298		return;
299	}
300
301	/* It is a threaded process */
302	kg = td->td_ksegrp;
303	kg->kg_runnable--;
304	TD_SET_CAN_RUN(td);
305	if (ke) {
306		if (kg->kg_last_assigned == td) {
307			kg->kg_last_assigned =
308			    TAILQ_PREV(td, threadqueue, td_runq);
309		}
310		sched_rem(ke);
311	}
312	TAILQ_REMOVE(&kg->kg_runq, td, td_runq);
313	td->td_priority = newpri;
314	setrunqueue(td);
315}
316
317void
318setrunqueue(struct thread *td)
319{
320	struct kse *ke;
321	struct ksegrp *kg;
322	struct thread *td2;
323	struct thread *tda;
324
325	CTR1(KTR_RUNQ, "setrunqueue: td%p", td);
326	mtx_assert(&sched_lock, MA_OWNED);
327	KASSERT((TD_CAN_RUN(td) || TD_IS_RUNNING(td)),
328	    ("setrunqueue: bad thread state"));
329	TD_SET_RUNQ(td);
330	kg = td->td_ksegrp;
331	kg->kg_runnable++;
332	if ((td->td_proc->p_flag & P_THREADED) == 0) {
333		/*
334		 * Common path optimisation: Only one of everything
335		 * and the KSE is always already attached.
336		 * Totally ignore the ksegrp run queue.
337		 */
338		sched_add(td->td_kse);
339		return;
340	}
341
342	tda = kg->kg_last_assigned;
343	if ((ke = td->td_kse) == NULL) {
344		if (kg->kg_idle_kses) {
345			/*
346			 * There is a free one so it's ours for the asking..
347			 */
348			ke = TAILQ_FIRST(&kg->kg_iq);
349			TAILQ_REMOVE(&kg->kg_iq, ke, ke_kgrlist);
350			ke->ke_state = KES_THREAD;
351			kg->kg_idle_kses--;
352		} else if (tda && (tda->td_priority > td->td_priority)) {
353			/*
354			 * None free, but there is one we can commandeer.
355			 */
356			ke = tda->td_kse;
357			tda->td_kse = NULL;
358			ke->ke_thread = NULL;
359			tda = kg->kg_last_assigned =
360		    	    TAILQ_PREV(tda, threadqueue, td_runq);
361			sched_rem(ke);
362		}
363	} else {
364		/*
365		 * Temporarily disassociate so it looks like the other cases.
366		 */
367		ke->ke_thread = NULL;
368		td->td_kse = NULL;
369	}
370
371	/*
372	 * Add the thread to the ksegrp's run queue at
373	 * the appropriate place.
374	 */
375	TAILQ_FOREACH(td2, &kg->kg_runq, td_runq) {
376		if (td2->td_priority > td->td_priority) {
377			TAILQ_INSERT_BEFORE(td2, td, td_runq);
378			break;
379		}
380	}
381	if (td2 == NULL) {
382		/* We ran off the end of the TAILQ or it was empty. */
383		TAILQ_INSERT_TAIL(&kg->kg_runq, td, td_runq);
384	}
385
386	/*
387	 * If we have a ke to use, then put it on the run queue and
388	 * If needed, readjust the last_assigned pointer.
389	 */
390	if (ke) {
391		if (tda == NULL) {
392			/*
393			 * No pre-existing last assigned so whoever is first
394			 * gets the KSE we brought in.. (maybe us)
395			 */
396			td2 = TAILQ_FIRST(&kg->kg_runq);
397			KASSERT((td2->td_kse == NULL),
398			    ("unexpected ke present"));
399			td2->td_kse = ke;
400			ke->ke_thread = td2;
401			kg->kg_last_assigned = td2;
402		} else if (tda->td_priority > td->td_priority) {
403			/*
404			 * It's ours, grab it, but last_assigned is past us
405			 * so don't change it.
406			 */
407			td->td_kse = ke;
408			ke->ke_thread = td;
409		} else {
410			/*
411			 * We are past last_assigned, so
412			 * put the new kse on whatever is next,
413			 * which may or may not be us.
414			 */
415			td2 = TAILQ_NEXT(tda, td_runq);
416			kg->kg_last_assigned = td2;
417			td2->td_kse = ke;
418			ke->ke_thread = td2;
419		}
420		sched_add(ke);
421	}
422}
423
424/************************************************************************
425 * Critical section marker functions					*
426 ************************************************************************/
427/* Critical sections that prevent preemption. */
428void
429critical_enter(void)
430{
431	struct thread *td;
432
433	td = curthread;
434	if (td->td_critnest == 0)
435		cpu_critical_enter();
436	td->td_critnest++;
437}
438
439void
440critical_exit(void)
441{
442	struct thread *td;
443
444	td = curthread;
445	if (td->td_critnest == 1) {
446		td->td_critnest = 0;
447		cpu_critical_exit();
448	} else {
449		td->td_critnest--;
450	}
451}
452
453
454/************************************************************************
455 * SYSTEM RUN QUEUE manipulations and tests				*
456 ************************************************************************/
457/*
458 * Initialize a run structure.
459 */
460void
461runq_init(struct runq *rq)
462{
463	int i;
464
465	bzero(rq, sizeof *rq);
466	for (i = 0; i < RQ_NQS; i++)
467		TAILQ_INIT(&rq->rq_queues[i]);
468}
469
470/*
471 * Clear the status bit of the queue corresponding to priority level pri,
472 * indicating that it is empty.
473 */
474static __inline void
475runq_clrbit(struct runq *rq, int pri)
476{
477	struct rqbits *rqb;
478
479	rqb = &rq->rq_status;
480	CTR4(KTR_RUNQ, "runq_clrbit: bits=%#x %#x bit=%#x word=%d",
481	    rqb->rqb_bits[RQB_WORD(pri)],
482	    rqb->rqb_bits[RQB_WORD(pri)] & ~RQB_BIT(pri),
483	    RQB_BIT(pri), RQB_WORD(pri));
484	rqb->rqb_bits[RQB_WORD(pri)] &= ~RQB_BIT(pri);
485}
486
487/*
488 * Find the index of the first non-empty run queue.  This is done by
489 * scanning the status bits, a set bit indicates a non-empty queue.
490 */
491static __inline int
492runq_findbit(struct runq *rq)
493{
494	struct rqbits *rqb;
495	int pri;
496	int i;
497
498	rqb = &rq->rq_status;
499	for (i = 0; i < RQB_LEN; i++)
500		if (rqb->rqb_bits[i]) {
501			pri = RQB_FFS(rqb->rqb_bits[i]) + (i << RQB_L2BPW);
502			CTR3(KTR_RUNQ, "runq_findbit: bits=%#x i=%d pri=%d",
503			    rqb->rqb_bits[i], i, pri);
504			return (pri);
505		}
506
507	return (-1);
508}
509
510/*
511 * Set the status bit of the queue corresponding to priority level pri,
512 * indicating that it is non-empty.
513 */
514static __inline void
515runq_setbit(struct runq *rq, int pri)
516{
517	struct rqbits *rqb;
518
519	rqb = &rq->rq_status;
520	CTR4(KTR_RUNQ, "runq_setbit: bits=%#x %#x bit=%#x word=%d",
521	    rqb->rqb_bits[RQB_WORD(pri)],
522	    rqb->rqb_bits[RQB_WORD(pri)] | RQB_BIT(pri),
523	    RQB_BIT(pri), RQB_WORD(pri));
524	rqb->rqb_bits[RQB_WORD(pri)] |= RQB_BIT(pri);
525}
526
527/*
528 * Add the KSE to the queue specified by its priority, and set the
529 * corresponding status bit.
530 */
531void
532runq_add(struct runq *rq, struct kse *ke)
533{
534	struct rqhead *rqh;
535	int pri;
536
537	pri = ke->ke_thread->td_priority / RQ_PPQ;
538	ke->ke_rqindex = pri;
539	runq_setbit(rq, pri);
540	rqh = &rq->rq_queues[pri];
541	CTR4(KTR_RUNQ, "runq_add: p=%p pri=%d %d rqh=%p",
542	    ke->ke_proc, ke->ke_thread->td_priority, pri, rqh);
543	TAILQ_INSERT_TAIL(rqh, ke, ke_procq);
544}
545
546/*
547 * Return true if there are runnable processes of any priority on the run
548 * queue, false otherwise.  Has no side effects, does not modify the run
549 * queue structure.
550 */
551int
552runq_check(struct runq *rq)
553{
554	struct rqbits *rqb;
555	int i;
556
557	rqb = &rq->rq_status;
558	for (i = 0; i < RQB_LEN; i++)
559		if (rqb->rqb_bits[i]) {
560			CTR2(KTR_RUNQ, "runq_check: bits=%#x i=%d",
561			    rqb->rqb_bits[i], i);
562			return (1);
563		}
564	CTR0(KTR_RUNQ, "runq_check: empty");
565
566	return (0);
567}
568
569/*
570 * Find the highest priority process on the run queue.
571 */
572struct kse *
573runq_choose(struct runq *rq)
574{
575	struct rqhead *rqh;
576	struct kse *ke;
577	int pri;
578
579	mtx_assert(&sched_lock, MA_OWNED);
580	while ((pri = runq_findbit(rq)) != -1) {
581		rqh = &rq->rq_queues[pri];
582		ke = TAILQ_FIRST(rqh);
583		KASSERT(ke != NULL, ("runq_choose: no proc on busy queue"));
584		CTR3(KTR_RUNQ,
585		    "runq_choose: pri=%d kse=%p rqh=%p", pri, ke, rqh);
586		return (ke);
587	}
588	CTR1(KTR_RUNQ, "runq_choose: idleproc pri=%d", pri);
589
590	return (NULL);
591}
592
593/*
594 * Remove the KSE from the queue specified by its priority, and clear the
595 * corresponding status bit if the queue becomes empty.
596 * Caller must set ke->ke_state afterwards.
597 */
598void
599runq_remove(struct runq *rq, struct kse *ke)
600{
601	struct rqhead *rqh;
602	int pri;
603
604	KASSERT(ke->ke_proc->p_sflag & PS_INMEM,
605		("runq_remove: process swapped out"));
606	pri = ke->ke_rqindex;
607	rqh = &rq->rq_queues[pri];
608	CTR4(KTR_RUNQ, "runq_remove: p=%p pri=%d %d rqh=%p",
609	    ke, ke->ke_thread->td_priority, pri, rqh);
610	KASSERT(ke != NULL, ("runq_remove: no proc on busy queue"));
611	TAILQ_REMOVE(rqh, ke, ke_procq);
612	if (TAILQ_EMPTY(rqh)) {
613		CTR0(KTR_RUNQ, "runq_remove: empty");
614		runq_clrbit(rq, pri);
615	}
616}
617
618#if 0
619void
620panc(char *string1, char *string2)
621{
622	printf("%s", string1);
623	Debugger(string2);
624}
625
626void
627thread_sanity_check(struct thread *td, char *string)
628{
629	struct proc *p;
630	struct ksegrp *kg;
631	struct kse *ke;
632	struct thread *td2 = NULL;
633	unsigned int prevpri;
634	int	saw_lastassigned = 0;
635	int unassigned = 0;
636	int assigned = 0;
637
638	p = td->td_proc;
639	kg = td->td_ksegrp;
640	ke = td->td_kse;
641
642
643	if (ke) {
644		if (p != ke->ke_proc) {
645			panc(string, "wrong proc");
646		}
647		if (ke->ke_thread != td) {
648			panc(string, "wrong thread");
649		}
650	}
651
652	if ((p->p_flag & P_THREADED) == 0) {
653		if (ke == NULL) {
654			panc(string, "non KSE thread lost kse");
655		}
656	} else {
657		prevpri = 0;
658		saw_lastassigned = 0;
659		unassigned = 0;
660		assigned = 0;
661		TAILQ_FOREACH(td2, &kg->kg_runq, td_runq) {
662			if (td2->td_priority < prevpri) {
663				panc(string, "thread runqueue unosorted");
664			}
665			if ((td2->td_state == TDS_RUNQ) &&
666			    td2->td_kse &&
667			    (td2->td_kse->ke_state != KES_ONRUNQ)) {
668				panc(string, "KSE wrong state");
669			}
670			prevpri = td2->td_priority;
671			if (td2->td_kse) {
672				assigned++;
673				if (unassigned) {
674					panc(string, "unassigned before assigned");
675				}
676 				if  (kg->kg_last_assigned == NULL) {
677					panc(string, "lastassigned corrupt");
678				}
679				if (saw_lastassigned) {
680					panc(string, "last assigned not last");
681				}
682				if (td2->td_kse->ke_thread != td2) {
683					panc(string, "mismatched kse/thread");
684				}
685			} else {
686				unassigned++;
687			}
688			if (td2 == kg->kg_last_assigned) {
689				saw_lastassigned = 1;
690				if (td2->td_kse == NULL) {
691					panc(string, "last assigned not assigned");
692				}
693			}
694		}
695		if (kg->kg_last_assigned && (saw_lastassigned == 0)) {
696			panc(string, "where on earth does lastassigned point?");
697		}
698#if 0
699		FOREACH_THREAD_IN_GROUP(kg, td2) {
700			if (((td2->td_flags & TDF_UNBOUND) == 0) &&
701			    (TD_ON_RUNQ(td2))) {
702				assigned++;
703				if (td2->td_kse == NULL) {
704					panc(string, "BOUND thread with no KSE");
705				}
706			}
707		}
708#endif
709#if 0
710		if ((unassigned + assigned) != kg->kg_runnable) {
711			panc(string, "wrong number in runnable");
712		}
713#endif
714	}
715	if (assigned == 12345) {
716		printf("%p %p %p %p %p %d, %d",
717		    td, td2, ke, kg, p, assigned, saw_lastassigned);
718	}
719}
720#endif
721
722