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_pagequeue.h

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  * SPDX-License-Identifier: (BSD-3-Clause AND MIT-CMU)
    3  *
    4  * Copyright (c) 1991, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * The Mach Operating System project at Carnegie-Mellon University.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  *      from: @(#)vm_page.h     8.2 (Berkeley) 12/13/93
   35  *
   36  *
   37  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
   38  * All rights reserved.
   39  *
   40  * Authors: Avadis Tevanian, Jr., Michael Wayne Young
   41  *
   42  * Permission to use, copy, modify and distribute this software and
   43  * its documentation is hereby granted, provided that both the copyright
   44  * notice and this permission notice appear in all copies of the
   45  * software, derivative works or modified versions, and any portions
   46  * thereof, and that both notices appear in supporting documentation.
   47  *
   48  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   49  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
   50  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   51  *
   52  * Carnegie Mellon requests users of this software to return to
   53  *
   54  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   55  *  School of Computer Science
   56  *  Carnegie Mellon University
   57  *  Pittsburgh PA 15213-3890
   58  *
   59  * any improvements or extensions that they make and grant Carnegie the
   60  * rights to redistribute these changes.
   61  *
   62  * $FreeBSD: releng/12.0/sys/vm/vm_pagequeue.h 339043 2018-10-01 14:14:21Z gallatin $
   63  */
   64 
   65 #ifndef _VM_PAGEQUEUE_
   66 #define _VM_PAGEQUEUE_
   67 
   68 #ifdef _KERNEL
   69 struct vm_pagequeue {
   70         struct mtx      pq_mutex;
   71         struct pglist   pq_pl;
   72         int             pq_cnt;
   73         const char      * const pq_name;
   74         uint64_t        pq_pdpages;
   75 } __aligned(CACHE_LINE_SIZE);
   76 
   77 #ifndef VM_BATCHQUEUE_SIZE
   78 #define VM_BATCHQUEUE_SIZE      7
   79 #endif
   80 
   81 struct vm_batchqueue {
   82         vm_page_t       bq_pa[VM_BATCHQUEUE_SIZE];
   83         int             bq_cnt;
   84 } __aligned(CACHE_LINE_SIZE);
   85 
   86 #include <vm/uma.h>
   87 #include <sys/pidctrl.h>
   88 struct sysctl_oid;
   89 
   90 /*
   91  * One vm_domain per-numa domain.  Contains pagequeues, free page structures,
   92  * and accounting.
   93  *
   94  * Lock Key:
   95  * f    vmd_free_mtx
   96  * p    vmd_pageout_mtx
   97  * d    vm_domainset_lock
   98  * a    atomic
   99  * c    const after boot
  100  * q    page queue lock
  101 */
  102 struct vm_domain {
  103         struct vm_pagequeue vmd_pagequeues[PQ_COUNT];
  104         struct mtx_padalign vmd_free_mtx;
  105         struct mtx_padalign vmd_pageout_mtx;
  106         uma_zone_t vmd_pgcache;         /* (c) page free cache. */
  107         struct vmem *vmd_kernel_arena;  /* (c) per-domain kva R/W arena. */
  108         struct vmem *vmd_kernel_rwx_arena; /* (c) per-domain kva R/W/X arena. */
  109         u_int vmd_domain;               /* (c) Domain number. */
  110         u_int vmd_page_count;           /* (c) Total page count. */
  111         long vmd_segs;                  /* (c) bitmask of the segments */
  112         u_int __aligned(CACHE_LINE_SIZE) vmd_free_count; /* (a,f) free page count */
  113         u_int vmd_pageout_deficit;      /* (a) Estimated number of pages deficit */
  114         uint8_t vmd_pad[CACHE_LINE_SIZE - (sizeof(u_int) * 2)];
  115 
  116         /* Paging control variables, used within single threaded page daemon. */
  117         struct pidctrl vmd_pid;         /* Pageout controller. */
  118         boolean_t vmd_oom;
  119         int vmd_oom_seq;
  120         int vmd_last_active_scan;
  121         struct vm_page vmd_markers[PQ_COUNT]; /* (q) markers for queue scans */
  122         struct vm_page vmd_inacthead; /* marker for LRU-defeating insertions */
  123         struct vm_page vmd_clock[2]; /* markers for active queue scan */
  124 
  125         int vmd_pageout_wanted;         /* (a, p) pageout daemon wait channel */
  126         int vmd_pageout_pages_needed;   /* (d) page daemon waiting for pages? */
  127         bool vmd_minset;                /* (d) Are we in vm_min_domains? */
  128         bool vmd_severeset;             /* (d) Are we in vm_severe_domains? */
  129         enum {
  130                 VM_LAUNDRY_IDLE = 0,
  131                 VM_LAUNDRY_BACKGROUND,
  132                 VM_LAUNDRY_SHORTFALL
  133         } vmd_laundry_request;
  134 
  135         /* Paging thresholds and targets. */
  136         u_int vmd_clean_pages_freed;    /* (q) accumulator for laundry thread */
  137         u_int vmd_background_launder_target; /* (c) */
  138         u_int vmd_free_reserved;        /* (c) pages reserved for deadlock */
  139         u_int vmd_free_target;          /* (c) pages desired free */
  140         u_int vmd_free_min;             /* (c) pages desired free */
  141         u_int vmd_inactive_target;      /* (c) pages desired inactive */
  142         u_int vmd_pageout_free_min;     /* (c) min pages reserved for kernel */
  143         u_int vmd_pageout_wakeup_thresh;/* (c) min pages to wake pagedaemon */
  144         u_int vmd_interrupt_free_min;   /* (c) reserved pages for int code */
  145         u_int vmd_free_severe;          /* (c) severe page depletion point */
  146 
  147         /* Name for sysctl etc. */
  148         struct sysctl_oid *vmd_oid;
  149         char vmd_name[sizeof(__XSTRING(MAXMEMDOM))];
  150 } __aligned(CACHE_LINE_SIZE);
  151 
  152 extern struct vm_domain vm_dom[MAXMEMDOM];
  153 
  154 #define VM_DOMAIN(n)            (&vm_dom[(n)])
  155 #define VM_DOMAIN_EMPTY(n)      (vm_dom[(n)].vmd_page_count == 0)
  156 
  157 #define vm_pagequeue_assert_locked(pq)  mtx_assert(&(pq)->pq_mutex, MA_OWNED)
  158 #define vm_pagequeue_lock(pq)           mtx_lock(&(pq)->pq_mutex)
  159 #define vm_pagequeue_lockptr(pq)        (&(pq)->pq_mutex)
  160 #define vm_pagequeue_trylock(pq)        mtx_trylock(&(pq)->pq_mutex)
  161 #define vm_pagequeue_unlock(pq)         mtx_unlock(&(pq)->pq_mutex)
  162 
  163 #define vm_domain_free_assert_locked(n)                                 \
  164             mtx_assert(vm_domain_free_lockptr((n)), MA_OWNED)
  165 #define vm_domain_free_assert_unlocked(n)                               \
  166             mtx_assert(vm_domain_free_lockptr((n)), MA_NOTOWNED)
  167 #define vm_domain_free_lock(d)                                          \
  168             mtx_lock(vm_domain_free_lockptr((d)))
  169 #define vm_domain_free_lockptr(d)                                       \
  170             (&(d)->vmd_free_mtx)
  171 #define vm_domain_free_trylock(d)                                       \
  172             mtx_trylock(vm_domain_free_lockptr((d)))
  173 #define vm_domain_free_unlock(d)                                        \
  174             mtx_unlock(vm_domain_free_lockptr((d)))
  175 
  176 #define vm_domain_pageout_lockptr(d)                                    \
  177             (&(d)->vmd_pageout_mtx)
  178 #define vm_domain_pageout_assert_locked(n)                              \
  179             mtx_assert(vm_domain_pageout_lockptr((n)), MA_OWNED)
  180 #define vm_domain_pageout_assert_unlocked(n)                            \
  181             mtx_assert(vm_domain_pageout_lockptr((n)), MA_NOTOWNED)
  182 #define vm_domain_pageout_lock(d)                                       \
  183             mtx_lock(vm_domain_pageout_lockptr((d)))
  184 #define vm_domain_pageout_unlock(d)                                     \
  185             mtx_unlock(vm_domain_pageout_lockptr((d)))
  186 
  187 static __inline void
  188 vm_pagequeue_cnt_add(struct vm_pagequeue *pq, int addend)
  189 {
  190 
  191         vm_pagequeue_assert_locked(pq);
  192         pq->pq_cnt += addend;
  193 }
  194 #define vm_pagequeue_cnt_inc(pq)        vm_pagequeue_cnt_add((pq), 1)
  195 #define vm_pagequeue_cnt_dec(pq)        vm_pagequeue_cnt_add((pq), -1)
  196 
  197 static inline void
  198 vm_batchqueue_init(struct vm_batchqueue *bq)
  199 {
  200 
  201         bq->bq_cnt = 0;
  202 }
  203 
  204 static inline bool
  205 vm_batchqueue_insert(struct vm_batchqueue *bq, vm_page_t m)
  206 {
  207 
  208         if (bq->bq_cnt < nitems(bq->bq_pa)) {
  209                 bq->bq_pa[bq->bq_cnt++] = m;
  210                 return (true);
  211         }
  212         return (false);
  213 }
  214 
  215 static inline vm_page_t
  216 vm_batchqueue_pop(struct vm_batchqueue *bq)
  217 {
  218 
  219         if (bq->bq_cnt == 0)
  220                 return (NULL);
  221         return (bq->bq_pa[--bq->bq_cnt]);
  222 }
  223 
  224 void vm_domain_set(struct vm_domain *vmd);
  225 void vm_domain_clear(struct vm_domain *vmd);
  226 int vm_domain_allocate(struct vm_domain *vmd, int req, int npages);
  227 
  228 /*
  229  *      vm_pagequeue_domain:
  230  *
  231  *      Return the memory domain the page belongs to.
  232  */
  233 static inline struct vm_domain *
  234 vm_pagequeue_domain(vm_page_t m)
  235 {
  236 
  237         return (VM_DOMAIN(vm_phys_domain(m)));
  238 }
  239 
  240 /*
  241  * Return the number of pages we need to free-up or cache
  242  * A positive number indicates that we do not have enough free pages.
  243  */
  244 static inline int
  245 vm_paging_target(struct vm_domain *vmd)
  246 {
  247 
  248         return (vmd->vmd_free_target - vmd->vmd_free_count);
  249 }
  250 
  251 /*
  252  * Returns TRUE if the pagedaemon needs to be woken up.
  253  */
  254 static inline int
  255 vm_paging_needed(struct vm_domain *vmd, u_int free_count)
  256 {
  257 
  258         return (free_count < vmd->vmd_pageout_wakeup_thresh);
  259 }
  260 
  261 /*
  262  * Returns TRUE if the domain is below the min paging target.
  263  */
  264 static inline int
  265 vm_paging_min(struct vm_domain *vmd)
  266 {
  267 
  268         return (vmd->vmd_free_min > vmd->vmd_free_count);
  269 }
  270 
  271 /*
  272  * Returns TRUE if the domain is below the severe paging target.
  273  */
  274 static inline int
  275 vm_paging_severe(struct vm_domain *vmd)
  276 {
  277 
  278         return (vmd->vmd_free_severe > vmd->vmd_free_count);
  279 }
  280 
  281 /*
  282  * Return the number of pages we need to launder.
  283  * A positive number indicates that we have a shortfall of clean pages.
  284  */
  285 static inline int
  286 vm_laundry_target(struct vm_domain *vmd)
  287 {
  288 
  289         return (vm_paging_target(vmd));
  290 }
  291 
  292 void pagedaemon_wakeup(int domain);
  293 
  294 static inline void
  295 vm_domain_freecnt_inc(struct vm_domain *vmd, int adj)
  296 {
  297         u_int old, new;
  298 
  299         old = atomic_fetchadd_int(&vmd->vmd_free_count, adj);
  300         new = old + adj;
  301         /*
  302          * Only update bitsets on transitions.  Notice we short-circuit the
  303          * rest of the checks if we're above min already.
  304          */
  305         if (old < vmd->vmd_free_min && (new >= vmd->vmd_free_min ||
  306             (old < vmd->vmd_free_severe && new >= vmd->vmd_free_severe) ||
  307             (old < vmd->vmd_pageout_free_min &&
  308             new >= vmd->vmd_pageout_free_min)))
  309                 vm_domain_clear(vmd);
  310 }
  311 
  312 #endif  /* _KERNEL */
  313 #endif                          /* !_VM_PAGEQUEUE_ */

Cache object: e52047c40a6da3d8b63368598c46f794


[ 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.