xref: /freebsd/sys/kern/kern_idle.c (revision 7ecfc090c0f50591327a2519c9cf1dc33e594aca)
10384fff8SJason Evans /*-
20384fff8SJason Evans  * Copyright (c) 2000, All rights reserved.  See /usr/src/COPYRIGHT
30384fff8SJason Evans  *
40384fff8SJason Evans  * $FreeBSD$
50384fff8SJason Evans  */
60384fff8SJason Evans 
70384fff8SJason Evans #include "opt_ktrace.h"
80384fff8SJason Evans 
90384fff8SJason Evans #include <sys/param.h>
100384fff8SJason Evans #include <sys/systm.h>
110384fff8SJason Evans #include <sys/proc.h>
120384fff8SJason Evans #include <sys/kernel.h>
130384fff8SJason Evans #include <sys/ktr.h>
140384fff8SJason Evans #include <sys/signalvar.h>
150384fff8SJason Evans #include <sys/resourcevar.h>
160384fff8SJason Evans #include <sys/vmmeter.h>
170384fff8SJason Evans #include <sys/sysctl.h>
180384fff8SJason Evans #include <sys/unistd.h>
191931cf94SJohn Baldwin #include <sys/ipl.h>
200384fff8SJason Evans #include <sys/kthread.h>
2135e0e5b3SJohn Baldwin #include <sys/mutex.h>
220384fff8SJason Evans #include <sys/queue.h>
23bdf3d8b9SMike Smith #include <sys/eventhandler.h>
240384fff8SJason Evans #include <vm/vm.h>
250384fff8SJason Evans #include <vm/vm_extern.h>
260384fff8SJason Evans #ifdef KTRACE
270384fff8SJason Evans #include <sys/uio.h>
280384fff8SJason Evans #include <sys/ktrace.h>
290384fff8SJason Evans #endif
300384fff8SJason Evans 
310384fff8SJason Evans #include <machine/cpu.h>
323650b375SJohn Baldwin #include <machine/md_var.h>
330384fff8SJason Evans #include <machine/smp.h>
340384fff8SJason Evans 
350384fff8SJason Evans #include <machine/globaldata.h>
360384fff8SJason Evans #include <machine/globals.h>
370384fff8SJason Evans 
380384fff8SJason Evans static void idle_setup(void *dummy);
390384fff8SJason Evans SYSINIT(idle_setup, SI_SUB_SCHED_IDLE, SI_ORDER_FIRST, idle_setup, NULL)
400384fff8SJason Evans 
410384fff8SJason Evans static void idle_proc(void *dummy);
420384fff8SJason Evans 
430384fff8SJason Evans /*
447ecfc090SJohn Baldwin  * Setup per-cpu idle process contexts.  The AP's shouldn't be running or
457ecfc090SJohn Baldwin  * accessing their idle processes at this point, so don't bother with
467ecfc090SJohn Baldwin  * locking.
470384fff8SJason Evans  */
480384fff8SJason Evans static void
490384fff8SJason Evans idle_setup(void *dummy)
500384fff8SJason Evans {
510384fff8SJason Evans 	struct globaldata *gd;
520384fff8SJason Evans 	int error;
530384fff8SJason Evans 
540384fff8SJason Evans 	SLIST_FOREACH(gd, &cpuhead, gd_allcpu) {
550384fff8SJason Evans #ifdef SMP
560384fff8SJason Evans 		error = kthread_create(idle_proc, NULL, &gd->gd_idleproc,
570384fff8SJason Evans 				       RFSTOPPED|RFHIGHPID, "idle: cpu%d",
580384fff8SJason Evans 				       gd->gd_cpuid);
590384fff8SJason Evans #else
600384fff8SJason Evans 		error = kthread_create(idle_proc, NULL, &gd->gd_idleproc,
610384fff8SJason Evans 				       RFSTOPPED|RFHIGHPID, "idle");
620384fff8SJason Evans #endif
630384fff8SJason Evans 		if (error)
640384fff8SJason Evans 			panic("idle_setup: kthread_create error %d\n", error);
650384fff8SJason Evans 
667ab37af1SJohn Baldwin 		gd->gd_idleproc->p_flag |= P_NOLOAD;
67f6a0af80SJohn Baldwin 		gd->gd_idleproc->p_stat = SRUN;
687ecfc090SJohn Baldwin 		if (gd->gd_curproc == NULL)
697ecfc090SJohn Baldwin 			gd->gd_curproc = gd->gd_idleproc;
700384fff8SJason Evans 	}
710384fff8SJason Evans }
720384fff8SJason Evans 
730384fff8SJason Evans /*
740384fff8SJason Evans  * idle process context
750384fff8SJason Evans  */
760384fff8SJason Evans static void
770384fff8SJason Evans idle_proc(void *dummy)
780384fff8SJason Evans {
793650b375SJohn Baldwin #ifdef DIAGNOSTIC
800384fff8SJason Evans 	int count;
813650b375SJohn Baldwin #endif
820384fff8SJason Evans 
830384fff8SJason Evans 	for (;;) {
840384fff8SJason Evans 		mtx_assert(&Giant, MA_NOTOWNED);
850384fff8SJason Evans 
863650b375SJohn Baldwin #ifdef DIAGNOSTIC
870384fff8SJason Evans 		count = 0;
880384fff8SJason Evans 
890384fff8SJason Evans 		while (count >= 0 && procrunnable() == 0) {
903650b375SJohn Baldwin #else
913650b375SJohn Baldwin 		while (procrunnable() == 0) {
923650b375SJohn Baldwin #endif
930384fff8SJason Evans 		/*
940384fff8SJason Evans 		 * This is a good place to put things to be done in
950384fff8SJason Evans 		 * the background, including sanity checks.
960384fff8SJason Evans 		 */
97bdf3d8b9SMike Smith 
983650b375SJohn Baldwin #ifdef DIAGNOSTIC
990384fff8SJason Evans 			if (count++ < 0)
1000384fff8SJason Evans 				CTR0(KTR_PROC, "idle_proc: timed out waiting"
1010384fff8SJason Evans 				    " for a process");
1023650b375SJohn Baldwin #endif
1033650b375SJohn Baldwin 
1043650b375SJohn Baldwin 			if (vm_page_zero_idle() != 0)
1053650b375SJohn Baldwin 				continue;
106bdf3d8b9SMike Smith 
107dc13e6dfSJohn Baldwin #ifdef __i386__
108dc13e6dfSJohn Baldwin 			cpu_idle();
109dc13e6dfSJohn Baldwin #endif
1100384fff8SJason Evans 		}
1110384fff8SJason Evans 
1129ed346baSBosko Milekic 		mtx_lock_spin(&sched_lock);
1137ecfc090SJohn Baldwin 		curproc->p_stats->p_ru.ru_nvcsw++;
1140384fff8SJason Evans 		mi_switch();
1159ed346baSBosko Milekic 		mtx_unlock_spin(&sched_lock);
1160384fff8SJason Evans 	}
1170384fff8SJason Evans }
118