xref: /freebsd/sys/kern/kern_switch.c (revision e602ba25fd1f9a7ea2215c01f470c08f140de809)
1dba6c5a6SPeter Wemm /*
2d5a08a60SJake Burkholder  * Copyright (c) 2001 Jake Burkholder <jake@FreeBSD.org>
3d5a08a60SJake Burkholder  * All rights reserved.
4dba6c5a6SPeter Wemm  *
5dba6c5a6SPeter Wemm  * Redistribution and use in source and binary forms, with or without
6dba6c5a6SPeter Wemm  * modification, are permitted provided that the following conditions
7dba6c5a6SPeter Wemm  * are met:
8dba6c5a6SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
9dba6c5a6SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
10dba6c5a6SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
11dba6c5a6SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
12dba6c5a6SPeter Wemm  *    documentation and/or other materials provided with the distribution.
13dba6c5a6SPeter Wemm  *
14dba6c5a6SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15dba6c5a6SPeter Wemm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16dba6c5a6SPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17dba6c5a6SPeter Wemm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18dba6c5a6SPeter Wemm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19dba6c5a6SPeter Wemm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20dba6c5a6SPeter Wemm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21dba6c5a6SPeter Wemm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22dba6c5a6SPeter Wemm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23dba6c5a6SPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24dba6c5a6SPeter Wemm  * SUCH DAMAGE.
25dba6c5a6SPeter Wemm  *
26dba6c5a6SPeter Wemm  * $FreeBSD$
27dba6c5a6SPeter Wemm  */
28dba6c5a6SPeter Wemm 
29e602ba25SJulian Elischer /***
30e602ba25SJulian Elischer 
31e602ba25SJulian Elischer Here is the logic..
32e602ba25SJulian Elischer 
33e602ba25SJulian Elischer If there are N processors, then there are at most N KSEs (kernel
34e602ba25SJulian Elischer schedulable entities) working to process threads that belong to a
35e602ba25SJulian Elischer KSEGOUP (kg). If there are X of these KSEs actually running at the
36e602ba25SJulian Elischer moment in question, then there are at most M (N-X) of these KSEs on
37e602ba25SJulian Elischer the run queue, as running KSEs are not on the queue.
38e602ba25SJulian Elischer 
39e602ba25SJulian Elischer Runnable threads are queued off the KSEGROUP in priority order.
40e602ba25SJulian Elischer If there are M or more threads runnable, the top M threads
41e602ba25SJulian Elischer (by priority) are 'preassigned' to the M KSEs not running. The KSEs take
42e602ba25SJulian Elischer their priority from those threads and are put on the run queue.
43e602ba25SJulian Elischer 
44e602ba25SJulian Elischer The last thread that had a priority high enough to have a KSE associated
45e602ba25SJulian Elischer with it, AND IS ON THE RUN QUEUE is pointed to by
46e602ba25SJulian Elischer kg->kg_last_assigned. If no threads queued off the KSEGROUP have KSEs
47e602ba25SJulian Elischer assigned as all the available KSEs are activly running, or because there
48e602ba25SJulian Elischer are no threads queued, that pointer is NULL.
49e602ba25SJulian Elischer 
50e602ba25SJulian Elischer When a KSE is removed from the run queue to become runnable, we know
51e602ba25SJulian Elischer it was associated with the highest priority thread in the queue (at the head
52e602ba25SJulian Elischer of the queue). If it is also the last assigned we know M was 1 and must
53e602ba25SJulian Elischer now be 0. Since the thread is no longer queued that pointer must be
54e602ba25SJulian Elischer removed from it. Since we know there were no more KSEs available,
55e602ba25SJulian Elischer (M was 1 and is now 0) and since we are not FREEING our KSE
56e602ba25SJulian Elischer but using it, we know there are STILL no more KSEs available, we can prove
57e602ba25SJulian Elischer that the next thread in the ksegrp list will not have a KSE to assign to
58e602ba25SJulian Elischer it, so we can show that the pointer must be made 'invalid' (NULL).
59e602ba25SJulian Elischer 
60e602ba25SJulian Elischer The pointer exists so that when a new thread is made runnable, it can
61e602ba25SJulian Elischer have its priority compared with the last assigned thread to see if
62e602ba25SJulian Elischer it should 'steal' its KSE or not.. i.e. is it 'earlier'
63e602ba25SJulian Elischer on the list than that thread or later.. If it's earlier, then the KSE is
64e602ba25SJulian Elischer removed from the last assigned (which is now not assigned a KSE)
65e602ba25SJulian Elischer and reassigned to the new thread, which is placed earlier in the list.
66e602ba25SJulian Elischer The pointer is then backed up to the previous thread (which may or may not
67e602ba25SJulian Elischer be the new thread).
68e602ba25SJulian Elischer 
69e602ba25SJulian Elischer When a thread sleeps or is removed, the KSE becomes available and if there
70e602ba25SJulian Elischer are queued threads that are not assigned KSEs, the highest priority one of
71e602ba25SJulian Elischer them is assigned the KSE, which is then placed back on the run queue at
72e602ba25SJulian Elischer the approipriate place, and the kg->kg_last_assigned pointer is adjusted down
73e602ba25SJulian Elischer to point to it.
74e602ba25SJulian Elischer 
75e602ba25SJulian Elischer The following diagram shows 2 KSEs and 3 threads from a single process.
76e602ba25SJulian Elischer 
77e602ba25SJulian Elischer  RUNQ: --->KSE---KSE--...    (KSEs queued at priorities from threads)
78e602ba25SJulian Elischer               \    \____
79e602ba25SJulian Elischer                \        \
80e602ba25SJulian Elischer     KSEGROUP---thread--thread--thread    (queued in priority order)
81e602ba25SJulian Elischer         \                 /
82e602ba25SJulian Elischer          \_______________/
83e602ba25SJulian Elischer           (last_assigned)
84e602ba25SJulian Elischer 
85e602ba25SJulian Elischer The result of this scheme is that the M available KSEs are always
86e602ba25SJulian Elischer queued at the priorities they have inherrited from the M highest priority
87e602ba25SJulian Elischer threads for that KSEGROUP. If this situation changes, the KSEs are
88e602ba25SJulian Elischer reassigned to keep this true.
89e602ba25SJulian Elischer 
90e602ba25SJulian Elischer */
91e602ba25SJulian Elischer 
92dba6c5a6SPeter Wemm #include <sys/param.h>
93dba6c5a6SPeter Wemm #include <sys/systm.h>
94dba6c5a6SPeter Wemm #include <sys/kernel.h>
950384fff8SJason Evans #include <sys/ktr.h>
96f34fa851SJohn Baldwin #include <sys/lock.h>
9735e0e5b3SJohn Baldwin #include <sys/mutex.h>
98dba6c5a6SPeter Wemm #include <sys/proc.h>
99dba6c5a6SPeter Wemm #include <sys/queue.h>
100182da820SMatthew Dillon #include <machine/critical.h>
101dba6c5a6SPeter Wemm 
102d2ac2316SJake Burkholder CTASSERT((RQB_BPW * RQB_LEN) == RQ_NQS);
103d2ac2316SJake Burkholder 
104dba6c5a6SPeter Wemm /*
105d5a08a60SJake Burkholder  * Global run queue.
106dba6c5a6SPeter Wemm  */
107d5a08a60SJake Burkholder static struct runq runq;
108d5a08a60SJake Burkholder SYSINIT(runq, SI_SUB_RUN_QUEUE, SI_ORDER_FIRST, runq_init, &runq)
109dba6c5a6SPeter Wemm 
110e602ba25SJulian Elischer static void runq_readjust(struct runq *rq, struct kse *ke);
111e602ba25SJulian Elischer /************************************************************************
112e602ba25SJulian Elischer  * Functions that manipulate runnability from a thread perspective.	*
113e602ba25SJulian Elischer  ************************************************************************/
114dba6c5a6SPeter Wemm 
115e602ba25SJulian Elischer /*
116e602ba25SJulian Elischer  * Select the KSE that will be run next.  From that find the thread, and x
117e602ba25SJulian Elischer  * remove it from the KSEGRP's run queue.  If there is thread clustering,
118e602ba25SJulian Elischer  * this will be what does it.
119e602ba25SJulian Elischer  */
120b40ce416SJulian Elischer struct thread *
121b40ce416SJulian Elischer choosethread(void)
122dba6c5a6SPeter Wemm {
123e602ba25SJulian Elischer 	struct kse *ke;
124e602ba25SJulian Elischer 	struct thread *td;
125e602ba25SJulian Elischer 	struct ksegrp *kg;
126e602ba25SJulian Elischer 
127e602ba25SJulian Elischer 	if ((ke = runq_choose(&runq))) {
128e602ba25SJulian Elischer 		td = ke->ke_thread;
129e602ba25SJulian Elischer 		KASSERT((td->td_kse == ke), ("kse/thread mismatch"));
130e602ba25SJulian Elischer 		kg = ke->ke_ksegrp;
131e602ba25SJulian Elischer 		if (td->td_flags & TDF_UNBOUND) {
132e602ba25SJulian Elischer 			TAILQ_REMOVE(&kg->kg_runq, td, td_runq);
133e602ba25SJulian Elischer 			if (kg->kg_last_assigned == td)
134e602ba25SJulian Elischer 				if (TAILQ_PREV(td, threadqueue, td_runq)
135e602ba25SJulian Elischer 				    != NULL)
136e602ba25SJulian Elischer 					printf("Yo MAMA!\n");
137e602ba25SJulian Elischer 				kg->kg_last_assigned = TAILQ_PREV(td,
138e602ba25SJulian Elischer 				    threadqueue, td_runq);
139e602ba25SJulian Elischer 			/*
140e602ba25SJulian Elischer 			 *  If we have started running an upcall,
141e602ba25SJulian Elischer 			 * Then TDF_UNBOUND WAS set because the thread was
142e602ba25SJulian Elischer 			 * created without a KSE. Now that we have one,
143e602ba25SJulian Elischer 			 * and it is our time to run, we make sure
144e602ba25SJulian Elischer 			 * that BOUND semantics apply for the rest of
145e602ba25SJulian Elischer 			 * the journey to userland, and into the UTS.
146e602ba25SJulian Elischer 			 */
147e602ba25SJulian Elischer #ifdef	NOTYET
148e602ba25SJulian Elischer 			if (td->td_flags & TDF_UPCALLING)
149e602ba25SJulian Elischer 				tdf->td_flags &= ~TDF_UNBOUND;
150e602ba25SJulian Elischer #endif
151e602ba25SJulian Elischer 		}
152e602ba25SJulian Elischer 		kg->kg_runnable--;
153e602ba25SJulian Elischer 		CTR2(KTR_RUNQ, "choosethread: td=%p pri=%d",
154e602ba25SJulian Elischer 		    td, td->td_priority);
155e602ba25SJulian Elischer 	} else {
156e602ba25SJulian Elischer 		/* Pretend the idle thread was on the run queue. */
157e602ba25SJulian Elischer 		td = PCPU_GET(idlethread);
158e602ba25SJulian Elischer 		/* Simulate that it was on the run queue */
159e602ba25SJulian Elischer 		td->td_state = TDS_RUNQ;
160e602ba25SJulian Elischer 		td->td_kse->ke_state = KES_UNQUEUED;
161e602ba25SJulian Elischer 		CTR1(KTR_RUNQ, "choosethread: td=%p (idle)", td);
162e602ba25SJulian Elischer 	}
163e602ba25SJulian Elischer 	thread_sanity_check(td);
164e602ba25SJulian Elischer 	return (td);
165e602ba25SJulian Elischer }
166e602ba25SJulian Elischer 
167e602ba25SJulian Elischer /*
168e602ba25SJulian Elischer  * Given a KSE (now surplus), either assign a new runable thread to it
169e602ba25SJulian Elischer  * (and put it in the run queue) or put it in the ksegrp's idle KSE list.
170e602ba25SJulian Elischer  * Assumes the kse is not linked to any threads any more. (has been cleaned).
171e602ba25SJulian Elischer  */
172e602ba25SJulian Elischer void
173e602ba25SJulian Elischer kse_reassign(struct kse *ke)
174e602ba25SJulian Elischer {
175e602ba25SJulian Elischer 	struct ksegrp *kg;
176e602ba25SJulian Elischer 	struct thread *td;
177e602ba25SJulian Elischer 
178e602ba25SJulian Elischer 	kg = ke->ke_ksegrp;
179e602ba25SJulian Elischer 
180e602ba25SJulian Elischer KASSERT((ke->ke_state != KES_ONRUNQ), ("kse_reassigning non-free kse"));
181e602ba25SJulian Elischer 	/*
182e602ba25SJulian Elischer 	 * Find the first unassigned thread
183e602ba25SJulian Elischer 	 * If there is a 'last assigned' then see what's next.
184e602ba25SJulian Elischer 	 * otherwise look at what is first.
185e602ba25SJulian Elischer 	 */
186e602ba25SJulian Elischer 	if ((td = kg->kg_last_assigned)) {
187e602ba25SJulian Elischer 		td = TAILQ_NEXT(td, td_runq);
188e602ba25SJulian Elischer 	} else {
189e602ba25SJulian Elischer 		td = TAILQ_FIRST(&kg->kg_runq);
190e602ba25SJulian Elischer 	}
191e602ba25SJulian Elischer 
192e602ba25SJulian Elischer 	/*
193e602ba25SJulian Elischer 	 * If we found one assign it the kse, otherwise idle the kse.
194e602ba25SJulian Elischer 	 */
195e602ba25SJulian Elischer 	if (td) {
196e602ba25SJulian Elischer 		thread_sanity_check(td);
197e602ba25SJulian Elischer 		kg->kg_last_assigned = td;
198e602ba25SJulian Elischer 		td->td_kse = ke;
199e602ba25SJulian Elischer 		ke->ke_thread = td;
200e602ba25SJulian Elischer 		runq_add(&runq, ke);
201e602ba25SJulian Elischer 		CTR2(KTR_RUNQ, "kse_reassign: ke%p -> td%p", ke, td);
202e602ba25SJulian Elischer 	} else {
203e602ba25SJulian Elischer 		KASSERT((ke->ke_state != KES_IDLE), ("kse already idle"));
204e602ba25SJulian Elischer KASSERT((ke->ke_kgrlist.tqe_next != ke), ("linked to self!"));
205e602ba25SJulian Elischer 		ke->ke_state = KES_IDLE;
206e602ba25SJulian Elischer 		ke->ke_thread = NULL;
207e602ba25SJulian Elischer 		TAILQ_INSERT_HEAD(&kg->kg_iq, ke, ke_kgrlist);
208e602ba25SJulian Elischer 		kg->kg_idle_kses++;
209e602ba25SJulian Elischer 		CTR1(KTR_RUNQ, "kse_reassign: ke%p idled", ke);
210e602ba25SJulian Elischer KASSERT((ke->ke_kgrlist.tqe_next != ke), ("linked to self2!"));
211e602ba25SJulian Elischer 	}
212d5a08a60SJake Burkholder }
213d5a08a60SJake Burkholder 
214d5a08a60SJake Burkholder int
215e602ba25SJulian Elischer kserunnable(void)
216d5a08a60SJake Burkholder {
217d5a08a60SJake Burkholder 	return runq_check(&runq);
218d5a08a60SJake Burkholder }
219d5a08a60SJake Burkholder 
220e602ba25SJulian Elischer /*
221e602ba25SJulian Elischer  * Remove a thread from its KSEGRP's run queue.
222e602ba25SJulian Elischer  * This in turn may remove it from a KSE if it was already assigned
223e602ba25SJulian Elischer  * to one, possibly causing a new thread to be assigned to the KSE
224e602ba25SJulian Elischer  * and the KSE getting a new priority (unless it's a BOUND thread/KSE pair).
225e602ba25SJulian Elischer  */
226d5a08a60SJake Burkholder void
227b40ce416SJulian Elischer remrunqueue(struct thread *td)
228d5a08a60SJake Burkholder {
229e602ba25SJulian Elischer 	struct thread *td2, *td3;
230e602ba25SJulian Elischer 	struct ksegrp *kg;
231e602ba25SJulian Elischer 	struct kse *ke;
232e602ba25SJulian Elischer 
233e602ba25SJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
234e602ba25SJulian Elischer 	thread_sanity_check(td);
235e602ba25SJulian Elischer 	KASSERT ((td->td_state == TDS_RUNQ),
236e602ba25SJulian Elischer 		("remrunqueue: Bad state on run queue"));
237e602ba25SJulian Elischer 	kg = td->td_ksegrp;
238e602ba25SJulian Elischer 	ke = td->td_kse;
239e602ba25SJulian Elischer 	/*
240e602ba25SJulian Elischer 	 * If it's a bound thread/KSE pair, take the shortcut. All non-KSE
241e602ba25SJulian Elischer 	 * threads are BOUND.
242e602ba25SJulian Elischer 	 */
243e602ba25SJulian Elischer 	CTR1(KTR_RUNQ, "remrunqueue: td%p", td);
244e602ba25SJulian Elischer 	td->td_state = TDS_UNQUEUED;
245e602ba25SJulian Elischer 	kg->kg_runnable--;
246e602ba25SJulian Elischer 	if ((td->td_flags & TDF_UNBOUND) == 0)  {
247e602ba25SJulian Elischer 		/* Bring its kse with it, leave the thread attached */
248e602ba25SJulian Elischer 		runq_remove(&runq, ke);
249e602ba25SJulian Elischer 		ke->ke_state = KES_UNQUEUED;
250e602ba25SJulian Elischer 		return;
251d5a08a60SJake Burkholder 	}
252e602ba25SJulian Elischer 	if (ke) {
253e602ba25SJulian Elischer 		/*
254e602ba25SJulian Elischer 		 * This thread has been assigned to a KSE.
255e602ba25SJulian Elischer 		 * We need to dissociate it and try assign the
256e602ba25SJulian Elischer 		 * KSE to the next available thread. Then, we should
257e602ba25SJulian Elischer 		 * see if we need to move the KSE in the run queues.
258e602ba25SJulian Elischer 		 */
259e602ba25SJulian Elischer 		td2 = kg->kg_last_assigned;
260e602ba25SJulian Elischer 		KASSERT((td2 != NULL), ("last assigned has wrong value "));
261e602ba25SJulian Elischer 		td->td_kse = NULL;
262e602ba25SJulian Elischer 		if ((td3 = TAILQ_NEXT(td2, td_runq))) {
263e602ba25SJulian Elischer 			KASSERT(td3 != td, ("td3 somehow matched td"));
264e602ba25SJulian Elischer 			/*
265e602ba25SJulian Elischer 			 * Give the next unassigned thread to the KSE
266e602ba25SJulian Elischer 			 * so the number of runnable KSEs remains
267e602ba25SJulian Elischer 			 * constant.
268e602ba25SJulian Elischer 			 */
269e602ba25SJulian Elischer 			td3->td_kse = ke;
270e602ba25SJulian Elischer 			ke->ke_thread = td3;
271e602ba25SJulian Elischer 			kg->kg_last_assigned = td3;
272e602ba25SJulian Elischer 			runq_readjust(&runq, ke);
273e602ba25SJulian Elischer 		} else {
274e602ba25SJulian Elischer 			/*
275e602ba25SJulian Elischer 			 * There is no unassigned thread.
276e602ba25SJulian Elischer 			 * If we were the last assigned one,
277e602ba25SJulian Elischer 			 * adjust the last assigned pointer back
278e602ba25SJulian Elischer 			 * one, which may result in NULL.
279e602ba25SJulian Elischer 			 */
280e602ba25SJulian Elischer 			if (td == td2) {
281e602ba25SJulian Elischer 				kg->kg_last_assigned =
282e602ba25SJulian Elischer 				    TAILQ_PREV(td, threadqueue, td_runq);
283e602ba25SJulian Elischer 			}
284e602ba25SJulian Elischer 			runq_remove(&runq, ke);
285e602ba25SJulian Elischer KASSERT((ke->ke_kgrlist.tqe_next != ke), ("linked to self!"));
286e602ba25SJulian Elischer 			KASSERT((ke->ke_state != KES_IDLE),
287e602ba25SJulian Elischer 			    ("kse already idle"));
288e602ba25SJulian Elischer 			ke->ke_state = KES_IDLE;
289e602ba25SJulian Elischer 			ke->ke_thread = NULL;
290e602ba25SJulian Elischer KASSERT((TAILQ_FIRST(&kg->kg_iq) != ke), ("really bad screwup"));
291e602ba25SJulian Elischer 			TAILQ_INSERT_HEAD(&kg->kg_iq, ke, ke_kgrlist);
292e602ba25SJulian Elischer 			kg->kg_idle_kses++;
293e602ba25SJulian Elischer KASSERT((ke->ke_kgrlist.tqe_next != ke), ("linked to self2!"));
294e602ba25SJulian Elischer 		}
295e602ba25SJulian Elischer 	}
296e602ba25SJulian Elischer 	TAILQ_REMOVE(&kg->kg_runq, td, td_runq);
297e602ba25SJulian Elischer 	thread_sanity_check(td);
298e602ba25SJulian Elischer }
299e602ba25SJulian Elischer 
300e602ba25SJulian Elischer #if 1 /* use the first version */
301d5a08a60SJake Burkholder 
302d5a08a60SJake Burkholder void
303b40ce416SJulian Elischer setrunqueue(struct thread *td)
304d5a08a60SJake Burkholder {
305e602ba25SJulian Elischer 	struct kse *ke;
306e602ba25SJulian Elischer 	struct ksegrp *kg;
307e602ba25SJulian Elischer 	struct thread *td2;
308e602ba25SJulian Elischer 	struct thread *tda;
309e602ba25SJulian Elischer 
310e602ba25SJulian Elischer 	CTR1(KTR_RUNQ, "setrunqueue: td%p", td);
311e602ba25SJulian Elischer 	mtx_assert(&sched_lock, MA_OWNED);
312e602ba25SJulian Elischer 	thread_sanity_check(td);
313e602ba25SJulian Elischer 	KASSERT((td->td_state != TDS_RUNQ), ("setrunqueue: bad thread state"));
314e602ba25SJulian Elischer 	td->td_state = TDS_RUNQ;
315e602ba25SJulian Elischer 	kg = td->td_ksegrp;
316e602ba25SJulian Elischer 	kg->kg_runnable++;
317e602ba25SJulian Elischer 	if ((td->td_flags & TDF_UNBOUND) == 0) {
318e602ba25SJulian Elischer 		KASSERT((td->td_kse != NULL),
319e602ba25SJulian Elischer 		    ("queueing BAD thread to run queue"));
320e602ba25SJulian Elischer 		/*
321e602ba25SJulian Elischer 		 * Common path optimisation: Only one of everything
322e602ba25SJulian Elischer 		 * and the KSE is always already attached.
323e602ba25SJulian Elischer 		 * Totally ignore the ksegrp run queue.
324e602ba25SJulian Elischer 		 */
325b40ce416SJulian Elischer 		runq_add(&runq, td->td_kse);
326e602ba25SJulian Elischer 		return;
327e602ba25SJulian Elischer 	}
328e602ba25SJulian Elischer 	/*
329e602ba25SJulian Elischer 	 * Ok, so we are threading with this thread.
330e602ba25SJulian Elischer 	 * We don't have a KSE, see if we can get one..
331e602ba25SJulian Elischer 	 */
332e602ba25SJulian Elischer 	tda = kg->kg_last_assigned;
333e602ba25SJulian Elischer 	if ((ke = td->td_kse) == NULL) {
334e602ba25SJulian Elischer 		/*
335e602ba25SJulian Elischer 		 * We will need a KSE, see if there is one..
336e602ba25SJulian Elischer 		 * First look for a free one, before getting desperate.
337e602ba25SJulian Elischer 		 * If we can't get one, our priority is not high enough..
338e602ba25SJulian Elischer 		 * that's ok..
339e602ba25SJulian Elischer 		 */
340e602ba25SJulian Elischer 		if (kg->kg_idle_kses) {
341e602ba25SJulian Elischer 			/*
342e602ba25SJulian Elischer 			 * There is a free one so it's ours for the asking..
343e602ba25SJulian Elischer 			 */
344e602ba25SJulian Elischer 			ke = TAILQ_FIRST(&kg->kg_iq);
345e602ba25SJulian Elischer KASSERT((ke->ke_kgrlist.tqe_next != ke), ("linked to self3!"));
346e602ba25SJulian Elischer 			TAILQ_REMOVE(&kg->kg_iq, ke, ke_kgrlist);
347e602ba25SJulian Elischer 			ke->ke_state = KES_UNQUEUED;
348e602ba25SJulian Elischer 			kg->kg_idle_kses--;
349e602ba25SJulian Elischer KASSERT((ke->ke_kgrlist.tqe_next != ke), ("linked to self4!"));
350e602ba25SJulian Elischer 		} else if (tda && (tda->td_priority > td->td_priority)) {
351e602ba25SJulian Elischer 			/*
352e602ba25SJulian Elischer 			 * None free, but there is one we can commandeer.
353e602ba25SJulian Elischer 			 */
354e602ba25SJulian Elischer 			ke = tda->td_kse;
355e602ba25SJulian Elischer 			tda->td_kse = NULL;
356e602ba25SJulian Elischer 			ke->ke_thread = NULL;
357e602ba25SJulian Elischer 			tda = kg->kg_last_assigned =
358e602ba25SJulian Elischer 		    	    TAILQ_PREV(tda, threadqueue, td_runq);
359e602ba25SJulian Elischer 			runq_remove(&runq, ke);
360e602ba25SJulian Elischer KASSERT((ke->ke_kgrlist.tqe_next != ke), ("linked to self5!"));
361e602ba25SJulian Elischer 		}
362e602ba25SJulian Elischer 	} else {
363e602ba25SJulian Elischer 		KASSERT(ke->ke_thread == td, ("KSE/thread mismatch"));
364e602ba25SJulian Elischer 		KASSERT(ke->ke_state != KES_IDLE, ("KSE unexpectedly idle"));
365e602ba25SJulian Elischer 		ke->ke_thread = NULL;
366e602ba25SJulian Elischer 		td->td_kse = NULL;
367d5a08a60SJake Burkholder 	}
368d5a08a60SJake Burkholder 
369e602ba25SJulian Elischer 	/*
370e602ba25SJulian Elischer 	 * Add the thread to the ksegrp's run queue at
371e602ba25SJulian Elischer 	 * the appropriate place.
372e602ba25SJulian Elischer 	 */
373e602ba25SJulian Elischer 	TAILQ_FOREACH(td2, &kg->kg_runq, td_runq) {
374e602ba25SJulian Elischer 		if (td2->td_priority > td->td_priority) {
375e602ba25SJulian Elischer 			TAILQ_INSERT_BEFORE(td2, td, td_runq);
376e602ba25SJulian Elischer 			break;
377e602ba25SJulian Elischer 		}
378e602ba25SJulian Elischer 	}
379e602ba25SJulian Elischer 	if (td2 == NULL) {
380e602ba25SJulian Elischer 		/* We ran off the end of the TAILQ or it was empty. */
381e602ba25SJulian Elischer 		TAILQ_INSERT_TAIL(&kg->kg_runq, td, td_runq);
382e602ba25SJulian Elischer 	}
383e602ba25SJulian Elischer 
384e602ba25SJulian Elischer 	/*
385e602ba25SJulian Elischer 	 * If we have a ke to use, then put it on the run queue and
386e602ba25SJulian Elischer 	 * If needed, readjust the last_assigned pointer.
387e602ba25SJulian Elischer 	 */
388e602ba25SJulian Elischer 	if (ke) {
389e602ba25SJulian Elischer 		if (tda == NULL) {
390e602ba25SJulian Elischer 			/*
391e602ba25SJulian Elischer 			 * No pre-existing last assigned so whoever is first
392e602ba25SJulian Elischer 			 * gets the KSE we borught in.. (may be us)
393e602ba25SJulian Elischer 			 */
394e602ba25SJulian Elischer 			td2 = TAILQ_FIRST(&kg->kg_runq);
395e602ba25SJulian Elischer 			KASSERT((td2->td_kse == NULL),
396e602ba25SJulian Elischer 			    ("unexpected ke present"));
397e602ba25SJulian Elischer 			td2->td_kse = ke;
398e602ba25SJulian Elischer 			ke->ke_thread = td2;
399e602ba25SJulian Elischer 			kg->kg_last_assigned = td2;
400e602ba25SJulian Elischer 		} else if (tda->td_priority > td->td_priority) {
401e602ba25SJulian Elischer 			/*
402e602ba25SJulian Elischer 			 * It's ours, grab it, but last_assigned is past us
403e602ba25SJulian Elischer 			 * so don't change it.
404e602ba25SJulian Elischer 			 */
405e602ba25SJulian Elischer 			td->td_kse = ke;
406e602ba25SJulian Elischer 			ke->ke_thread = td;
407e602ba25SJulian Elischer 		} else {
408e602ba25SJulian Elischer 			/*
409e602ba25SJulian Elischer 			 * We are past last_assigned, so
410e602ba25SJulian Elischer 			 * put the new kse on whatever is next,
411e602ba25SJulian Elischer 			 * which may or may not be us.
412e602ba25SJulian Elischer 			 */
413e602ba25SJulian Elischer 			td2 = TAILQ_NEXT(tda, td_runq);
414e602ba25SJulian Elischer 			kg->kg_last_assigned = td2;
415e602ba25SJulian Elischer 			td2->td_kse = ke;
416e602ba25SJulian Elischer 			ke->ke_thread = td2;
417e602ba25SJulian Elischer 		}
418e602ba25SJulian Elischer 		runq_add(&runq, ke);
419e602ba25SJulian Elischer 	}
420e602ba25SJulian Elischer 	thread_sanity_check(td);
421e602ba25SJulian Elischer }
422e602ba25SJulian Elischer 
423e602ba25SJulian Elischer #else
424e602ba25SJulian Elischer 
425e602ba25SJulian Elischer void
426e602ba25SJulian Elischer setrunqueue(struct thread *td)
427e602ba25SJulian Elischer {
428e602ba25SJulian Elischer 	struct kse *ke;
429e602ba25SJulian Elischer 	struct ksegrp *kg;
430e602ba25SJulian Elischer 	struct thread *td2;
431e602ba25SJulian Elischer 
432e602ba25SJulian Elischer 	CTR1(KTR_RUNQ, "setrunqueue: td%p", td);
433e602ba25SJulian Elischer 	KASSERT((td->td_state != TDS_RUNQ), ("setrunqueue: bad thread state"));
434e602ba25SJulian Elischer 	td->td_state = TDS_RUNQ;
435e602ba25SJulian Elischer 	kg = td->td_ksegrp;
436e602ba25SJulian Elischer 	kg->kg_runnable++;
437e602ba25SJulian Elischer 	if ((td->td_flags & TDF_UNBOUND) == 0) {
438e602ba25SJulian Elischer 		/*
439e602ba25SJulian Elischer 		 * Common path optimisation: Only one of everything
440e602ba25SJulian Elischer 		 * and the KSE is always already attached.
441e602ba25SJulian Elischer 		 * Totally ignore the ksegrp run queue.
442e602ba25SJulian Elischer 		 */
443e602ba25SJulian Elischer 		runq_add(&runq, td->td_kse);
444e602ba25SJulian Elischer 		return;
445e602ba25SJulian Elischer 	}
446e602ba25SJulian Elischer 	/*
447e602ba25SJulian Elischer 	 * First add the thread to the ksegrp's run queue at
448e602ba25SJulian Elischer 	 * the appropriate place.
449e602ba25SJulian Elischer 	 */
450e602ba25SJulian Elischer 	TAILQ_FOREACH(td2, &kg->kg_runq, td_runq) {
451e602ba25SJulian Elischer 		if (td2->td_priority > td->td_priority) {
452e602ba25SJulian Elischer 			TAILQ_INSERT_BEFORE(td2, td, td_runq);
453e602ba25SJulian Elischer 			break;
454e602ba25SJulian Elischer 		}
455e602ba25SJulian Elischer 	}
456e602ba25SJulian Elischer 	if (td2 == NULL) {
457e602ba25SJulian Elischer 		/* We ran off the end of the TAILQ or it was empty. */
458e602ba25SJulian Elischer 		TAILQ_INSERT_TAIL(&kg->kg_runq, td, td_runq);
459e602ba25SJulian Elischer 	}
460e602ba25SJulian Elischer 
461e602ba25SJulian Elischer 	/*
462e602ba25SJulian Elischer 	 * The following could be achieved by simply doing:
463e602ba25SJulian Elischer 	 * td->td_kse = NULL; kse_reassign(ke);
464e602ba25SJulian Elischer 	 * but I felt that I'd try do it inline here.
465e602ba25SJulian Elischer 	 * All this work may not be worth it.
466e602ba25SJulian Elischer 	 */
467e602ba25SJulian Elischer 	if ((ke = td->td_kse)) { /* XXXKSE */
468e602ba25SJulian Elischer 		/*
469e602ba25SJulian Elischer 		 * We have a KSE already. See whether we can keep it
470e602ba25SJulian Elischer 		 * or if we need to give it to someone else.
471e602ba25SJulian Elischer 		 * Either way it will need to be inserted into
472e602ba25SJulian Elischer 		 * the runq. kse_reassign() will do this as will runq_add().
473e602ba25SJulian Elischer 		 */
474e602ba25SJulian Elischer 		if ((kg->kg_last_assigned) &&
475e602ba25SJulian Elischer 		   (kg->kg_last_assigned->td_priority > td->td_priority)) {
476e602ba25SJulian Elischer 			/*
477e602ba25SJulian Elischer 			 * We can definitly keep the KSE
478e602ba25SJulian Elischer 			 * as the "last assignead thread" has
479e602ba25SJulian Elischer 			 * less priority than we do.
480e602ba25SJulian Elischer 			 * The "last assigned" pointer stays the same.
481e602ba25SJulian Elischer 			 */
482e602ba25SJulian Elischer 			runq_add(&runq, ke);
483e602ba25SJulian Elischer 			return;
484e602ba25SJulian Elischer 
485e602ba25SJulian Elischer 		}
486e602ba25SJulian Elischer 		/*
487e602ba25SJulian Elischer 		 * Give it to the correct thread,
488e602ba25SJulian Elischer 		 * which may be (often is) us, but may not be.
489e602ba25SJulian Elischer 		 */
490e602ba25SJulian Elischer 		td->td_kse = NULL;
491e602ba25SJulian Elischer 		kse_reassign(ke);
492e602ba25SJulian Elischer 		return;
493e602ba25SJulian Elischer 	}
494e602ba25SJulian Elischer 	/*
495e602ba25SJulian Elischer 	 * There are two cases where KSE adjustment is needed.
496e602ba25SJulian Elischer 	 * Usurpation of an already assigned KSE, and assignment
497e602ba25SJulian Elischer 	 * of a previously IDLE KSE.
498e602ba25SJulian Elischer 	 */
499e602ba25SJulian Elischer 	if (kg->kg_idle_kses) {
500e602ba25SJulian Elischer 		/*
501e602ba25SJulian Elischer 		 * If there are unassigned KSEs then we definitly
502e602ba25SJulian Elischer 		 * will be assigned one from the idle KSE list.
503e602ba25SJulian Elischer 		 * If we are the last, we should get the "last
504e602ba25SJulian Elischer 		 * assigned" pointer set to us as well.
505e602ba25SJulian Elischer 		 */
506e602ba25SJulian Elischer 		ke = TAILQ_FIRST(&kg->kg_iq);
507e602ba25SJulian Elischer KASSERT((ke->ke_kgrlist.tqe_next != ke), ("linked to self!"));
508e602ba25SJulian Elischer 		TAILQ_REMOVE(&kg->kg_iq, ke, ke_kgrlist);
509e602ba25SJulian Elischer 		ke->ke_state = KES_UNQUEUED;
510e602ba25SJulian Elischer 		kg->kg_idle_kses--;
511e602ba25SJulian Elischer KASSERT((ke->ke_kgrlist.tqe_next != ke), ("linked to self!"));
512e602ba25SJulian Elischer 		ke->ke_thread = td;
513e602ba25SJulian Elischer 		td->td_kse = ke;
514e602ba25SJulian Elischer 		runq_add(&runq, ke);
515e602ba25SJulian Elischer KASSERT((ke->ke_kgrlist.tqe_next != ke), ("linked to self!"));
516e602ba25SJulian Elischer 		if (TAILQ_NEXT(td, td_runq) == NULL) {
517e602ba25SJulian Elischer 			kg->kg_last_assigned = td;
518e602ba25SJulian Elischer 		}
519e602ba25SJulian Elischer 	} else if (kg->kg_last_assigned &&
520e602ba25SJulian Elischer 		(kg->kg_last_assigned->td_priority > td->td_priority)) {
521e602ba25SJulian Elischer 		/*
522e602ba25SJulian Elischer 		 * If there were none last-assigned, all KSEs
523e602ba25SJulian Elischer 		 * are actually out running as we speak.
524e602ba25SJulian Elischer 		 * If there was a last assigned, but we didn't see it,
525e602ba25SJulian Elischer 		 * we must be inserting before it, so take the KSE from
526e602ba25SJulian Elischer 		 * the last assigned, and back it up one entry. Then,
527e602ba25SJulian Elischer 		 * assign the KSE to the new thread and adjust its priority.
528e602ba25SJulian Elischer 		 */
529e602ba25SJulian Elischer 		td2 = kg->kg_last_assigned;
530e602ba25SJulian Elischer 		ke = td2->td_kse;
531e602ba25SJulian Elischer KASSERT((ke->ke_kgrlist.tqe_next != ke), ("linked to self!"));
532e602ba25SJulian Elischer 		kg->kg_last_assigned =
533e602ba25SJulian Elischer 		    TAILQ_PREV(td2, threadqueue, td_runq);
534e602ba25SJulian Elischer 		td2->td_kse = NULL;
535e602ba25SJulian Elischer 		td->td_kse = ke;
536e602ba25SJulian Elischer 		ke->ke_thread = td;
537e602ba25SJulian Elischer 		runq_readjust(&runq, ke);
538e602ba25SJulian Elischer KASSERT((ke->ke_kgrlist.tqe_next != ke), ("linked to self!"));
539e602ba25SJulian Elischer 	}
540e602ba25SJulian Elischer }
541e602ba25SJulian Elischer #endif
542e602ba25SJulian Elischer 
543e602ba25SJulian Elischer /************************************************************************
544e602ba25SJulian Elischer  * Critical section marker functions					*
545e602ba25SJulian Elischer  ************************************************************************/
5467e1f6dfeSJohn Baldwin /* Critical sections that prevent preemption. */
5477e1f6dfeSJohn Baldwin void
5487e1f6dfeSJohn Baldwin critical_enter(void)
5497e1f6dfeSJohn Baldwin {
5507e1f6dfeSJohn Baldwin 	struct thread *td;
5517e1f6dfeSJohn Baldwin 
5527e1f6dfeSJohn Baldwin 	td = curthread;
5537e1f6dfeSJohn Baldwin 	if (td->td_critnest == 0)
554d74ac681SMatthew Dillon 		cpu_critical_enter();
5557e1f6dfeSJohn Baldwin 	td->td_critnest++;
5567e1f6dfeSJohn Baldwin }
5577e1f6dfeSJohn Baldwin 
5587e1f6dfeSJohn Baldwin void
5597e1f6dfeSJohn Baldwin critical_exit(void)
5607e1f6dfeSJohn Baldwin {
5617e1f6dfeSJohn Baldwin 	struct thread *td;
5627e1f6dfeSJohn Baldwin 
5637e1f6dfeSJohn Baldwin 	td = curthread;
5647e1f6dfeSJohn Baldwin 	if (td->td_critnest == 1) {
5657e1f6dfeSJohn Baldwin 		td->td_critnest = 0;
566d74ac681SMatthew Dillon 		cpu_critical_exit();
567d74ac681SMatthew Dillon 	} else {
5687e1f6dfeSJohn Baldwin 		td->td_critnest--;
5697e1f6dfeSJohn Baldwin 	}
570d74ac681SMatthew Dillon }
5717e1f6dfeSJohn Baldwin 
572e602ba25SJulian Elischer 
573e602ba25SJulian Elischer /************************************************************************
574e602ba25SJulian Elischer  * SYSTEM RUN QUEUE manipulations and tests				*
575e602ba25SJulian Elischer  ************************************************************************/
576e602ba25SJulian Elischer /*
577e602ba25SJulian Elischer  * Initialize a run structure.
578e602ba25SJulian Elischer  */
579e602ba25SJulian Elischer void
580e602ba25SJulian Elischer runq_init(struct runq *rq)
581e602ba25SJulian Elischer {
582e602ba25SJulian Elischer 	int i;
583e602ba25SJulian Elischer 
584e602ba25SJulian Elischer 	bzero(rq, sizeof *rq);
585e602ba25SJulian Elischer 	for (i = 0; i < RQ_NQS; i++)
586e602ba25SJulian Elischer 		TAILQ_INIT(&rq->rq_queues[i]);
587e602ba25SJulian Elischer }
588e602ba25SJulian Elischer 
589d5a08a60SJake Burkholder /*
590d5a08a60SJake Burkholder  * Clear the status bit of the queue corresponding to priority level pri,
591d5a08a60SJake Burkholder  * indicating that it is empty.
592d5a08a60SJake Burkholder  */
593d5a08a60SJake Burkholder static __inline void
594d5a08a60SJake Burkholder runq_clrbit(struct runq *rq, int pri)
595d5a08a60SJake Burkholder {
596d5a08a60SJake Burkholder 	struct rqbits *rqb;
597d5a08a60SJake Burkholder 
598d5a08a60SJake Burkholder 	rqb = &rq->rq_status;
599d5a08a60SJake Burkholder 	CTR4(KTR_RUNQ, "runq_clrbit: bits=%#x %#x bit=%#x word=%d",
600d5a08a60SJake Burkholder 	    rqb->rqb_bits[RQB_WORD(pri)],
601d5a08a60SJake Burkholder 	    rqb->rqb_bits[RQB_WORD(pri)] & ~RQB_BIT(pri),
602d5a08a60SJake Burkholder 	    RQB_BIT(pri), RQB_WORD(pri));
603d5a08a60SJake Burkholder 	rqb->rqb_bits[RQB_WORD(pri)] &= ~RQB_BIT(pri);
604d5a08a60SJake Burkholder }
605d5a08a60SJake Burkholder 
606d5a08a60SJake Burkholder /*
607d5a08a60SJake Burkholder  * Find the index of the first non-empty run queue.  This is done by
608d5a08a60SJake Burkholder  * scanning the status bits, a set bit indicates a non-empty queue.
609d5a08a60SJake Burkholder  */
610d5a08a60SJake Burkholder static __inline int
611d5a08a60SJake Burkholder runq_findbit(struct runq *rq)
612d5a08a60SJake Burkholder {
613d5a08a60SJake Burkholder 	struct rqbits *rqb;
614d5a08a60SJake Burkholder 	int pri;
615d5a08a60SJake Burkholder 	int i;
616d5a08a60SJake Burkholder 
617d5a08a60SJake Burkholder 	rqb = &rq->rq_status;
618d5a08a60SJake Burkholder 	for (i = 0; i < RQB_LEN; i++)
619d5a08a60SJake Burkholder 		if (rqb->rqb_bits[i]) {
6202f9267ecSPeter Wemm 			pri = RQB_FFS(rqb->rqb_bits[i]) + (i << RQB_L2BPW);
621d5a08a60SJake Burkholder 			CTR3(KTR_RUNQ, "runq_findbit: bits=%#x i=%d pri=%d",
622d5a08a60SJake Burkholder 			    rqb->rqb_bits[i], i, pri);
623d5a08a60SJake Burkholder 			return (pri);
624d5a08a60SJake Burkholder 		}
625d5a08a60SJake Burkholder 
626d5a08a60SJake Burkholder 	return (-1);
627d5a08a60SJake Burkholder }
628d5a08a60SJake Burkholder 
629d5a08a60SJake Burkholder /*
630d5a08a60SJake Burkholder  * Set the status bit of the queue corresponding to priority level pri,
631d5a08a60SJake Burkholder  * indicating that it is non-empty.
632d5a08a60SJake Burkholder  */
633d5a08a60SJake Burkholder static __inline void
634d5a08a60SJake Burkholder runq_setbit(struct runq *rq, int pri)
635d5a08a60SJake Burkholder {
636d5a08a60SJake Burkholder 	struct rqbits *rqb;
637d5a08a60SJake Burkholder 
638d5a08a60SJake Burkholder 	rqb = &rq->rq_status;
639d5a08a60SJake Burkholder 	CTR4(KTR_RUNQ, "runq_setbit: bits=%#x %#x bit=%#x word=%d",
640d5a08a60SJake Burkholder 	    rqb->rqb_bits[RQB_WORD(pri)],
641d5a08a60SJake Burkholder 	    rqb->rqb_bits[RQB_WORD(pri)] | RQB_BIT(pri),
642d5a08a60SJake Burkholder 	    RQB_BIT(pri), RQB_WORD(pri));
643d5a08a60SJake Burkholder 	rqb->rqb_bits[RQB_WORD(pri)] |= RQB_BIT(pri);
644d5a08a60SJake Burkholder }
645d5a08a60SJake Burkholder 
646d5a08a60SJake Burkholder /*
647e602ba25SJulian Elischer  * Add the KSE to the queue specified by its priority, and set the
648d5a08a60SJake Burkholder  * corresponding status bit.
649d5a08a60SJake Burkholder  */
650d5a08a60SJake Burkholder void
651b40ce416SJulian Elischer runq_add(struct runq *rq, struct kse *ke)
652d5a08a60SJake Burkholder {
653d5a08a60SJake Burkholder 	struct rqhead *rqh;
654d5a08a60SJake Burkholder 	int pri;
655dba6c5a6SPeter Wemm 
6560384fff8SJason Evans 	mtx_assert(&sched_lock, MA_OWNED);
657e602ba25SJulian Elischer 	KASSERT((ke->ke_thread != NULL), ("runq_add: No thread on KSE"));
658e602ba25SJulian Elischer 	KASSERT((ke->ke_thread->td_kse != NULL), ("runq_add: No KSE on thread"));
659e602ba25SJulian Elischer 	if (ke->ke_state == KES_ONRUNQ)
660e602ba25SJulian Elischer 		return;
661e602ba25SJulian Elischer #if defined(INVARIANTS) && defined(DIAGNOSTIC)
662e602ba25SJulian Elischer 	KASSERT(ke->ke_state != KES_ONRUNQ,
663e602ba25SJulian Elischer 	    ("runq_add: kse %p (%s) already in run queue", ke,
664e602ba25SJulian Elischer 	    ke->ke_proc->p_comm));
665e602ba25SJulian Elischer #endif
6662c100766SJulian Elischer 	pri = ke->ke_thread->td_priority / RQ_PPQ;
667b40ce416SJulian Elischer 	ke->ke_rqindex = pri;
668d5a08a60SJake Burkholder 	runq_setbit(rq, pri);
669d5a08a60SJake Burkholder 	rqh = &rq->rq_queues[pri];
670d5a08a60SJake Burkholder 	CTR4(KTR_RUNQ, "runq_add: p=%p pri=%d %d rqh=%p",
6712c100766SJulian Elischer 	    ke->ke_proc, ke->ke_thread->td_priority, pri, rqh);
672b40ce416SJulian Elischer 	TAILQ_INSERT_TAIL(rqh, ke, ke_procq);
673e602ba25SJulian Elischer 	ke->ke_ksegrp->kg_runq_kses++;
674e602ba25SJulian Elischer 	ke->ke_state = KES_ONRUNQ;
675dba6c5a6SPeter Wemm }
676d5a08a60SJake Burkholder 
677d5a08a60SJake Burkholder /*
678d5a08a60SJake Burkholder  * Return true if there are runnable processes of any priority on the run
679d5a08a60SJake Burkholder  * queue, false otherwise.  Has no side effects, does not modify the run
680d5a08a60SJake Burkholder  * queue structure.
681d5a08a60SJake Burkholder  */
682d5a08a60SJake Burkholder int
683d5a08a60SJake Burkholder runq_check(struct runq *rq)
684d5a08a60SJake Burkholder {
685d5a08a60SJake Burkholder 	struct rqbits *rqb;
686d5a08a60SJake Burkholder 	int i;
687d5a08a60SJake Burkholder 
688d5a08a60SJake Burkholder 	rqb = &rq->rq_status;
689d5a08a60SJake Burkholder 	for (i = 0; i < RQB_LEN; i++)
690d5a08a60SJake Burkholder 		if (rqb->rqb_bits[i]) {
691d5a08a60SJake Burkholder 			CTR2(KTR_RUNQ, "runq_check: bits=%#x i=%d",
692d5a08a60SJake Burkholder 			    rqb->rqb_bits[i], i);
693d5a08a60SJake Burkholder 			return (1);
694dba6c5a6SPeter Wemm 		}
695d5a08a60SJake Burkholder 	CTR0(KTR_RUNQ, "runq_check: empty");
696d5a08a60SJake Burkholder 
697d5a08a60SJake Burkholder 	return (0);
698dba6c5a6SPeter Wemm }
699d5a08a60SJake Burkholder 
700d5a08a60SJake Burkholder /*
701d5a08a60SJake Burkholder  * Find and remove the highest priority process from the run queue.
702d5a08a60SJake Burkholder  * If there are no runnable processes, the per-cpu idle process is
703d5a08a60SJake Burkholder  * returned.  Will not return NULL under any circumstances.
704d5a08a60SJake Burkholder  */
705b40ce416SJulian Elischer struct kse *
706d5a08a60SJake Burkholder runq_choose(struct runq *rq)
707d5a08a60SJake Burkholder {
708d5a08a60SJake Burkholder 	struct rqhead *rqh;
709b40ce416SJulian Elischer 	struct kse *ke;
710d5a08a60SJake Burkholder 	int pri;
711d5a08a60SJake Burkholder 
712d5a08a60SJake Burkholder 	mtx_assert(&sched_lock, MA_OWNED);
713e602ba25SJulian Elischer 	while ((pri = runq_findbit(rq)) != -1) {
714d5a08a60SJake Burkholder 		rqh = &rq->rq_queues[pri];
715b40ce416SJulian Elischer 		ke = TAILQ_FIRST(rqh);
716b40ce416SJulian Elischer 		KASSERT(ke != NULL, ("runq_choose: no proc on busy queue"));
717e602ba25SJulian Elischer 		CTR3(KTR_RUNQ,
718e602ba25SJulian Elischer 		    "runq_choose: pri=%d kse=%p rqh=%p", pri, ke, rqh);
719e602ba25SJulian Elischer KASSERT(ke->ke_procq.tqe_prev != NULL, ("no prev"));
720e602ba25SJulian Elischer if (ke->ke_procq.tqe_next)
721e602ba25SJulian Elischer 	KASSERT(ke->ke_procq.tqe_next->ke_procq.tqe_prev != NULL, ("no next"));
722b40ce416SJulian Elischer 		TAILQ_REMOVE(rqh, ke, ke_procq);
723e602ba25SJulian Elischer 		ke->ke_ksegrp->kg_runq_kses--;
724d5a08a60SJake Burkholder 		if (TAILQ_EMPTY(rqh)) {
725d5a08a60SJake Burkholder 			CTR0(KTR_RUNQ, "runq_choose: empty");
726d5a08a60SJake Burkholder 			runq_clrbit(rq, pri);
727d5a08a60SJake Burkholder 		}
728e602ba25SJulian Elischer 
729e602ba25SJulian Elischer 		ke->ke_state = KES_RUNNING;
730e602ba25SJulian Elischer 		KASSERT((ke->ke_thread != NULL),
731e602ba25SJulian Elischer 		    ("runq_choose: No thread on KSE"));
732e602ba25SJulian Elischer 		KASSERT((ke->ke_thread->td_kse != NULL),
733e602ba25SJulian Elischer 		    ("runq_choose: No KSE on thread"));
734b40ce416SJulian Elischer 		return (ke);
735d5a08a60SJake Burkholder 	}
736d5a08a60SJake Burkholder 	CTR1(KTR_RUNQ, "runq_choose: idleproc pri=%d", pri);
737d5a08a60SJake Burkholder 
738e602ba25SJulian Elischer 	return (NULL);
739d5a08a60SJake Burkholder }
740d5a08a60SJake Burkholder 
741d5a08a60SJake Burkholder /*
742e602ba25SJulian Elischer  * Remove the KSE from the queue specified by its priority, and clear the
743d5a08a60SJake Burkholder  * corresponding status bit if the queue becomes empty.
744e602ba25SJulian Elischer  * Caller must set ke->ke_state afterwards.
745d5a08a60SJake Burkholder  */
746d5a08a60SJake Burkholder void
747b40ce416SJulian Elischer runq_remove(struct runq *rq, struct kse *ke)
748d5a08a60SJake Burkholder {
749d5a08a60SJake Burkholder 	struct rqhead *rqh;
750d5a08a60SJake Burkholder 	int pri;
751d5a08a60SJake Burkholder 
752e602ba25SJulian Elischer 	KASSERT((ke->ke_state == KES_ONRUNQ), ("KSE not on run queue"));
753d5a08a60SJake Burkholder 	mtx_assert(&sched_lock, MA_OWNED);
754b40ce416SJulian Elischer 	pri = ke->ke_rqindex;
755d5a08a60SJake Burkholder 	rqh = &rq->rq_queues[pri];
756d5a08a60SJake Burkholder 	CTR4(KTR_RUNQ, "runq_remove: p=%p pri=%d %d rqh=%p",
7572c100766SJulian Elischer 	    ke, ke->ke_thread->td_priority, pri, rqh);
758b40ce416SJulian Elischer 	KASSERT(ke != NULL, ("runq_remove: no proc on busy queue"));
759b40ce416SJulian Elischer 	TAILQ_REMOVE(rqh, ke, ke_procq);
760d5a08a60SJake Burkholder 	if (TAILQ_EMPTY(rqh)) {
761d5a08a60SJake Burkholder 		CTR0(KTR_RUNQ, "runq_remove: empty");
762d5a08a60SJake Burkholder 		runq_clrbit(rq, pri);
763d5a08a60SJake Burkholder 	}
764e602ba25SJulian Elischer 	ke->ke_state = KES_UNQUEUED;
765e602ba25SJulian Elischer 	ke->ke_ksegrp->kg_runq_kses--;
766dba6c5a6SPeter Wemm }
767e602ba25SJulian Elischer 
768e602ba25SJulian Elischer static void
769e602ba25SJulian Elischer runq_readjust(struct runq *rq, struct kse *ke)
770e602ba25SJulian Elischer {
771e602ba25SJulian Elischer 
772e602ba25SJulian Elischer 	if (ke->ke_rqindex != (ke->ke_thread->td_priority / RQ_PPQ)) {
773e602ba25SJulian Elischer 		runq_remove(rq, ke);
774e602ba25SJulian Elischer 		runq_add(rq, ke);
775e602ba25SJulian Elischer 	}
776e602ba25SJulian Elischer }
777e602ba25SJulian Elischer 
778e602ba25SJulian Elischer void
779e602ba25SJulian Elischer thread_sanity_check(struct thread *td)
780e602ba25SJulian Elischer {
781e602ba25SJulian Elischer 	struct proc *p;
782e602ba25SJulian Elischer 	struct ksegrp *kg;
783e602ba25SJulian Elischer 	struct kse *ke;
784e602ba25SJulian Elischer 	struct thread *td2;
785e602ba25SJulian Elischer 	unsigned int prevpri;
786e602ba25SJulian Elischer 	int	saw_lastassigned;
787e602ba25SJulian Elischer 	int unassigned;
788e602ba25SJulian Elischer 	int assigned;
789e602ba25SJulian Elischer 
790e602ba25SJulian Elischer 	p = td->td_proc;
791e602ba25SJulian Elischer 	kg = td->td_ksegrp;
792e602ba25SJulian Elischer 	ke = td->td_kse;
793e602ba25SJulian Elischer 
794e602ba25SJulian Elischer 	if (kg != &p->p_ksegrp) {
795e602ba25SJulian Elischer 		panic ("wrong ksegrp");
796e602ba25SJulian Elischer 	}
797e602ba25SJulian Elischer 
798e602ba25SJulian Elischer 	if (ke) {
799e602ba25SJulian Elischer 		if (ke != &p->p_kse) {
800e602ba25SJulian Elischer 			panic("wrong kse");
801e602ba25SJulian Elischer 		}
802e602ba25SJulian Elischer 		if (ke->ke_thread != td) {
803e602ba25SJulian Elischer 			panic("wrong thread");
804e602ba25SJulian Elischer 		}
805e602ba25SJulian Elischer 	}
806e602ba25SJulian Elischer 
807e602ba25SJulian Elischer 	if ((p->p_flag & P_KSES) == 0) {
808e602ba25SJulian Elischer 		if (ke == NULL) {
809e602ba25SJulian Elischer 			panic("non KSE thread lost kse");
810e602ba25SJulian Elischer 		}
811e602ba25SJulian Elischer 	} else {
812e602ba25SJulian Elischer 		prevpri = 0;
813e602ba25SJulian Elischer 		saw_lastassigned = 0;
814e602ba25SJulian Elischer 		unassigned = 0;
815e602ba25SJulian Elischer 		assigned = 0;
816e602ba25SJulian Elischer 		TAILQ_FOREACH(td2, &kg->kg_runq, td_runq) {
817e602ba25SJulian Elischer 			if (td2->td_priority < prevpri) {
818e602ba25SJulian Elischer 				panic("thread runqueue unosorted");
819e602ba25SJulian Elischer 			}
820e602ba25SJulian Elischer 			prevpri = td2->td_priority;
821e602ba25SJulian Elischer 			if (td2->td_kse) {
822e602ba25SJulian Elischer 				assigned++;
823e602ba25SJulian Elischer 				if (unassigned) {
824e602ba25SJulian Elischer 					panic("unassigned before assigned");
825e602ba25SJulian Elischer 				}
826e602ba25SJulian Elischer  				if  (kg->kg_last_assigned == NULL) {
827e602ba25SJulian Elischer 					panic("lastassigned corrupt");
828e602ba25SJulian Elischer 				}
829e602ba25SJulian Elischer 				if (saw_lastassigned) {
830e602ba25SJulian Elischer 					panic("last assigned not last");
831e602ba25SJulian Elischer 				}
832e602ba25SJulian Elischer 				if (td2->td_kse->ke_thread != td2) {
833e602ba25SJulian Elischer 					panic("mismatched kse/thread");
834e602ba25SJulian Elischer 				}
835e602ba25SJulian Elischer 			} else {
836e602ba25SJulian Elischer 				unassigned++;
837e602ba25SJulian Elischer 			}
838e602ba25SJulian Elischer 			if (td2 == kg->kg_last_assigned) {
839e602ba25SJulian Elischer 				saw_lastassigned = 1;
840e602ba25SJulian Elischer 				if (td2->td_kse == NULL) {
841e602ba25SJulian Elischer 					panic("last assigned not assigned");
842e602ba25SJulian Elischer 				}
843e602ba25SJulian Elischer 			}
844e602ba25SJulian Elischer 		}
845e602ba25SJulian Elischer 		if (kg->kg_last_assigned && (saw_lastassigned == 0)) {
846e602ba25SJulian Elischer 			panic("where on earth does lastassigned point?");
847e602ba25SJulian Elischer 		}
848e602ba25SJulian Elischer 		FOREACH_THREAD_IN_GROUP(kg, td2) {
849e602ba25SJulian Elischer 			if (((td2->td_flags & TDF_UNBOUND) == 0) &&
850e602ba25SJulian Elischer 			    (td2->td_state == TDS_RUNQ)) {
851e602ba25SJulian Elischer 				assigned++;
852e602ba25SJulian Elischer 				if (td2->td_kse == NULL) {
853e602ba25SJulian Elischer 					panic ("BOUND thread with no KSE");
854e602ba25SJulian Elischer 				}
855e602ba25SJulian Elischer 			}
856e602ba25SJulian Elischer 		}
857e602ba25SJulian Elischer #if 0
858e602ba25SJulian Elischer 		if ((unassigned + assigned) != kg->kg_runnable) {
859e602ba25SJulian Elischer 			panic("wrong number in runnable");
860e602ba25SJulian Elischer 		}
861e602ba25SJulian Elischer #endif
862e602ba25SJulian Elischer 	}
863e602ba25SJulian Elischer }
864e602ba25SJulian Elischer 
865