xref: /freebsd/sys/kern/kern_idle.c (revision fb919e4d5a2c1baca52ac70d1064f140fffdda71)
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/kernel.h>
120384fff8SJason Evans #include <sys/ktr.h>
13fb919e4dSMark Murray #include <sys/lock.h>
14fb919e4dSMark Murray #include <sys/mutex.h>
15fb919e4dSMark Murray #include <sys/proc.h>
160384fff8SJason Evans #include <sys/signalvar.h>
176caa8a15SJohn Baldwin #include <sys/smp.h>
180384fff8SJason Evans #include <sys/resourcevar.h>
190384fff8SJason Evans #include <sys/vmmeter.h>
200384fff8SJason Evans #include <sys/sysctl.h>
210384fff8SJason Evans #include <sys/unistd.h>
221931cf94SJohn Baldwin #include <sys/ipl.h>
230384fff8SJason Evans #include <sys/kthread.h>
240384fff8SJason Evans #include <sys/queue.h>
25bdf3d8b9SMike Smith #include <sys/eventhandler.h>
260384fff8SJason Evans #include <vm/vm.h>
270384fff8SJason Evans #include <vm/vm_extern.h>
280384fff8SJason Evans #ifdef KTRACE
290384fff8SJason Evans #include <sys/uio.h>
300384fff8SJason Evans #include <sys/ktrace.h>
310384fff8SJason Evans #endif
320384fff8SJason Evans 
330384fff8SJason Evans #include <machine/cpu.h>
343650b375SJohn Baldwin #include <machine/md_var.h>
350384fff8SJason Evans 
360384fff8SJason Evans #include <machine/globaldata.h>
370384fff8SJason Evans #include <machine/globals.h>
380384fff8SJason Evans 
390384fff8SJason Evans static void idle_setup(void *dummy);
400384fff8SJason Evans SYSINIT(idle_setup, SI_SUB_SCHED_IDLE, SI_ORDER_FIRST, idle_setup, NULL)
410384fff8SJason Evans 
420384fff8SJason Evans static void idle_proc(void *dummy);
430384fff8SJason Evans 
440384fff8SJason Evans /*
457ecfc090SJohn Baldwin  * Setup per-cpu idle process contexts.  The AP's shouldn't be running or
467ecfc090SJohn Baldwin  * accessing their idle processes at this point, so don't bother with
477ecfc090SJohn Baldwin  * locking.
480384fff8SJason Evans  */
490384fff8SJason Evans static void
500384fff8SJason Evans idle_setup(void *dummy)
510384fff8SJason Evans {
526caa8a15SJohn Baldwin #ifdef SMP
530384fff8SJason Evans 	struct globaldata *gd;
546caa8a15SJohn Baldwin #endif
556caa8a15SJohn Baldwin 	struct proc *p;
560384fff8SJason Evans 	int error;
570384fff8SJason Evans 
580384fff8SJason Evans #ifdef SMP
596caa8a15SJohn Baldwin 	SLIST_FOREACH(gd, &cpuhead, gd_allcpu) {
606caa8a15SJohn Baldwin 		error = kthread_create(idle_proc, NULL, &p,
616caa8a15SJohn Baldwin 		    RFSTOPPED | RFHIGHPID, "idle: cpu%d", gd->gd_cpuid);
626caa8a15SJohn Baldwin 		gd->gd_idleproc = p;
636caa8a15SJohn Baldwin 		if (gd->gd_curproc == NULL)
646caa8a15SJohn Baldwin 			gd->gd_curproc = p;
650384fff8SJason Evans #else
666caa8a15SJohn Baldwin 		error = kthread_create(idle_proc, NULL, &p,
670384fff8SJason Evans 		    RFSTOPPED | RFHIGHPID, "idle");
686caa8a15SJohn Baldwin 		PCPU_SET(idleproc, p);
690384fff8SJason Evans #endif
700384fff8SJason Evans 		if (error)
710384fff8SJason Evans 			panic("idle_setup: kthread_create error %d\n", error);
720384fff8SJason Evans 
736caa8a15SJohn Baldwin 		p->p_flag |= P_NOLOAD;
746caa8a15SJohn Baldwin 		p->p_stat = SRUN;
756caa8a15SJohn Baldwin #ifdef SMP
760384fff8SJason Evans 	}
776caa8a15SJohn Baldwin #endif
780384fff8SJason Evans }
790384fff8SJason Evans 
800384fff8SJason Evans /*
810384fff8SJason Evans  * idle process context
820384fff8SJason Evans  */
830384fff8SJason Evans static void
840384fff8SJason Evans idle_proc(void *dummy)
850384fff8SJason Evans {
863650b375SJohn Baldwin #ifdef DIAGNOSTIC
870384fff8SJason Evans 	int count;
883650b375SJohn Baldwin #endif
890384fff8SJason Evans 
900384fff8SJason Evans 	for (;;) {
910384fff8SJason Evans 		mtx_assert(&Giant, MA_NOTOWNED);
920384fff8SJason Evans 
933650b375SJohn Baldwin #ifdef DIAGNOSTIC
940384fff8SJason Evans 		count = 0;
950384fff8SJason Evans 
960384fff8SJason Evans 		while (count >= 0 && procrunnable() == 0) {
973650b375SJohn Baldwin #else
983650b375SJohn Baldwin 		while (procrunnable() == 0) {
993650b375SJohn Baldwin #endif
1000384fff8SJason Evans 		/*
1010384fff8SJason Evans 		 * This is a good place to put things to be done in
1020384fff8SJason Evans 		 * the background, including sanity checks.
1030384fff8SJason Evans 		 */
104bdf3d8b9SMike Smith 
1053650b375SJohn Baldwin #ifdef DIAGNOSTIC
1060384fff8SJason Evans 			if (count++ < 0)
1070384fff8SJason Evans 				CTR0(KTR_PROC, "idle_proc: timed out waiting"
1080384fff8SJason Evans 				    " for a process");
1093650b375SJohn Baldwin #endif
1103650b375SJohn Baldwin 
111d5a08a60SJake Burkholder #if 0
1123650b375SJohn Baldwin 			if (vm_page_zero_idle() != 0)
1133650b375SJohn Baldwin 				continue;
114d5a08a60SJake Burkholder #endif
115bdf3d8b9SMike Smith 
116dc13e6dfSJohn Baldwin #ifdef __i386__
117dc13e6dfSJohn Baldwin 			cpu_idle();
118dc13e6dfSJohn Baldwin #endif
1190384fff8SJason Evans 		}
1200384fff8SJason Evans 
1219ed346baSBosko Milekic 		mtx_lock_spin(&sched_lock);
1227ecfc090SJohn Baldwin 		curproc->p_stats->p_ru.ru_nvcsw++;
1230384fff8SJason Evans 		mi_switch();
1249ed346baSBosko Milekic 		mtx_unlock_spin(&sched_lock);
1250384fff8SJason Evans 	}
1260384fff8SJason Evans }
127