xref: /freebsd/sys/kern/kern_idle.c (revision 4411688509c43a24ab7aa7561072e54b999b9b21)
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