vm_zeroidle.c revision 79265
179265Sdillon/*-
279265Sdillon * Copyright (c) 1994 John Dyson
379265Sdillon * Copyright (c) 2001 Matt Dillon
479265Sdillon *
579265Sdillon * All rights reserved.  Terms for use and redistribution
679265Sdillon * are covered by the BSD Copyright as found in /usr/src/COPYRIGHT.
779265Sdillon *
879265Sdillon *	from: @(#)vm_machdep.c	7.3 (Berkeley) 5/13/91
979265Sdillon *	Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
1079265Sdillon * $FreeBSD: head/sys/vm/vm_zeroidle.c 79265 2001-07-05 01:32:42Z dillon $
1179265Sdillon */
1279265Sdillon
1379265Sdillon#include "opt_npx.h"
1479265Sdillon#ifdef PC98
1579265Sdillon#include "opt_pc98.h"
1679265Sdillon#endif
1779265Sdillon#include "opt_reset.h"
1879265Sdillon#include "opt_isa.h"
1979265Sdillon
2079265Sdillon#include <sys/param.h>
2179265Sdillon#include <sys/systm.h>
2279265Sdillon#include <sys/malloc.h>
2379265Sdillon#include <sys/proc.h>
2479265Sdillon#include <sys/bio.h>
2579265Sdillon#include <sys/buf.h>
2679265Sdillon#include <sys/vnode.h>
2779265Sdillon#include <sys/vmmeter.h>
2879265Sdillon#include <sys/kernel.h>
2979265Sdillon#include <sys/ktr.h>
3079265Sdillon#include <sys/mutex.h>
3179265Sdillon#include <sys/smp.h>
3279265Sdillon#include <sys/sysctl.h>
3379265Sdillon#include <sys/unistd.h>
3479265Sdillon
3579265Sdillon#include <machine/cpu.h>
3679265Sdillon#include <machine/md_var.h>
3779265Sdillon#include <machine/pcb.h>
3879265Sdillon#include <machine/pcb_ext.h>
3979265Sdillon#include <machine/vm86.h>
4079265Sdillon
4179265Sdillon#include <vm/vm.h>
4279265Sdillon#include <vm/vm_param.h>
4379265Sdillon#include <sys/lock.h>
4479265Sdillon#include <vm/vm_kern.h>
4579265Sdillon#include <vm/vm_page.h>
4679265Sdillon#include <vm/vm_map.h>
4779265Sdillon#include <vm/vm_extern.h>
4879265Sdillon
4979265Sdillon#include <sys/user.h>
5079265Sdillon
5179265Sdillon#ifdef PC98
5279265Sdillon#include <pc98/pc98/pc98.h>
5379265Sdillon#else
5479265Sdillon#include <i386/isa/isa.h>
5579265Sdillon#endif
5679265Sdillon
5779265SdillonSYSCTL_DECL(_vm_stats_misc);
5879265Sdillon
5979265Sdillonstatic int cnt_prezero;
6079265Sdillon
6179265SdillonSYSCTL_INT(_vm_stats_misc, OID_AUTO,
6279265Sdillon	cnt_prezero, CTLFLAG_RD, &cnt_prezero, 0, "");
6379265Sdillon
6479265Sdillon/*
6579265Sdillon * Implement the pre-zeroed page mechanism.
6679265Sdillon * This routine is called from the idle loop.
6779265Sdillon */
6879265Sdillon
6979265Sdillon#define ZIDLE_LO(v)	((v) * 2 / 3)
7079265Sdillon#define ZIDLE_HI(v)	((v) * 4 / 5)
7179265Sdillon
7279265Sdillonint
7379265Sdillonvm_page_zero_idle(void)
7479265Sdillon{
7579265Sdillon	static int free_rover;
7679265Sdillon	static int zero_state;
7779265Sdillon	vm_page_t m;
7879265Sdillon
7979265Sdillon	/*
8079265Sdillon	 * Attempt to maintain approximately 1/2 of our free pages in a
8179265Sdillon	 * PG_ZERO'd state.   Add some hysteresis to (attempt to) avoid
8279265Sdillon	 * generally zeroing a page when the system is near steady-state.
8379265Sdillon	 * Otherwise we might get 'flutter' during disk I/O / IPC or
8479265Sdillon	 * fast sleeps.  We also do not want to be continuously zeroing
8579265Sdillon	 * pages because doing so may flush our L1 and L2 caches too much.
8679265Sdillon	 */
8779265Sdillon
8879265Sdillon	if (zero_state && vm_page_zero_count >= ZIDLE_LO(cnt.v_free_count))
8979265Sdillon		return(0);
9079265Sdillon	if (vm_page_zero_count >= ZIDLE_HI(cnt.v_free_count))
9179265Sdillon		return(0);
9279265Sdillon
9379265Sdillon	if (mtx_trylock(&Giant)) {
9479265Sdillon		zero_state = 0;
9579265Sdillon		m = vm_pageq_find(PQ_FREE, free_rover, FALSE);
9679265Sdillon		if (m != NULL && (m->flags & PG_ZERO) == 0) {
9779265Sdillon			vm_page_queues[m->queue].lcnt--;
9879265Sdillon			TAILQ_REMOVE(&vm_page_queues[m->queue].pl, m, pageq);
9979265Sdillon			m->queue = PQ_NONE;
10079265Sdillon			pmap_zero_page(VM_PAGE_TO_PHYS(m));
10179265Sdillon			vm_page_flag_set(m, PG_ZERO);
10279265Sdillon			m->queue = PQ_FREE + m->pc;
10379265Sdillon			vm_page_queues[m->queue].lcnt++;
10479265Sdillon			TAILQ_INSERT_TAIL(&vm_page_queues[m->queue].pl, m,
10579265Sdillon			    pageq);
10679265Sdillon			++vm_page_zero_count;
10779265Sdillon			++cnt_prezero;
10879265Sdillon			if (vm_page_zero_count >= ZIDLE_HI(cnt.v_free_count))
10979265Sdillon				zero_state = 1;
11079265Sdillon		}
11179265Sdillon		free_rover = (free_rover + PQ_PRIME2) & PQ_L2_MASK;
11279265Sdillon		mtx_unlock(&Giant);
11379265Sdillon		return (1);
11479265Sdillon	}
11579265Sdillon	return(0);
11679265Sdillon}
11779265Sdillon
118