vm_zeroidle.c revision 79273
1/*-
2 * Copyright (c) 1994 John Dyson
3 * Copyright (c) 2001 Matt Dillon
4 *
5 * All rights reserved.  Terms for use and redistribution
6 * are covered by the BSD Copyright as found in /usr/src/COPYRIGHT.
7 *
8 *	from: @(#)vm_machdep.c	7.3 (Berkeley) 5/13/91
9 *	Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
10 * $FreeBSD: head/sys/vm/vm_zeroidle.c 79273 2001-07-05 06:13:44Z mjacob $
11 */
12
13#ifndef	__alpha__
14#include "opt_npx.h"
15#ifdef PC98
16#include "opt_pc98.h"
17#endif
18#include "opt_reset.h"
19#include "opt_isa.h"
20#endif
21
22#include <sys/param.h>
23#include <sys/systm.h>
24#include <sys/malloc.h>
25#include <sys/proc.h>
26#include <sys/bio.h>
27#include <sys/buf.h>
28#include <sys/vnode.h>
29#include <sys/vmmeter.h>
30#include <sys/kernel.h>
31#include <sys/ktr.h>
32#include <sys/mutex.h>
33#include <sys/smp.h>
34#include <sys/sysctl.h>
35#include <sys/unistd.h>
36
37#include <machine/cpu.h>
38#include <machine/md_var.h>
39#include <machine/pcb.h>
40#ifndef	__alpha__
41#include <machine/pcb_ext.h>
42#include <machine/vm86.h>
43#endif
44
45#include <vm/vm.h>
46#include <vm/vm_param.h>
47#include <sys/lock.h>
48#include <vm/vm_kern.h>
49#include <vm/vm_page.h>
50#include <vm/vm_map.h>
51#include <vm/vm_extern.h>
52
53#include <sys/user.h>
54
55#ifndef	__alpha__
56#ifdef PC98
57#include <pc98/pc98/pc98.h>
58#else
59#include <i386/isa/isa.h>
60#endif
61#endif
62
63SYSCTL_DECL(_vm_stats_misc);
64
65static int cnt_prezero;
66
67SYSCTL_INT(_vm_stats_misc, OID_AUTO,
68	cnt_prezero, CTLFLAG_RD, &cnt_prezero, 0, "");
69
70/*
71 * Implement the pre-zeroed page mechanism.
72 * This routine is called from the idle loop.
73 */
74
75#define ZIDLE_LO(v)	((v) * 2 / 3)
76#define ZIDLE_HI(v)	((v) * 4 / 5)
77
78int
79vm_page_zero_idle(void)
80{
81	static int free_rover;
82	static int zero_state;
83	vm_page_t m;
84
85	/*
86	 * Attempt to maintain approximately 1/2 of our free pages in a
87	 * PG_ZERO'd state.   Add some hysteresis to (attempt to) avoid
88	 * generally zeroing a page when the system is near steady-state.
89	 * Otherwise we might get 'flutter' during disk I/O / IPC or
90	 * fast sleeps.  We also do not want to be continuously zeroing
91	 * pages because doing so may flush our L1 and L2 caches too much.
92	 */
93
94	if (zero_state && vm_page_zero_count >= ZIDLE_LO(cnt.v_free_count))
95		return(0);
96	if (vm_page_zero_count >= ZIDLE_HI(cnt.v_free_count))
97		return(0);
98
99	if (mtx_trylock(&Giant)) {
100		zero_state = 0;
101		m = vm_pageq_find(PQ_FREE, free_rover, FALSE);
102		if (m != NULL && (m->flags & PG_ZERO) == 0) {
103			vm_page_queues[m->queue].lcnt--;
104			TAILQ_REMOVE(&vm_page_queues[m->queue].pl, m, pageq);
105			m->queue = PQ_NONE;
106			pmap_zero_page(VM_PAGE_TO_PHYS(m));
107			vm_page_flag_set(m, PG_ZERO);
108			m->queue = PQ_FREE + m->pc;
109			vm_page_queues[m->queue].lcnt++;
110			TAILQ_INSERT_TAIL(&vm_page_queues[m->queue].pl, m,
111			    pageq);
112			++vm_page_zero_count;
113			++cnt_prezero;
114			if (vm_page_zero_count >= ZIDLE_HI(cnt.v_free_count))
115				zero_state = 1;
116		}
117		free_rover = (free_rover + PQ_PRIME2) & PQ_L2_MASK;
118		mtx_unlock(&Giant);
119		return (1);
120	}
121	return(0);
122}
123
124