10384fff8SJason Evans /*- 244116885SWarner Losh * Copyright (C) 2000-2004 The FreeBSD Project. All rights reserved. 30384fff8SJason Evans * 444116885SWarner Losh * Redistribution and use in source and binary forms, with or without 544116885SWarner Losh * modification, are permitted provided that the following conditions 644116885SWarner Losh * are met: 744116885SWarner Losh * 1. Redistributions of source code must retain the above copyright 844116885SWarner Losh * notice, this list of conditions and the following disclaimer. 944116885SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 1044116885SWarner Losh * notice, this list of conditions and the following disclaimer in the 1144116885SWarner Losh * documentation and/or other materials provided with the distribution. 1244116885SWarner Losh * 1344116885SWarner Losh * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1444116885SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1544116885SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1644116885SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 1744116885SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1844116885SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1944116885SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2044116885SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2144116885SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2244116885SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2344116885SWarner Losh * SUCH DAMAGE. 240384fff8SJason Evans */ 250384fff8SJason Evans 26677b542eSDavid E. O'Brien #include <sys/cdefs.h> 27677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 28677b542eSDavid E. O'Brien 290384fff8SJason Evans #include <sys/param.h> 300384fff8SJason Evans #include <sys/systm.h> 310384fff8SJason Evans #include <sys/kernel.h> 32ba228f6dSJohn Baldwin #include <sys/kthread.h> 33fb919e4dSMark Murray #include <sys/lock.h> 34fb919e4dSMark Murray #include <sys/mutex.h> 35fb919e4dSMark Murray #include <sys/proc.h> 360384fff8SJason Evans #include <sys/resourcevar.h> 37b43179fbSJeff Roberson #include <sys/sched.h> 380384fff8SJason Evans #include <sys/unistd.h> 390384fff8SJason Evans 400384fff8SJason Evans static void idle_setup(void *dummy); 410384fff8SJason Evans SYSINIT(idle_setup, SI_SUB_SCHED_IDLE, SI_ORDER_FIRST, idle_setup, NULL) 420384fff8SJason Evans 430384fff8SJason Evans static void idle_proc(void *dummy); 440384fff8SJason Evans 450384fff8SJason Evans /* 467ecfc090SJohn Baldwin * Set up per-cpu idle process contexts. The AP's shouldn't be running or 477ecfc090SJohn Baldwin * accessing their idle processes at this point, so don't bother with 487ecfc090SJohn Baldwin * locking. 490384fff8SJason Evans */ 500384fff8SJason Evans static void 510384fff8SJason Evans idle_setup(void *dummy) 520384fff8SJason Evans { 536caa8a15SJohn Baldwin #ifdef SMP 540bbc8826SJohn Baldwin struct pcpu *pc; 556caa8a15SJohn Baldwin #endif 566caa8a15SJohn Baldwin struct proc *p; 57e602ba25SJulian Elischer struct thread *td; 580384fff8SJason Evans int error; 590384fff8SJason Evans 600384fff8SJason Evans #ifdef SMP 610bbc8826SJohn Baldwin SLIST_FOREACH(pc, &cpuhead, pc_allcpu) { 626caa8a15SJohn Baldwin error = kthread_create(idle_proc, NULL, &p, 63316ec49aSScott Long RFSTOPPED | RFHIGHPID, 0, "idle: cpu%d", pc->pc_cpuid); 64079b7badSJulian Elischer pc->pc_idlethread = FIRST_THREAD_IN_PROC(p); 657e1f6dfeSJohn Baldwin if (pc->pc_curthread == NULL) { 660bbc8826SJohn Baldwin pc->pc_curthread = pc->pc_idlethread; 677e1f6dfeSJohn Baldwin pc->pc_idlethread->td_critnest = 0; 687e1f6dfeSJohn Baldwin } 690384fff8SJason Evans #else 706caa8a15SJohn Baldwin error = kthread_create(idle_proc, NULL, &p, 71316ec49aSScott Long RFSTOPPED | RFHIGHPID, 0, "idle"); 72079b7badSJulian Elischer PCPU_SET(idlethread, FIRST_THREAD_IN_PROC(p)); 730384fff8SJason Evans #endif 740384fff8SJason Evans if (error) 750384fff8SJason Evans panic("idle_setup: kthread_create error %d\n", error); 760384fff8SJason Evans 77e674d807SJohn Baldwin PROC_LOCK(p); 786caa8a15SJohn Baldwin p->p_flag |= P_NOLOAD; 79e674d807SJohn Baldwin mtx_lock_spin(&sched_lock); 80e602ba25SJulian Elischer td = FIRST_THREAD_IN_PROC(p); 81bf0acc27SJohn Baldwin TD_SET_CAN_RUN(td); 82b1ac98d8SJulian Elischer td->td_flags |= TDF_IDLETD; 83c086588fSJohn Baldwin td->td_priority = PRI_MAX_IDLE; 84e674d807SJohn Baldwin mtx_unlock_spin(&sched_lock); 85e674d807SJohn Baldwin PROC_UNLOCK(p); 866caa8a15SJohn Baldwin #ifdef SMP 870384fff8SJason Evans } 886caa8a15SJohn Baldwin #endif 890384fff8SJason Evans } 900384fff8SJason Evans 910384fff8SJason Evans /* 9268d86cf1SPeter Wemm * The actual idle process. 930384fff8SJason Evans */ 940384fff8SJason Evans static void 950384fff8SJason Evans idle_proc(void *dummy) 960384fff8SJason Evans { 97e602ba25SJulian Elischer struct proc *p; 9868d86cf1SPeter Wemm struct thread *td; 990384fff8SJason Evans 100e602ba25SJulian Elischer td = curthread; 101e602ba25SJulian Elischer p = td->td_proc; 1020384fff8SJason Evans for (;;) { 1030384fff8SJason Evans mtx_assert(&Giant, MA_NOTOWNED); 1040384fff8SJason Evans 10568d86cf1SPeter Wemm while (sched_runnable() == 0) 106dc13e6dfSJohn Baldwin cpu_idle(); 1070384fff8SJason Evans 1089ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 109bf0acc27SJohn Baldwin mi_switch(SW_VOL, NULL); 1109ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 1110384fff8SJason Evans } 1120384fff8SJason Evans } 113