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