xref: /freebsd/sys/kern/kern_idle.c (revision 3a51f88a2721f4cf7aded2a63f20925f8d700a7c)
1 /*-
2  * Copyright (c) 2000, All rights reserved.  See /usr/src/COPYRIGHT
3  *
4  * $FreeBSD$
5  */
6 
7 #include "opt_ktrace.h"
8 
9 #include <sys/param.h>
10 #include <sys/systm.h>
11 #include <sys/kernel.h>
12 #include <sys/ktr.h>
13 #include <sys/lock.h>
14 #include <sys/mutex.h>
15 #include <sys/proc.h>
16 #include <sys/signalvar.h>
17 #include <sys/smp.h>
18 #include <sys/resourcevar.h>
19 #include <sys/vmmeter.h>
20 #include <sys/sysctl.h>
21 #include <sys/unistd.h>
22 #include <sys/ipl.h>
23 #include <sys/kthread.h>
24 #include <sys/queue.h>
25 #include <sys/eventhandler.h>
26 #include <vm/vm.h>
27 #include <vm/vm_extern.h>
28 #ifdef KTRACE
29 #include <sys/uio.h>
30 #include <sys/ktrace.h>
31 #endif
32 
33 #include <machine/cpu.h>
34 #include <machine/md_var.h>
35 
36 #include <machine/globaldata.h>
37 #include <machine/globals.h>
38 
39 static void idle_setup(void *dummy);
40 SYSINIT(idle_setup, SI_SUB_SCHED_IDLE, SI_ORDER_FIRST, idle_setup, NULL)
41 
42 static void idle_proc(void *dummy);
43 
44 /*
45  * Setup per-cpu idle process contexts.  The AP's shouldn't be running or
46  * accessing their idle processes at this point, so don't bother with
47  * locking.
48  */
49 static void
50 idle_setup(void *dummy)
51 {
52 #ifdef SMP
53 	struct globaldata *gd;
54 #endif
55 	struct proc *p;
56 	int error;
57 
58 #ifdef SMP
59 	SLIST_FOREACH(gd, &cpuhead, gd_allcpu) {
60 		error = kthread_create(idle_proc, NULL, &p,
61 		    RFSTOPPED | RFHIGHPID, "idle: cpu%d", gd->gd_cpuid);
62 		gd->gd_idleproc = p;
63 		if (gd->gd_curproc == NULL)
64 			gd->gd_curproc = p;
65 #else
66 		error = kthread_create(idle_proc, NULL, &p,
67 		    RFSTOPPED | RFHIGHPID, "idle");
68 		PCPU_SET(idleproc, p);
69 #endif
70 		if (error)
71 			panic("idle_setup: kthread_create error %d\n", error);
72 
73 		p->p_flag |= P_NOLOAD;
74 		p->p_stat = SRUN;
75 #ifdef SMP
76 	}
77 #endif
78 }
79 
80 /*
81  * idle process context
82  */
83 static void
84 idle_proc(void *dummy)
85 {
86 #ifdef DIAGNOSTIC
87 	int count;
88 #endif
89 
90 	for (;;) {
91 		mtx_assert(&Giant, MA_NOTOWNED);
92 
93 #ifdef DIAGNOSTIC
94 		count = 0;
95 
96 		while (count >= 0 && procrunnable() == 0) {
97 #else
98 		while (procrunnable() == 0) {
99 #endif
100 		/*
101 		 * This is a good place to put things to be done in
102 		 * the background, including sanity checks.
103 		 */
104 
105 #ifdef DIAGNOSTIC
106 			if (count++ < 0)
107 				CTR0(KTR_PROC, "idle_proc: timed out waiting"
108 				    " for a process");
109 #endif
110 
111 #if 0
112 			if (vm_page_zero_idle() != 0)
113 				continue;
114 #endif
115 
116 #ifdef __i386__
117 			cpu_idle();
118 #endif
119 		}
120 
121 		mtx_lock_spin(&sched_lock);
122 		curproc->p_stats->p_ru.ru_nvcsw++;
123 		mi_switch();
124 		mtx_unlock_spin(&sched_lock);
125 	}
126 }
127