xref: /freebsd/sys/kern/kern_idle.c (revision 339a7e7fbbcd821d329835ea06286cb1249b1d9d)
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>
396804a3abSJulian Elischer #ifdef SMP
406804a3abSJulian Elischer #include <sys/smp.h>
416804a3abSJulian Elischer #endif
420384fff8SJason Evans 
430384fff8SJason Evans static void idle_setup(void *dummy);
440384fff8SJason Evans SYSINIT(idle_setup, SI_SUB_SCHED_IDLE, SI_ORDER_FIRST, idle_setup, NULL)
450384fff8SJason Evans 
460384fff8SJason Evans static void idle_proc(void *dummy);
470384fff8SJason Evans 
480384fff8SJason Evans /*
497ecfc090SJohn Baldwin  * Set up per-cpu idle process contexts.  The AP's shouldn't be running or
507ecfc090SJohn Baldwin  * accessing their idle processes at this point, so don't bother with
517ecfc090SJohn Baldwin  * locking.
520384fff8SJason Evans  */
530384fff8SJason Evans static void
540384fff8SJason Evans idle_setup(void *dummy)
550384fff8SJason Evans {
566caa8a15SJohn Baldwin #ifdef SMP
570bbc8826SJohn Baldwin 	struct pcpu *pc;
586caa8a15SJohn Baldwin #endif
596caa8a15SJohn Baldwin 	struct proc *p;
60e602ba25SJulian Elischer 	struct thread *td;
610384fff8SJason Evans 	int error;
620384fff8SJason Evans 
630384fff8SJason Evans #ifdef SMP
640bbc8826SJohn Baldwin 	SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
656caa8a15SJohn Baldwin 		error = kthread_create(idle_proc, NULL, &p,
66316ec49aSScott Long 		    RFSTOPPED | RFHIGHPID, 0, "idle: cpu%d", pc->pc_cpuid);
67079b7badSJulian Elischer 		pc->pc_idlethread = FIRST_THREAD_IN_PROC(p);
687e1f6dfeSJohn Baldwin 		if (pc->pc_curthread == NULL) {
690bbc8826SJohn Baldwin 			pc->pc_curthread = pc->pc_idlethread;
707e1f6dfeSJohn Baldwin 			pc->pc_idlethread->td_critnest = 0;
717e1f6dfeSJohn Baldwin 		}
720384fff8SJason Evans #else
736caa8a15SJohn Baldwin 		error = kthread_create(idle_proc, NULL, &p,
74316ec49aSScott Long 		    RFSTOPPED | RFHIGHPID, 0, "idle");
75079b7badSJulian Elischer 		PCPU_SET(idlethread, FIRST_THREAD_IN_PROC(p));
760384fff8SJason Evans #endif
770384fff8SJason Evans 		if (error)
780384fff8SJason Evans 			panic("idle_setup: kthread_create error %d\n", error);
790384fff8SJason Evans 
80e674d807SJohn Baldwin 		PROC_LOCK(p);
816caa8a15SJohn Baldwin 		p->p_flag |= P_NOLOAD;
82e674d807SJohn Baldwin 		mtx_lock_spin(&sched_lock);
83e602ba25SJulian Elischer 		td = FIRST_THREAD_IN_PROC(p);
84bf0acc27SJohn Baldwin 		TD_SET_CAN_RUN(td);
85b1ac98d8SJulian Elischer 		td->td_flags |= TDF_IDLETD;
86339a7e7fSSuleiman Souhlal 		sched_class(td->td_ksegrp, PRI_IDLE);
87339a7e7fSSuleiman Souhlal 		sched_prio(td, PRI_MAX_IDLE);
88e674d807SJohn Baldwin 		mtx_unlock_spin(&sched_lock);
89e674d807SJohn Baldwin 		PROC_UNLOCK(p);
906caa8a15SJohn Baldwin #ifdef SMP
910384fff8SJason Evans 	}
926caa8a15SJohn Baldwin #endif
930384fff8SJason Evans }
940384fff8SJason Evans 
950384fff8SJason Evans /*
9668d86cf1SPeter Wemm  * The actual idle process.
970384fff8SJason Evans  */
980384fff8SJason Evans static void
990384fff8SJason Evans idle_proc(void *dummy)
1000384fff8SJason Evans {
101e602ba25SJulian Elischer 	struct proc *p;
10268d86cf1SPeter Wemm 	struct thread *td;
1036804a3abSJulian Elischer #ifdef SMP
1046804a3abSJulian Elischer 	cpumask_t mycpu;
1056804a3abSJulian Elischer #endif
1060384fff8SJason Evans 
107e602ba25SJulian Elischer 	td = curthread;
108e602ba25SJulian Elischer 	p = td->td_proc;
1096804a3abSJulian Elischer #ifdef SMP
1106804a3abSJulian Elischer 	mycpu = PCPU_GET(cpumask);
1116804a3abSJulian Elischer 	mtx_lock_spin(&sched_lock);
1126804a3abSJulian Elischer 	idle_cpus_mask |= mycpu;
1136804a3abSJulian Elischer 	mtx_unlock_spin(&sched_lock);
1146804a3abSJulian Elischer #endif
1150384fff8SJason Evans 	for (;;) {
1160384fff8SJason Evans 		mtx_assert(&Giant, MA_NOTOWNED);
1170384fff8SJason Evans 
11868d86cf1SPeter Wemm 		while (sched_runnable() == 0)
119dc13e6dfSJohn Baldwin 			cpu_idle();
1200384fff8SJason Evans 
1219ed346baSBosko Milekic 		mtx_lock_spin(&sched_lock);
1226804a3abSJulian Elischer #ifdef SMP
1236804a3abSJulian Elischer 		idle_cpus_mask &= ~mycpu;
1246804a3abSJulian Elischer #endif
125bf0acc27SJohn Baldwin 		mi_switch(SW_VOL, NULL);
1266804a3abSJulian Elischer #ifdef SMP
1276804a3abSJulian Elischer 		idle_cpus_mask |= mycpu;
1286804a3abSJulian Elischer #endif
1299ed346baSBosko Milekic 		mtx_unlock_spin(&sched_lock);
1300384fff8SJason Evans 	}
1310384fff8SJason Evans }
132