xref: /freebsd/sys/kern/kern_idle.c (revision e602ba25fd1f9a7ea2215c01f470c08f140de809)
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>
13ba228f6dSJohn Baldwin #include <sys/kthread.h>
14fb919e4dSMark Murray #include <sys/lock.h>
15fb919e4dSMark Murray #include <sys/mutex.h>
16ba228f6dSJohn Baldwin #include <sys/pcpu.h>
17fb919e4dSMark Murray #include <sys/proc.h>
180384fff8SJason Evans #include <sys/resourcevar.h>
19ba228f6dSJohn Baldwin #include <sys/smp.h>
200384fff8SJason Evans #include <sys/unistd.h>
210384fff8SJason Evans #ifdef KTRACE
220384fff8SJason Evans #include <sys/uio.h>
230384fff8SJason Evans #include <sys/ktrace.h>
240384fff8SJason Evans #endif
250384fff8SJason Evans 
260384fff8SJason Evans static void idle_setup(void *dummy);
270384fff8SJason Evans SYSINIT(idle_setup, SI_SUB_SCHED_IDLE, SI_ORDER_FIRST, idle_setup, NULL)
280384fff8SJason Evans 
290384fff8SJason Evans static void idle_proc(void *dummy);
300384fff8SJason Evans 
310384fff8SJason Evans /*
327ecfc090SJohn Baldwin  * Setup per-cpu idle process contexts.  The AP's shouldn't be running or
337ecfc090SJohn Baldwin  * accessing their idle processes at this point, so don't bother with
347ecfc090SJohn Baldwin  * locking.
350384fff8SJason Evans  */
360384fff8SJason Evans static void
370384fff8SJason Evans idle_setup(void *dummy)
380384fff8SJason Evans {
396caa8a15SJohn Baldwin #ifdef SMP
400bbc8826SJohn Baldwin 	struct pcpu *pc;
416caa8a15SJohn Baldwin #endif
426caa8a15SJohn Baldwin 	struct proc *p;
43e602ba25SJulian Elischer 	struct thread *td;
440384fff8SJason Evans 	int error;
450384fff8SJason Evans 
460384fff8SJason Evans #ifdef SMP
470bbc8826SJohn Baldwin 	SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
486caa8a15SJohn Baldwin 		error = kthread_create(idle_proc, NULL, &p,
490bbc8826SJohn Baldwin 		    RFSTOPPED | RFHIGHPID, "idle: cpu%d", pc->pc_cpuid);
50079b7badSJulian Elischer 		pc->pc_idlethread = FIRST_THREAD_IN_PROC(p);
517e1f6dfeSJohn Baldwin 		if (pc->pc_curthread == NULL) {
520bbc8826SJohn Baldwin 			pc->pc_curthread = pc->pc_idlethread;
537e1f6dfeSJohn Baldwin 			pc->pc_idlethread->td_critnest = 0;
547e1f6dfeSJohn Baldwin 		}
550384fff8SJason Evans #else
566caa8a15SJohn Baldwin 		error = kthread_create(idle_proc, NULL, &p,
570384fff8SJason Evans 		    RFSTOPPED | RFHIGHPID, "idle");
58079b7badSJulian Elischer 		PCPU_SET(idlethread, FIRST_THREAD_IN_PROC(p));
590384fff8SJason Evans #endif
600384fff8SJason Evans 		if (error)
610384fff8SJason Evans 			panic("idle_setup: kthread_create error %d\n", error);
620384fff8SJason Evans 
636caa8a15SJohn Baldwin 		p->p_flag |= P_NOLOAD;
64e602ba25SJulian Elischer 		td = FIRST_THREAD_IN_PROC(p);
65e602ba25SJulian Elischer 		td->td_state = TDS_RUNQ;
66e602ba25SJulian Elischer 		td->td_kse->ke_state = KES_ONRUNQ;
67e602ba25SJulian Elischer 		td->td_kse->ke_flags |= KEF_IDLEKSE;
686caa8a15SJohn Baldwin #ifdef SMP
690384fff8SJason Evans 	}
706caa8a15SJohn Baldwin #endif
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
82e602ba25SJulian Elischer 	struct thread *td;
83e602ba25SJulian Elischer 	struct proc *p;
840384fff8SJason Evans 
85e602ba25SJulian Elischer 	td = curthread;
86e602ba25SJulian Elischer 	p = td->td_proc;
87e602ba25SJulian Elischer 	td->td_state = TDS_RUNNING;
88e602ba25SJulian Elischer 	td->td_kse->ke_state = KES_RUNNING;
890384fff8SJason Evans 	for (;;) {
900384fff8SJason Evans 		mtx_assert(&Giant, MA_NOTOWNED);
910384fff8SJason Evans 
923650b375SJohn Baldwin #ifdef DIAGNOSTIC
930384fff8SJason Evans 		count = 0;
940384fff8SJason Evans 
95e602ba25SJulian Elischer 		while (count >= 0 && kserunnable() == 0) {
963650b375SJohn Baldwin #else
97e602ba25SJulian Elischer 		while (kserunnable() == 0) {
983650b375SJohn Baldwin #endif
990384fff8SJason Evans 		/*
1000384fff8SJason Evans 		 * This is a good place to put things to be done in
1010384fff8SJason Evans 		 * the background, including sanity checks.
1020384fff8SJason Evans 		 */
103bdf3d8b9SMike Smith 
1043650b375SJohn Baldwin #ifdef DIAGNOSTIC
1050384fff8SJason Evans 			if (count++ < 0)
1060384fff8SJason Evans 				CTR0(KTR_PROC, "idle_proc: timed out waiting"
1070384fff8SJason Evans 				    " for a process");
1083650b375SJohn Baldwin #endif
1093650b375SJohn Baldwin 
110dc13e6dfSJohn Baldwin #ifdef __i386__
111dc13e6dfSJohn Baldwin 			cpu_idle();
112dc13e6dfSJohn Baldwin #endif
1130384fff8SJason Evans 		}
1140384fff8SJason Evans 
1159ed346baSBosko Milekic 		mtx_lock_spin(&sched_lock);
116e602ba25SJulian Elischer 		p->p_stats->p_ru.ru_nvcsw++;
1170384fff8SJason Evans 		mi_switch();
118e602ba25SJulian Elischer 		td->td_kse->ke_state = KES_RUNNING;
1199ed346baSBosko Milekic 		mtx_unlock_spin(&sched_lock);
1200384fff8SJason Evans 	}
1210384fff8SJason Evans }
122