The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/vm/vm_zeroidle.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: releng/5.1/sys/vm/vm_zeroidle.c 113070 2003-04-04 12:08:42Z des $
   11  */
   12 
   13 #include <sys/param.h>
   14 #include <sys/systm.h>
   15 #include <sys/kernel.h>
   16 #include <sys/proc.h>
   17 #include <sys/resourcevar.h>
   18 #include <sys/vmmeter.h>
   19 #include <sys/lock.h>
   20 #include <sys/mutex.h>
   21 #include <sys/sched.h>
   22 #include <sys/sysctl.h>
   23 #include <sys/kthread.h>
   24 
   25 #include <vm/vm.h>
   26 #include <vm/vm_page.h>
   27 
   28 SYSCTL_DECL(_vm_stats_misc);
   29 
   30 static int cnt_prezero;
   31 SYSCTL_INT(_vm_stats_misc, OID_AUTO,
   32         cnt_prezero, CTLFLAG_RD, &cnt_prezero, 0, "");
   33 
   34 static int idlezero_enable = 1;
   35 SYSCTL_INT(_vm, OID_AUTO, idlezero_enable, CTLFLAG_RW, &idlezero_enable, 0, "");
   36 TUNABLE_INT("vm.idlezero_enable", &idlezero_enable);
   37 
   38 static int idlezero_maxrun = 16;
   39 SYSCTL_INT(_vm, OID_AUTO, idlezero_maxrun, CTLFLAG_RW, &idlezero_maxrun, 0, "");
   40 TUNABLE_INT("vm.idlezero_maxrun", &idlezero_maxrun);
   41 
   42 /*
   43  * Implement the pre-zeroed page mechanism.
   44  */
   45 
   46 #define ZIDLE_LO(v)     ((v) * 2 / 3)
   47 #define ZIDLE_HI(v)     ((v) * 4 / 5)
   48 
   49 static int zero_state;
   50 
   51 static int
   52 vm_page_zero_check(void)
   53 {
   54 
   55         if (!idlezero_enable)
   56                 return 0;
   57         /*
   58          * Attempt to maintain approximately 1/2 of our free pages in a
   59          * PG_ZERO'd state.   Add some hysteresis to (attempt to) avoid
   60          * generally zeroing a page when the system is near steady-state.
   61          * Otherwise we might get 'flutter' during disk I/O / IPC or 
   62          * fast sleeps.  We also do not want to be continuously zeroing
   63          * pages because doing so may flush our L1 and L2 caches too much.
   64          */
   65         if (zero_state && vm_page_zero_count >= ZIDLE_LO(cnt.v_free_count))
   66                 return 0;
   67         if (vm_page_zero_count >= ZIDLE_HI(cnt.v_free_count))
   68                 return 0;
   69         return 1;
   70 }
   71 
   72 static int
   73 vm_page_zero_idle(void)
   74 {
   75         static int free_rover;
   76         vm_page_t m;
   77 
   78         mtx_lock_spin(&vm_page_queue_free_mtx);
   79         zero_state = 0;
   80         m = vm_pageq_find(PQ_FREE, free_rover, FALSE);
   81         if (m != NULL && (m->flags & PG_ZERO) == 0) {
   82                 vm_pageq_remove_nowakeup(m);
   83                 mtx_unlock_spin(&vm_page_queue_free_mtx);
   84                 pmap_zero_page_idle(m);
   85                 mtx_lock_spin(&vm_page_queue_free_mtx);
   86                 m->flags |= PG_ZERO;
   87                 vm_pageq_enqueue(PQ_FREE + m->pc, m);
   88                 ++vm_page_zero_count;
   89                 ++cnt_prezero;
   90                 if (vm_page_zero_count >= ZIDLE_HI(cnt.v_free_count))
   91                         zero_state = 1;
   92         }
   93         free_rover = (free_rover + PQ_PRIME2) & PQ_L2_MASK;
   94         mtx_unlock_spin(&vm_page_queue_free_mtx);
   95         return 1;
   96 }
   97 
   98 
   99 /* Called by vm_page_free to hint that a new page is available */
  100 void
  101 vm_page_zero_idle_wakeup(void)
  102 {
  103 
  104         if (idlezero_enable && vm_page_zero_check())
  105                 wakeup(&zero_state);
  106 }
  107 
  108 static void
  109 vm_pagezero(void)
  110 {
  111         struct thread *td;
  112         struct proc *p;
  113         struct rtprio rtp;
  114         int pages = 0;
  115         int pri;
  116 
  117         td = curthread;
  118         p = td->td_proc;
  119         rtp.prio = RTP_PRIO_MAX;
  120         rtp.type = RTP_PRIO_IDLE;
  121         mtx_lock_spin(&sched_lock);
  122         rtp_to_pri(&rtp, td->td_ksegrp);
  123         pri = td->td_priority;
  124         mtx_unlock_spin(&sched_lock);
  125         PROC_LOCK(p);
  126         p->p_flag |= P_NOLOAD;
  127         PROC_UNLOCK(p);
  128 
  129         for (;;) {
  130                 if (vm_page_zero_check()) {
  131                         pages += vm_page_zero_idle();
  132                         if (pages > idlezero_maxrun || sched_runnable()) {
  133                                 mtx_lock_spin(&sched_lock);
  134                                 td->td_proc->p_stats->p_ru.ru_nvcsw++;
  135                                 mi_switch();
  136                                 mtx_unlock_spin(&sched_lock);
  137                                 pages = 0;
  138                         }
  139                 } else {
  140                         tsleep(&zero_state, pri, "pgzero", hz * 300);
  141                         pages = 0;
  142                 }
  143         }
  144 }
  145 
  146 static struct proc *pagezero_proc;
  147 static struct kproc_desc pagezero_kp = {
  148          "pagezero",
  149          vm_pagezero,
  150          &pagezero_proc
  151 };
  152 SYSINIT(pagezero, SI_SUB_KTHREAD_VM, SI_ORDER_ANY, kproc_start, &pagezero_kp)

Cache object: 65f5783c5340ba2cfda487807236de2b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.