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