xref: /dflybsd-src/sys/vm/vm_page2.h (revision 2198d48d13b680ca7a6ab9e1b5ca226967bcc1e5)
112e4aaffSMatthew Dillon /*-
212e4aaffSMatthew Dillon  * Copyright (c) 1982, 1986, 1993
312e4aaffSMatthew Dillon  *	The Regents of the University of California.  All rights reserved.
412e4aaffSMatthew Dillon  *
512e4aaffSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
612e4aaffSMatthew Dillon  * modification, are permitted provided that the following conditions
712e4aaffSMatthew Dillon  * are met:
812e4aaffSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
912e4aaffSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
1012e4aaffSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
1112e4aaffSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in the
1212e4aaffSMatthew Dillon  *    documentation and/or other materials provided with the distribution.
132c64e990Szrj  * 3. Neither the name of the University nor the names of its contributors
1412e4aaffSMatthew Dillon  *    may be used to endorse or promote products derived from this software
1512e4aaffSMatthew Dillon  *    without specific prior written permission.
1612e4aaffSMatthew Dillon  *
1712e4aaffSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1812e4aaffSMatthew Dillon  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1912e4aaffSMatthew Dillon  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2012e4aaffSMatthew Dillon  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2112e4aaffSMatthew Dillon  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2212e4aaffSMatthew Dillon  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2312e4aaffSMatthew Dillon  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2412e4aaffSMatthew Dillon  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2512e4aaffSMatthew Dillon  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2612e4aaffSMatthew Dillon  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2712e4aaffSMatthew Dillon  * SUCH DAMAGE.
2812e4aaffSMatthew Dillon  *
2912e4aaffSMatthew Dillon  *	@(#)vmmeter.h	8.2 (Berkeley) 7/10/94
3012e4aaffSMatthew Dillon  * $FreeBSD: src/sys/sys/vmmeter.h,v 1.21.2.2 2002/10/10 19:28:21 dillon Exp $
3112e4aaffSMatthew Dillon  */
3212e4aaffSMatthew Dillon 
331bd40720SMatthew Dillon #ifndef _VM_VM_PAGE2_H_
341bd40720SMatthew Dillon #define _VM_VM_PAGE2_H_
3512e4aaffSMatthew Dillon 
363f397408STomohiro Kusumi #ifdef _KERNEL
373f397408STomohiro Kusumi 
3812e4aaffSMatthew Dillon #ifndef _SYS_VMMETER_H_
3912e4aaffSMatthew Dillon #include <sys/vmmeter.h>
4012e4aaffSMatthew Dillon #endif
4110192baeSMatthew Dillon #ifndef _SYS_QUEUE_H_
4210192baeSMatthew Dillon #include <sys/queue.h>
4310192baeSMatthew Dillon #endif
44210a0869SSascha Wildner #ifndef _VM_VM_PAGE_H_
4510192baeSMatthew Dillon #include <vm/vm_page.h>
4610192baeSMatthew Dillon #endif
47b12defdcSMatthew Dillon #ifndef _SYS_SPINLOCK_H_
48b12defdcSMatthew Dillon #include <sys/spinlock.h>
49b12defdcSMatthew Dillon #endif
50b12defdcSMatthew Dillon #ifndef _SYS_SPINLOCK2_H_
51b12defdcSMatthew Dillon #include <sys/spinlock2.h>
52b12defdcSMatthew Dillon #endif
5312e4aaffSMatthew Dillon 
5412e4aaffSMatthew Dillon /*
5575979118SMatthew Dillon  * SMP NOTE
5675979118SMatthew Dillon  *
5775979118SMatthew Dillon  * VM fault rates are highly dependent on SMP locking conflicts and, on
5875979118SMatthew Dillon  * multi-socket systems, cache mastership changes for globals due to atomic
5975979118SMatthew Dillon  * ops (even simple atomic_add_*() calls).  Cache mastership changes can
6075979118SMatthew Dillon  * limit the aggregate fault rate.
6175979118SMatthew Dillon  *
6275979118SMatthew Dillon  * For this reason we go through some hoops to access VM statistics for
6375979118SMatthew Dillon  * low-memory handling, pageout, and other triggers.  Each cpu collects
6475979118SMatthew Dillon  * adjustments in gd->gd_vmstats_adj.  These get rolled up into the global
6575979118SMatthew Dillon  * vmstats structure.  The global vmstats structure is then pulled into
6675979118SMatthew Dillon  * gd->gd_vmstats by each cpu when it needs it.  Critical path checks always
6775979118SMatthew Dillon  * use the pcpu gd->gd_vmstats structure.
6875979118SMatthew Dillon  */
6975979118SMatthew Dillon /*
7012e4aaffSMatthew Dillon  * Return TRUE if we are under our severe low-free-pages threshold
7112e4aaffSMatthew Dillon  *
7220479584SMatthew Dillon  * This causes user processes to stall to avoid exhausting memory that
7320479584SMatthew Dillon  * the kernel might need.
7420479584SMatthew Dillon  *
75e91e64c7SMatthew Dillon  * reserved < severe < minimum < wait < start < target1 < target2
7612e4aaffSMatthew Dillon  */
7712e4aaffSMatthew Dillon static __inline
7812e4aaffSMatthew Dillon int
vm_paging_severe(void)79e91e64c7SMatthew Dillon vm_paging_severe(void)
8012e4aaffSMatthew Dillon {
8175979118SMatthew Dillon 	globaldata_t gd = mycpu;
8275979118SMatthew Dillon 
83e91e64c7SMatthew Dillon 	if (__predict_false(gd->gd_vmstats.v_free_severe >
84e91e64c7SMatthew Dillon 			    gd->gd_vmstats.v_free_count +
85e91e64c7SMatthew Dillon 			    gd->gd_vmstats.v_cache_count))
86e91e64c7SMatthew Dillon 	{
87e91e64c7SMatthew Dillon 		return 1;
88e91e64c7SMatthew Dillon 	}
89e91e64c7SMatthew Dillon 	if (__predict_false(gd->gd_vmstats.v_free_reserved >
90e91e64c7SMatthew Dillon 			    gd->gd_vmstats.v_free_count))
91e91e64c7SMatthew Dillon 	{
92e91e64c7SMatthew Dillon 		return 1;
93e91e64c7SMatthew Dillon 	}
94e91e64c7SMatthew Dillon 	return 0;
9512e4aaffSMatthew Dillon }
9612e4aaffSMatthew Dillon 
9712e4aaffSMatthew Dillon /*
98e91e64c7SMatthew Dillon  * Return TRUE if we are under our minimum low-free-pages threshold.  We
99e91e64c7SMatthew Dillon  * will not count (donotcount) free pages as being free (used mainly for
100e91e64c7SMatthew Dillon  * hystersis tests).
10112e4aaffSMatthew Dillon  *
102e91e64c7SMatthew Dillon  * This will cause most normal page faults to block and activate the
103e91e64c7SMatthew Dillon  * pageout daemon.
104e91e64c7SMatthew Dillon  *
105e91e64c7SMatthew Dillon  * The pageout daemon should already be active due to vm_paging_start(n)
106e91e64c7SMatthew Dillon  * and will typically continue running until it hits target2
107e91e64c7SMatthew Dillon  *
108e91e64c7SMatthew Dillon  * reserved < severe < minimum < wait < start < target1 < target2
10912e4aaffSMatthew Dillon  */
11012e4aaffSMatthew Dillon static __inline
11112e4aaffSMatthew Dillon int
vm_paging_min_dnc(long donotcount)112e91e64c7SMatthew Dillon vm_paging_min_dnc(long donotcount)
11312e4aaffSMatthew Dillon {
11475979118SMatthew Dillon 	globaldata_t gd = mycpu;
11575979118SMatthew Dillon 
116e91e64c7SMatthew Dillon 	if (__predict_false(gd->gd_vmstats.v_free_min + donotcount >
117e91e64c7SMatthew Dillon 			    (gd->gd_vmstats.v_free_count +
118e91e64c7SMatthew Dillon 			     gd->gd_vmstats.v_cache_count)))
119e91e64c7SMatthew Dillon 	{
120e91e64c7SMatthew Dillon 		return 1;
121e91e64c7SMatthew Dillon 	}
122e91e64c7SMatthew Dillon 	if (__predict_false(gd->gd_vmstats.v_free_reserved >
123e91e64c7SMatthew Dillon 			    gd->gd_vmstats.v_free_count))
124e91e64c7SMatthew Dillon 	{
125e91e64c7SMatthew Dillon 		return 1;
126e91e64c7SMatthew Dillon 	}
127e91e64c7SMatthew Dillon 	return 0;
128e91e64c7SMatthew Dillon }
129e91e64c7SMatthew Dillon 
130*2198d48dSMatthew Dillon /*
131*2198d48dSMatthew Dillon  * Returns TRUE if the number of FREE+CACHE pages falls below vm_paging_wait,
132*2198d48dSMatthew Dillon  * based on the nice value the trip point can be between vm_paging_min and
133*2198d48dSMatthew Dillon  * vm_paging_wait.
134*2198d48dSMatthew Dillon  *
135*2198d48dSMatthew Dillon  * Used by vm_fault (see vm_wait_pfault()) to block a process on low-memory
136*2198d48dSMatthew Dillon  * based on the process 'nice' value (-20 to +20).
137*2198d48dSMatthew Dillon  */
138*2198d48dSMatthew Dillon static __inline
139*2198d48dSMatthew Dillon int
vm_paging_min_nice(int nice)140*2198d48dSMatthew Dillon vm_paging_min_nice(int nice)
141*2198d48dSMatthew Dillon {
142*2198d48dSMatthew Dillon 	long count;
143*2198d48dSMatthew Dillon 	long delta;
144*2198d48dSMatthew Dillon 
145*2198d48dSMatthew Dillon 	count = 0;
146*2198d48dSMatthew Dillon 	if (nice) {
147*2198d48dSMatthew Dillon 		delta = vmstats.v_paging_wait - vmstats.v_free_min - 1;
148*2198d48dSMatthew Dillon 		delta = delta >> 1;
149*2198d48dSMatthew Dillon 		if (delta > 0) {
150*2198d48dSMatthew Dillon 			/* range 0-40, 0 is high priority, 40 is low */
151*2198d48dSMatthew Dillon 			count = (nice + 20) * delta / 40;
152*2198d48dSMatthew Dillon 		}
153*2198d48dSMatthew Dillon 	}
154*2198d48dSMatthew Dillon 	return vm_paging_min_dnc(count);
155*2198d48dSMatthew Dillon }
156*2198d48dSMatthew Dillon 
157e91e64c7SMatthew Dillon static __inline
158e91e64c7SMatthew Dillon int
vm_paging_min(void)159e91e64c7SMatthew Dillon vm_paging_min(void)
160e91e64c7SMatthew Dillon {
161e91e64c7SMatthew Dillon 	return vm_paging_min_dnc(0);
16212e4aaffSMatthew Dillon }
16312e4aaffSMatthew Dillon 
16412e4aaffSMatthew Dillon /*
165e91e64c7SMatthew Dillon  * Return TRUE if nominal userland / VM-system allocations should slow
166e91e64c7SMatthew Dillon  * down (but not stop) due to low free pages in the system.  This is
167e91e64c7SMatthew Dillon  * typically 1/2 way between min and start.
16877d1fb91SMatthew Dillon  *
169e91e64c7SMatthew Dillon  * reserved < severe < minimum < wait < start < target1 < target2
17012e4aaffSMatthew Dillon  */
17112e4aaffSMatthew Dillon static __inline
17212e4aaffSMatthew Dillon int
vm_paging_wait(void)173e91e64c7SMatthew Dillon vm_paging_wait(void)
17412e4aaffSMatthew Dillon {
17575979118SMatthew Dillon 	globaldata_t gd = mycpu;
17675979118SMatthew Dillon 
177e91e64c7SMatthew Dillon 	if (__predict_false(gd->gd_vmstats.v_paging_wait >
178e91e64c7SMatthew Dillon 			    (gd->gd_vmstats.v_free_count +
179e91e64c7SMatthew Dillon 			     gd->gd_vmstats.v_cache_count)))
180e91e64c7SMatthew Dillon         {
181e91e64c7SMatthew Dillon 		return 1;
182e91e64c7SMatthew Dillon 	}
183e91e64c7SMatthew Dillon 	if (__predict_false(gd->gd_vmstats.v_free_reserved >
184e91e64c7SMatthew Dillon 			    gd->gd_vmstats.v_free_count))
185e91e64c7SMatthew Dillon 	{
186e91e64c7SMatthew Dillon 		return 1;
187e91e64c7SMatthew Dillon 	}
188e91e64c7SMatthew Dillon 	return 0;
18912e4aaffSMatthew Dillon }
19012e4aaffSMatthew Dillon 
19112e4aaffSMatthew Dillon /*
192e91e64c7SMatthew Dillon  * Return TRUE if the pageout daemon should be started up or continue
193e91e64c7SMatthew Dillon  * running.  Available pages have dropped to a level where we need to
194e91e64c7SMatthew Dillon  * think about freeing some up.
195cd3c66bdSMatthew Dillon  *
196e91e64c7SMatthew Dillon  * Also handles edge cases for required 'actually-free' pages.
197cd3c66bdSMatthew Dillon  *
198e91e64c7SMatthew Dillon  * reserved < severe < minimum < wait < start < target1 < target2
199e91e64c7SMatthew Dillon  */
200e91e64c7SMatthew Dillon static __inline
201e91e64c7SMatthew Dillon int
vm_paging_start(int adj)202e91e64c7SMatthew Dillon vm_paging_start(int adj)
203e91e64c7SMatthew Dillon {
204e91e64c7SMatthew Dillon 	globaldata_t gd = mycpu;
205e91e64c7SMatthew Dillon 
206e91e64c7SMatthew Dillon 	if (__predict_false(gd->gd_vmstats.v_paging_start >
207e91e64c7SMatthew Dillon 			    (gd->gd_vmstats.v_free_count +
208e91e64c7SMatthew Dillon 			     gd->gd_vmstats.v_cache_count + adj)))
209e91e64c7SMatthew Dillon 	{
210e91e64c7SMatthew Dillon 		return 1;
211e91e64c7SMatthew Dillon 	}
212e91e64c7SMatthew Dillon 	if (__predict_false(gd->gd_vmstats.v_free_min >
213e91e64c7SMatthew Dillon 			    gd->gd_vmstats.v_free_count + adj))
214e91e64c7SMatthew Dillon 	{
215e91e64c7SMatthew Dillon 		return 1;
216e91e64c7SMatthew Dillon 	}
217e91e64c7SMatthew Dillon 	if (__predict_false(gd->gd_vmstats.v_free_reserved >
218e91e64c7SMatthew Dillon 			    gd->gd_vmstats.v_free_count))
219e91e64c7SMatthew Dillon 	{
220e91e64c7SMatthew Dillon 		return 1;
221e91e64c7SMatthew Dillon 	}
222e91e64c7SMatthew Dillon 	return 0;
223e91e64c7SMatthew Dillon }
224e91e64c7SMatthew Dillon 
225e91e64c7SMatthew Dillon /*
226e91e64c7SMatthew Dillon  * Return TRUE if the pageout daemon has not yet reached its initial target.
227e91e64c7SMatthew Dillon  * The pageout daemon works hard to reach target1.
228e91e64c7SMatthew Dillon  *
229e91e64c7SMatthew Dillon  * reserved < severe < minimum < wait < start < target1 < target2
230e91e64c7SMatthew Dillon  */
231e91e64c7SMatthew Dillon static __inline
232e91e64c7SMatthew Dillon int
vm_paging_target1(void)233e91e64c7SMatthew Dillon vm_paging_target1(void)
234e91e64c7SMatthew Dillon {
235e91e64c7SMatthew Dillon 	globaldata_t gd = mycpu;
236e91e64c7SMatthew Dillon 
237e91e64c7SMatthew Dillon 	if (__predict_false(gd->gd_vmstats.v_paging_target1 >
238e91e64c7SMatthew Dillon 			    (gd->gd_vmstats.v_free_count +
239e91e64c7SMatthew Dillon 			     gd->gd_vmstats.v_cache_count)))
240e91e64c7SMatthew Dillon 	{
241e91e64c7SMatthew Dillon 		return 1;
242e91e64c7SMatthew Dillon 	}
243e91e64c7SMatthew Dillon 	if (__predict_false(gd->gd_vmstats.v_free_reserved >
244e91e64c7SMatthew Dillon 			    gd->gd_vmstats.v_free_count))
245e91e64c7SMatthew Dillon 	{
246e91e64c7SMatthew Dillon 		return 1;
247e91e64c7SMatthew Dillon 	}
248e91e64c7SMatthew Dillon 	return 0;
249e91e64c7SMatthew Dillon }
250e91e64c7SMatthew Dillon 
251e91e64c7SMatthew Dillon static __inline
252e91e64c7SMatthew Dillon long
vm_paging_target1_count(void)253e91e64c7SMatthew Dillon vm_paging_target1_count(void)
254e91e64c7SMatthew Dillon {
255e91e64c7SMatthew Dillon 	globaldata_t gd = mycpu;
256e91e64c7SMatthew Dillon 	long delta;
257e91e64c7SMatthew Dillon 
258e91e64c7SMatthew Dillon 	delta = gd->gd_vmstats.v_paging_target1 -
259e91e64c7SMatthew Dillon 		(gd->gd_vmstats.v_free_count + gd->gd_vmstats.v_cache_count);
260e91e64c7SMatthew Dillon 	return delta;
261e91e64c7SMatthew Dillon }
262e91e64c7SMatthew Dillon 
263e91e64c7SMatthew Dillon /*
264e91e64c7SMatthew Dillon  * Return TRUE if the pageout daemon has not yet reached its final target.
265e91e64c7SMatthew Dillon  * The pageout daemon takes it easy on its way between target1 and target2.
266e91e64c7SMatthew Dillon  *
267e91e64c7SMatthew Dillon  * reserved < severe < minimum < wait < start < target1 < target2
268e91e64c7SMatthew Dillon  */
269e91e64c7SMatthew Dillon static __inline
270e91e64c7SMatthew Dillon int
vm_paging_target2(void)271e91e64c7SMatthew Dillon vm_paging_target2(void)
272e91e64c7SMatthew Dillon {
273e91e64c7SMatthew Dillon 	globaldata_t gd = mycpu;
274e91e64c7SMatthew Dillon 
275e91e64c7SMatthew Dillon 	if (__predict_false(gd->gd_vmstats.v_paging_target2 >
276e91e64c7SMatthew Dillon 			    (gd->gd_vmstats.v_free_count +
277e91e64c7SMatthew Dillon 			     gd->gd_vmstats.v_cache_count)))
278e91e64c7SMatthew Dillon 	{
279e91e64c7SMatthew Dillon 		return 1;
280e91e64c7SMatthew Dillon 	}
281e91e64c7SMatthew Dillon 	if (__predict_false(gd->gd_vmstats.v_free_reserved >
282e91e64c7SMatthew Dillon 			    gd->gd_vmstats.v_free_count))
283e91e64c7SMatthew Dillon 	{
284e91e64c7SMatthew Dillon 		return 1;
285e91e64c7SMatthew Dillon 	}
286e91e64c7SMatthew Dillon 	return 0;
287e91e64c7SMatthew Dillon }
288e91e64c7SMatthew Dillon 
289e91e64c7SMatthew Dillon static __inline
290e91e64c7SMatthew Dillon long
vm_paging_target2_count(void)291e91e64c7SMatthew Dillon vm_paging_target2_count(void)
292e91e64c7SMatthew Dillon {
293e91e64c7SMatthew Dillon 	globaldata_t gd = mycpu;
294e91e64c7SMatthew Dillon 	long delta;
295e91e64c7SMatthew Dillon 
296e91e64c7SMatthew Dillon 	delta = gd->gd_vmstats.v_paging_target2 -
297e91e64c7SMatthew Dillon 		(gd->gd_vmstats.v_free_count + gd->gd_vmstats.v_cache_count);
298e91e64c7SMatthew Dillon 	return delta;
299e91e64c7SMatthew Dillon }
300e91e64c7SMatthew Dillon 
301e91e64c7SMatthew Dillon /*
302e91e64c7SMatthew Dillon  * Returns TRUE if additional pages must be deactivated, either during a
303e91e64c7SMatthew Dillon  * pageout operation or during the page stats scan.
304e91e64c7SMatthew Dillon  *
305e91e64c7SMatthew Dillon  * Inactive tests are used in two places.  During heavy paging the
306e91e64c7SMatthew Dillon  * inactive_target is used to refill the inactive queue in staged.
307e91e64c7SMatthew Dillon  * Those pages are then ultimately flushed and moved to the cache or free
308e91e64c7SMatthew Dillon  * queues.
309e91e64c7SMatthew Dillon  *
310e91e64c7SMatthew Dillon  * The inactive queue is also used to manage scans to update page stats
311e91e64c7SMatthew Dillon  * (m->act_count).  The page stats scan occurs lazily in small batches to
312e91e64c7SMatthew Dillon  * update m->act_count for pages in the active queue and to move pages
313e91e64c7SMatthew Dillon  * (limited by inactive_target) to the inactive queue.  Page stats scanning
314e91e64c7SMatthew Dillon  * and active deactivations only run while the inactive queue is below target.
315e91e64c7SMatthew Dillon  * After this, additional page stats scanning just to update m->act_count
316e91e64c7SMatthew Dillon  * (but not do further deactivations) continues to run for a limited period
317e91e64c7SMatthew Dillon  * of time after any pageout daemon activity.
318e91e64c7SMatthew Dillon  */
319e91e64c7SMatthew Dillon static __inline
320e91e64c7SMatthew Dillon int
vm_paging_inactive(void)321e91e64c7SMatthew Dillon vm_paging_inactive(void)
322e91e64c7SMatthew Dillon {
323e91e64c7SMatthew Dillon 	globaldata_t gd = mycpu;
324e91e64c7SMatthew Dillon 
325e91e64c7SMatthew Dillon 	if (__predict_false((gd->gd_vmstats.v_free_count +
326e91e64c7SMatthew Dillon 			     gd->gd_vmstats.v_cache_count +
327e91e64c7SMatthew Dillon 			     gd->gd_vmstats.v_inactive_count) <
328e91e64c7SMatthew Dillon 			    (gd->gd_vmstats.v_free_min +
329e91e64c7SMatthew Dillon 			     gd->gd_vmstats.v_inactive_target)))
330e91e64c7SMatthew Dillon 	{
331e91e64c7SMatthew Dillon 		return 1;
332e91e64c7SMatthew Dillon 	}
333e91e64c7SMatthew Dillon 	return 0;
334e91e64c7SMatthew Dillon }
335e91e64c7SMatthew Dillon 
336e91e64c7SMatthew Dillon /*
337e91e64c7SMatthew Dillon  * Return number of pages that need to be deactivated to achieve the inactive
338e91e64c7SMatthew Dillon  * target as a positive number.  A negative number indicates that there are
339e91e64c7SMatthew Dillon  * already a sufficient number of inactive pages.
34012e4aaffSMatthew Dillon  */
34112e4aaffSMatthew Dillon static __inline
342b7ea2f3fSMatthew Dillon long
vm_paging_inactive_count(void)343e91e64c7SMatthew Dillon vm_paging_inactive_count(void)
34412e4aaffSMatthew Dillon {
34575979118SMatthew Dillon 	globaldata_t gd = mycpu;
346e91e64c7SMatthew Dillon 	long delta;
34775979118SMatthew Dillon 
348e91e64c7SMatthew Dillon 	delta = (gd->gd_vmstats.v_free_min + gd->gd_vmstats.v_inactive_target) -
349e91e64c7SMatthew Dillon 		(gd->gd_vmstats.v_free_count + gd->gd_vmstats.v_cache_count +
350e91e64c7SMatthew Dillon 		 gd->gd_vmstats.v_inactive_count);
35112e4aaffSMatthew Dillon 
352e91e64c7SMatthew Dillon 	return delta;
35312e4aaffSMatthew Dillon }
35412e4aaffSMatthew Dillon 
3551a54183bSMatthew Dillon /*
3561a54183bSMatthew Dillon  * Clear dirty bits in the VM page but truncate the
3571a54183bSMatthew Dillon  * end to a DEV_BSIZE'd boundary.
3581a54183bSMatthew Dillon  *
3591a54183bSMatthew Dillon  * Used when reading data in, typically via getpages.
3601a54183bSMatthew Dillon  * The partial device block at the end of the truncation
3611a54183bSMatthew Dillon  * range should not lose its dirty bit.
362cb1cf930SMatthew Dillon  *
363cb1cf930SMatthew Dillon  * NOTE: This function does not clear the pmap modified bit.
3641a54183bSMatthew Dillon  */
3651a54183bSMatthew Dillon static __inline
3661a54183bSMatthew Dillon void
vm_page_clear_dirty_end_nonincl(vm_page_t m,int base,int size)3671a54183bSMatthew Dillon vm_page_clear_dirty_end_nonincl(vm_page_t m, int base, int size)
3681a54183bSMatthew Dillon {
3691a54183bSMatthew Dillon     size = (base + size) & ~DEV_BMASK;
3701a54183bSMatthew Dillon     if (base < size)
3711a54183bSMatthew Dillon 	vm_page_clear_dirty(m, base, size - base);
3721a54183bSMatthew Dillon }
3731a54183bSMatthew Dillon 
3741a54183bSMatthew Dillon /*
3751a54183bSMatthew Dillon  * Clear dirty bits in the VM page but truncate the
3761a54183bSMatthew Dillon  * beginning to a DEV_BSIZE'd boundary.
3771a54183bSMatthew Dillon  *
3781a54183bSMatthew Dillon  * Used when truncating a buffer.  The partial device
3791a54183bSMatthew Dillon  * block at the beginning of the truncation range
3801a54183bSMatthew Dillon  * should not lose its dirty bit.
381cb1cf930SMatthew Dillon  *
382cb1cf930SMatthew Dillon  * NOTE: This function does not clear the pmap modified bit.
3831a54183bSMatthew Dillon  */
3841a54183bSMatthew Dillon static __inline
3851a54183bSMatthew Dillon void
vm_page_clear_dirty_beg_nonincl(vm_page_t m,int base,int size)3861a54183bSMatthew Dillon vm_page_clear_dirty_beg_nonincl(vm_page_t m, int base, int size)
3871a54183bSMatthew Dillon {
3881a54183bSMatthew Dillon     size += base;
3891a54183bSMatthew Dillon     base = (base + DEV_BMASK) & ~DEV_BMASK;
3901a54183bSMatthew Dillon     if (base < size)
3911a54183bSMatthew Dillon 	vm_page_clear_dirty(m, base, size - base);
3921a54183bSMatthew Dillon }
3931a54183bSMatthew Dillon 
394b12defdcSMatthew Dillon static __inline
395b12defdcSMatthew Dillon void
vm_page_spin_lock(vm_page_t m)396b12defdcSMatthew Dillon vm_page_spin_lock(vm_page_t m)
397b12defdcSMatthew Dillon {
3986ba5daf8SMatthew Dillon     spin_lock(&m->spin);
399b12defdcSMatthew Dillon }
400b12defdcSMatthew Dillon 
401b12defdcSMatthew Dillon static __inline
402b12defdcSMatthew Dillon void
vm_page_spin_unlock(vm_page_t m)403b12defdcSMatthew Dillon vm_page_spin_unlock(vm_page_t m)
404b12defdcSMatthew Dillon {
4056ba5daf8SMatthew Dillon     spin_unlock(&m->spin);
406b12defdcSMatthew Dillon }
407b12defdcSMatthew Dillon 
408b12defdcSMatthew Dillon /*
409b12defdcSMatthew Dillon  * Wire a vm_page that is already wired.  Does not require a busied
410b12defdcSMatthew Dillon  * page.
411b12defdcSMatthew Dillon  */
412b12defdcSMatthew Dillon static __inline
413b12defdcSMatthew Dillon void
vm_page_wire_quick(vm_page_t m)414b12defdcSMatthew Dillon vm_page_wire_quick(vm_page_t m)
415b12defdcSMatthew Dillon {
416b12defdcSMatthew Dillon     if (atomic_fetchadd_int(&m->wire_count, 1) == 0)
417b12defdcSMatthew Dillon 	panic("vm_page_wire_quick: wire_count was 0");
418b12defdcSMatthew Dillon }
419b12defdcSMatthew Dillon 
420b12defdcSMatthew Dillon /*
421b12defdcSMatthew Dillon  * Unwire a vm_page quickly, does not require a busied page.
422b12defdcSMatthew Dillon  *
423b12defdcSMatthew Dillon  * This routine refuses to drop the wire_count to 0 and will return
424b12defdcSMatthew Dillon  * TRUE if it would have had to (instead of decrementing it to 0).
425b12defdcSMatthew Dillon  * The caller can then busy the page and deal with it.
426b12defdcSMatthew Dillon  */
427b12defdcSMatthew Dillon static __inline
428b12defdcSMatthew Dillon int
vm_page_unwire_quick(vm_page_t m)429b12defdcSMatthew Dillon vm_page_unwire_quick(vm_page_t m)
430b12defdcSMatthew Dillon {
431b12defdcSMatthew Dillon     KKASSERT(m->wire_count > 0);
432b12defdcSMatthew Dillon     for (;;) {
433b12defdcSMatthew Dillon 	u_int wire_count = m->wire_count;
434b12defdcSMatthew Dillon 
435b12defdcSMatthew Dillon 	cpu_ccfence();
436b12defdcSMatthew Dillon 	if (wire_count == 1)
437b12defdcSMatthew Dillon 		return TRUE;
438b12defdcSMatthew Dillon 	if (atomic_cmpset_int(&m->wire_count, wire_count, wire_count - 1))
439b12defdcSMatthew Dillon 		return FALSE;
440b12defdcSMatthew Dillon     }
441b12defdcSMatthew Dillon }
442b12defdcSMatthew Dillon 
443a86ce0cdSMatthew Dillon /*
444a86ce0cdSMatthew Dillon  *	Functions implemented as macros
445a86ce0cdSMatthew Dillon  */
446a86ce0cdSMatthew Dillon 
447a86ce0cdSMatthew Dillon static __inline void
vm_page_flag_set(vm_page_t m,unsigned int bits)448a86ce0cdSMatthew Dillon vm_page_flag_set(vm_page_t m, unsigned int bits)
449a86ce0cdSMatthew Dillon {
450a86ce0cdSMatthew Dillon 	atomic_set_int(&(m)->flags, bits);
451a86ce0cdSMatthew Dillon }
452a86ce0cdSMatthew Dillon 
453a86ce0cdSMatthew Dillon static __inline void
vm_page_flag_clear(vm_page_t m,unsigned int bits)454a86ce0cdSMatthew Dillon vm_page_flag_clear(vm_page_t m, unsigned int bits)
455a86ce0cdSMatthew Dillon {
456a86ce0cdSMatthew Dillon 	atomic_clear_int(&(m)->flags, bits);
457a86ce0cdSMatthew Dillon }
458a86ce0cdSMatthew Dillon 
459a86ce0cdSMatthew Dillon /*
460a86ce0cdSMatthew Dillon  * Wakeup anyone waiting for the page after potentially unbusying
461a86ce0cdSMatthew Dillon  * (hard or soft) or doing other work on a page that might make a
462bc0aa189SMatthew Dillon  * waiter ready.  The setting of PBUSY_WANTED is integrated into the
463a86ce0cdSMatthew Dillon  * related flags and it can't be set once the flags are already
464a86ce0cdSMatthew Dillon  * clear, so there should be no races here.
465a86ce0cdSMatthew Dillon  */
466a86ce0cdSMatthew Dillon static __inline void
vm_page_flash(vm_page_t m)467a86ce0cdSMatthew Dillon vm_page_flash(vm_page_t m)
468a86ce0cdSMatthew Dillon {
469bc0aa189SMatthew Dillon 	if (m->busy_count & PBUSY_WANTED) {
470bc0aa189SMatthew Dillon 		atomic_clear_int(&m->busy_count, PBUSY_WANTED);
471bc0aa189SMatthew Dillon 		wakeup(m);
472bc0aa189SMatthew Dillon 	}
473bc0aa189SMatthew Dillon }
474bc0aa189SMatthew Dillon 
475bc0aa189SMatthew Dillon /*
476bc0aa189SMatthew Dillon  * Adjust the soft-busy count on a page.  The drop code will issue an
477bc0aa189SMatthew Dillon  * integrated wakeup if busy_count becomes 0.
478bc0aa189SMatthew Dillon  */
479bc0aa189SMatthew Dillon static __inline void
vm_page_sbusy_hold(vm_page_t m)480bc0aa189SMatthew Dillon vm_page_sbusy_hold(vm_page_t m)
481bc0aa189SMatthew Dillon {
482bc0aa189SMatthew Dillon 	atomic_add_int(&m->busy_count, 1);
483bc0aa189SMatthew Dillon }
484bc0aa189SMatthew Dillon 
485bc0aa189SMatthew Dillon static __inline void
vm_page_sbusy_drop(vm_page_t m)486bc0aa189SMatthew Dillon vm_page_sbusy_drop(vm_page_t m)
487bc0aa189SMatthew Dillon {
488bc0aa189SMatthew Dillon 	uint32_t ocount;
489bc0aa189SMatthew Dillon 
490bc0aa189SMatthew Dillon 	ocount = atomic_fetchadd_int(&m->busy_count, -1);
491bc0aa189SMatthew Dillon 	if (ocount - 1 == PBUSY_WANTED) {
492bc0aa189SMatthew Dillon 		/* WANTED and no longer BUSY or SBUSY */
493bc0aa189SMatthew Dillon 		atomic_clear_int(&m->busy_count, PBUSY_WANTED);
494a86ce0cdSMatthew Dillon 		wakeup(m);
495a86ce0cdSMatthew Dillon 	}
496a86ce0cdSMatthew Dillon }
497a86ce0cdSMatthew Dillon 
498a86ce0cdSMatthew Dillon /*
499a86ce0cdSMatthew Dillon  * Reduce the protection of a page.  This routine never raises the
500a86ce0cdSMatthew Dillon  * protection and therefore can be safely called if the page is already
501a86ce0cdSMatthew Dillon  * at VM_PROT_NONE (it will be a NOP effectively ).
502a86ce0cdSMatthew Dillon  *
503a86ce0cdSMatthew Dillon  * VM_PROT_NONE will remove all user mappings of a page.  This is often
504a86ce0cdSMatthew Dillon  * necessary when a page changes state (for example, turns into a copy-on-write
505a86ce0cdSMatthew Dillon  * page or needs to be frozen for write I/O) in order to force a fault, or
506a86ce0cdSMatthew Dillon  * to force a page's dirty bits to be synchronized and avoid hardware
507a86ce0cdSMatthew Dillon  * (modified/accessed) bit update races with pmap changes.
508a86ce0cdSMatthew Dillon  *
509a86ce0cdSMatthew Dillon  * Since 'prot' is usually a constant, this inline usually winds up optimizing
510a86ce0cdSMatthew Dillon  * out the primary conditional.
511a86ce0cdSMatthew Dillon  *
512530e94fcSMatthew Dillon  * Must be called with (m) hard-busied.
513530e94fcSMatthew Dillon  *
514a86ce0cdSMatthew Dillon  * WARNING: VM_PROT_NONE can block, but will loop until all mappings have
515530e94fcSMatthew Dillon  *	    been cleared.  Callers should be aware that other page related
516530e94fcSMatthew Dillon  *	    elements might have changed, however.
517a86ce0cdSMatthew Dillon  */
518a86ce0cdSMatthew Dillon static __inline void
vm_page_protect(vm_page_t m,int prot)519a86ce0cdSMatthew Dillon vm_page_protect(vm_page_t m, int prot)
520a86ce0cdSMatthew Dillon {
521bc0aa189SMatthew Dillon 	KKASSERT(m->busy_count & PBUSY_LOCKED);
522a86ce0cdSMatthew Dillon 	if (prot == VM_PROT_NONE) {
523c2830aa6SMatthew Dillon 		if (pmap_mapped_sync(m) & (PG_MAPPED | PG_WRITEABLE)) {
524a86ce0cdSMatthew Dillon 			pmap_page_protect(m, VM_PROT_NONE);
525a86ce0cdSMatthew Dillon 			/* PG_WRITEABLE & PG_MAPPED cleared by call */
526a86ce0cdSMatthew Dillon 		}
527e3c330f0SMatthew Dillon 	} else if ((prot == VM_PROT_READ) &&
528e3c330f0SMatthew Dillon 		   (m->flags & PG_WRITEABLE) &&
529e3c330f0SMatthew Dillon 		   (pmap_mapped_sync(m) & PG_WRITEABLE)) {
530a86ce0cdSMatthew Dillon 		pmap_page_protect(m, VM_PROT_READ);
531a86ce0cdSMatthew Dillon 		/* PG_WRITEABLE cleared by call */
532a86ce0cdSMatthew Dillon 	}
533a86ce0cdSMatthew Dillon }
534a86ce0cdSMatthew Dillon 
535a86ce0cdSMatthew Dillon /*
536a86ce0cdSMatthew Dillon  * Zero-fill the specified page.  The entire contents of the page will be
537a86ce0cdSMatthew Dillon  * zero'd out.
538a86ce0cdSMatthew Dillon  */
539a86ce0cdSMatthew Dillon static __inline boolean_t
vm_page_zero_fill(vm_page_t m)540a86ce0cdSMatthew Dillon vm_page_zero_fill(vm_page_t m)
541a86ce0cdSMatthew Dillon {
542a86ce0cdSMatthew Dillon 	pmap_zero_page(VM_PAGE_TO_PHYS(m));
543a86ce0cdSMatthew Dillon 	return (TRUE);
544a86ce0cdSMatthew Dillon }
545a86ce0cdSMatthew Dillon 
546a86ce0cdSMatthew Dillon /*
547a86ce0cdSMatthew Dillon  * Copy the contents of src_m to dest_m.  The pages must be stable but spl
548a86ce0cdSMatthew Dillon  * and other protections depend on context.
549a86ce0cdSMatthew Dillon  */
550a86ce0cdSMatthew Dillon static __inline void
vm_page_copy(vm_page_t src_m,vm_page_t dest_m)551a86ce0cdSMatthew Dillon vm_page_copy(vm_page_t src_m, vm_page_t dest_m)
552a86ce0cdSMatthew Dillon {
553a86ce0cdSMatthew Dillon 	pmap_copy_page(VM_PAGE_TO_PHYS(src_m), VM_PAGE_TO_PHYS(dest_m));
554a86ce0cdSMatthew Dillon 	dest_m->valid = VM_PAGE_BITS_ALL;
555a86ce0cdSMatthew Dillon 	dest_m->dirty = VM_PAGE_BITS_ALL;
556a86ce0cdSMatthew Dillon }
557a86ce0cdSMatthew Dillon 
558a86ce0cdSMatthew Dillon /*
559a86ce0cdSMatthew Dillon  * Free a page.  The page must be marked BUSY.
560a86ce0cdSMatthew Dillon  */
561a86ce0cdSMatthew Dillon static __inline void
vm_page_free(vm_page_t m)562a86ce0cdSMatthew Dillon vm_page_free(vm_page_t m)
563a86ce0cdSMatthew Dillon {
564a86ce0cdSMatthew Dillon 	vm_page_free_toq(m);
565a86ce0cdSMatthew Dillon }
566a86ce0cdSMatthew Dillon 
567a86ce0cdSMatthew Dillon /*
568a86ce0cdSMatthew Dillon  * Free a page to the zerod-pages queue.  The caller must ensure that the
569a86ce0cdSMatthew Dillon  * page has been zerod.
570a86ce0cdSMatthew Dillon  */
571a86ce0cdSMatthew Dillon static __inline void
vm_page_free_zero(vm_page_t m)572a86ce0cdSMatthew Dillon vm_page_free_zero(vm_page_t m)
573a86ce0cdSMatthew Dillon {
574a86ce0cdSMatthew Dillon #ifdef PMAP_DEBUG
575a86ce0cdSMatthew Dillon #ifdef PHYS_TO_DMAP
576a86ce0cdSMatthew Dillon 	char *p = (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
577a86ce0cdSMatthew Dillon 	int i;
578a86ce0cdSMatthew Dillon 
579a86ce0cdSMatthew Dillon 	for (i = 0; i < PAGE_SIZE; i++) {
580a86ce0cdSMatthew Dillon 		if (p[i] != 0) {
581a86ce0cdSMatthew Dillon 			panic("non-zero page in vm_page_free_zero()");
582a86ce0cdSMatthew Dillon 		}
583a86ce0cdSMatthew Dillon 	}
584a86ce0cdSMatthew Dillon #endif
585a86ce0cdSMatthew Dillon #endif
586a86ce0cdSMatthew Dillon 	vm_page_free_toq(m);
587a86ce0cdSMatthew Dillon }
588a86ce0cdSMatthew Dillon 
589a86ce0cdSMatthew Dillon /*
590a86ce0cdSMatthew Dillon  * Set page to not be dirty.  Note: does not clear pmap modify bits .
591a86ce0cdSMatthew Dillon  */
592a86ce0cdSMatthew Dillon static __inline void
vm_page_undirty(vm_page_t m)593a86ce0cdSMatthew Dillon vm_page_undirty(vm_page_t m)
594a86ce0cdSMatthew Dillon {
595a86ce0cdSMatthew Dillon 	m->dirty = 0;
596a86ce0cdSMatthew Dillon }
597a86ce0cdSMatthew Dillon 
59812e4aaffSMatthew Dillon #endif	/* _KERNEL */
5991bd40720SMatthew Dillon #endif	/* _VM_VM_PAGE2_H_ */
60012e4aaffSMatthew Dillon 
601