Annotation of Gnu-Mach/vm/vm_page.h, revision 1.1.1.7

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1993-1988 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     File:   vm/vm_page.h
                     28:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
                     29:  *     Date:   1985
                     30:  *
                     31:  *     Resident memory system definitions.
                     32:  */
                     33: 
                     34: #ifndef        _VM_VM_PAGE_H_
                     35: #define _VM_VM_PAGE_H_
                     36: 
                     37: #include <mach/boolean.h>
                     38: #include <mach/vm_prot.h>
1.1.1.6   root       39: #include <machine/vm_param.h>
1.1       root       40: #include <vm/vm_object.h>
1.1.1.3   root       41: #include <vm/vm_types.h>
1.1       root       42: #include <kern/queue.h>
1.1.1.7 ! root       43: #include <kern/list.h>
1.1       root       44: #include <kern/lock.h>
1.1.1.6   root       45: #include <kern/log2.h>
1.1       root       46: 
1.1.1.5   root       47: #include <kern/macros.h>
1.1       root       48: #include <kern/sched_prim.h>   /* definitions of wait/wakeup */
                     49: 
                     50: #if    MACH_VM_DEBUG
                     51: #include <mach_debug/hash_info.h>
                     52: #endif
                     53: 
                     54: /*
                     55:  *     Management of resident (logical) pages.
                     56:  *
                     57:  *     A small structure is kept for each resident
                     58:  *     page, indexed by page number.  Each structure
                     59:  *     is an element of several lists:
                     60:  *
                     61:  *             A hash table bucket used to quickly
                     62:  *             perform object/offset lookups
                     63:  *
                     64:  *             A list of all pages for a given object,
                     65:  *             so they can be quickly deactivated at
                     66:  *             time of deallocation.
                     67:  *
                     68:  *             An ordered list of pages due for pageout.
                     69:  *
                     70:  *     In addition, the structure contains the object
                     71:  *     and offset to which this page belongs (for pageout),
                     72:  *     and sundry status bits.
                     73:  *
                     74:  *     Fields in this structure are locked either by the lock on the
                     75:  *     object that the page belongs to (O) or by the lock on the page
                     76:  *     queues (P).  [Some fields require that both locks be held to
                     77:  *     change that field; holding either lock is sufficient to read.]
                     78:  */
                     79: 
                     80: struct vm_page {
1.1.1.7 ! root       81:        struct list node;               /* page queues or free list (P) */
1.1.1.6   root       82:        unsigned short type;
                     83:        unsigned short seg_index;
                     84:        unsigned short order;
                     85:        void *priv;
                     86: 
                     87:        /*
                     88:         * This member is used throughout the code and may only change for
                     89:         * fictitious pages.
                     90:         */
                     91:        phys_addr_t phys_addr;
                     92: 
1.1.1.7 ! root       93:        queue_chain_t   listq;          /* all pages in same object (O) */
        !            94:        struct vm_page  *next;          /* VP bucket link (O) */
        !            95: 
1.1.1.6   root       96:        /* We use an empty struct as the delimiter.  */
                     97:        struct {} vm_page_header;
                     98: #define VM_PAGE_HEADER_SIZE    offsetof(struct vm_page, vm_page_header)
                     99: 
1.1       root      100:        vm_object_t     object;         /* which object am I in (O,P) */
                    101:        vm_offset_t     offset;         /* offset into that object (O,P) */
                    102: 
1.1.1.4   root      103:        unsigned int    wire_count:15,  /* how many wired down maps use me?
1.1       root      104:                                           (O&P) */
                    105:        /* boolean_t */ inactive:1,     /* page is in inactive list (P) */
                    106:                        active:1,       /* page is in active list (P) */
                    107:                        laundry:1,      /* page is being cleaned now (P)*/
1.1.1.7 ! root      108:                        external_laundry:1,     /* same as laundry for external pagers (P)*/
1.1       root      109:                        free:1,         /* page is on free list (P) */
                    110:                        reference:1,    /* page has been used (P) */
1.1.1.7 ! root      111:                        external:1,     /* page in external object (P) */
1.1.1.4   root      112:                        busy:1,         /* page is in transit (O) */
1.1       root      113:                        wanted:1,       /* someone is waiting for page (O) */
                    114:                        tabled:1,       /* page is in VP table (O) */
                    115:                        fictitious:1,   /* Physical page doesn't exist (O) */
                    116:                        private:1,      /* Page should not be returned to
                    117:                                         *  the free list (O) */
                    118:                        absent:1,       /* Data has been requested, but is
                    119:                                         *  not yet available (O) */
                    120:                        error:1,        /* Data manager was unable to provide
                    121:                                         *  data due to error (O) */
                    122:                        dirty:1,        /* Page must be cleaned (O) */
                    123:                        precious:1,     /* Page is precious; data must be
                    124:                                         *  returned even if clean (O) */
1.1.1.4   root      125:                        overwriting:1;  /* Request to unlock has been made
1.1       root      126:                                         * without having data. (O)
                    127:                                         * [See vm_object_overwrite] */
                    128: 
                    129:        vm_prot_t       page_lock;      /* Uses prohibited by data manager (O) */
                    130:        vm_prot_t       unlock_request; /* Outstanding unlock request (O) */
                    131: };
                    132: 
                    133: /*
                    134:  *     For debugging, this macro can be defined to perform
                    135:  *     some useful check on a page structure.
                    136:  */
                    137: 
1.1.1.7 ! root      138: #define VM_PAGE_CHECK(mem) vm_page_check(mem)
        !           139: 
        !           140: void vm_page_check(const struct vm_page *page);
1.1       root      141: 
                    142: /*
                    143:  *     Each pageable resident page falls into one of three lists:
                    144:  *
                    145:  *     free    
                    146:  *             Available for allocation now.
                    147:  *     inactive
                    148:  *             Not referenced in any map, but still has an
                    149:  *             object/offset-page mapping, and may be dirty.
                    150:  *             This is the list of pages that should be
                    151:  *             paged out next.
                    152:  *     active
                    153:  *             A list of pages which have been placed in
                    154:  *             at least one physical map.  This list is
                    155:  *             ordered, in LRU-like fashion.
                    156:  */
                    157: 
                    158: extern
                    159: int    vm_page_fictitious_count;/* How many fictitious pages are free? */
                    160: extern
                    161: int    vm_page_active_count;   /* How many pages are active? */
                    162: extern
                    163: int    vm_page_inactive_count; /* How many pages are inactive? */
                    164: extern
                    165: int    vm_page_wire_count;     /* How many pages are wired? */
                    166: extern
                    167: int    vm_page_laundry_count;  /* How many pages being laundered? */
1.1.1.2   root      168: extern
1.1.1.7 ! root      169: int    vm_page_external_laundry_count; /* How many external pages being paged out? */
1.1       root      170: 
                    171: decl_simple_lock_data(extern,vm_page_queue_lock)/* lock on active and inactive
                    172:                                                   page queues */
                    173: decl_simple_lock_data(extern,vm_page_queue_free_lock)
                    174:                                                /* lock on free page queue */
                    175: 
1.1.1.7 ! root      176: extern phys_addr_t     vm_page_fictitious_addr;
1.1       root      177:                                /* (fake) phys_addr of fictitious pages */
                    178: 
                    179: extern void            vm_page_bootstrap(
                    180:        vm_offset_t     *startp,
                    181:        vm_offset_t     *endp);
                    182: extern void            vm_page_module_init(void);
                    183: 
                    184: extern vm_page_t       vm_page_lookup(
                    185:        vm_object_t     object,
                    186:        vm_offset_t     offset);
                    187: extern vm_page_t       vm_page_grab_fictitious(void);
1.1.1.7 ! root      188: extern boolean_t       vm_page_convert(vm_page_t *);
1.1       root      189: extern void            vm_page_more_fictitious(void);
1.1.1.7 ! root      190: extern vm_page_t       vm_page_grab(void);
        !           191: extern void            vm_page_release(vm_page_t, boolean_t, boolean_t);
        !           192: extern phys_addr_t     vm_page_grab_phys_addr(void);
1.1.1.6   root      193: extern vm_page_t       vm_page_grab_contig(vm_size_t, unsigned int);
                    194: extern void            vm_page_free_contig(vm_page_t, vm_size_t);
1.1       root      195: extern void            vm_page_wait(void (*)(void));
                    196: extern vm_page_t       vm_page_alloc(
                    197:        vm_object_t     object,
                    198:        vm_offset_t     offset);
                    199: extern void            vm_page_init(
1.1.1.6   root      200:        vm_page_t       mem);
1.1       root      201: extern void            vm_page_free(vm_page_t);
                    202: extern void            vm_page_activate(vm_page_t);
                    203: extern void            vm_page_deactivate(vm_page_t);
                    204: extern void            vm_page_rename(
                    205:        vm_page_t       mem,
                    206:        vm_object_t     new_object,
                    207:        vm_offset_t     new_offset);
                    208: extern void            vm_page_insert(
                    209:        vm_page_t       mem,
                    210:        vm_object_t     object,
                    211:        vm_offset_t     offset);
                    212: extern void            vm_page_remove(
                    213:        vm_page_t       mem);
                    214: 
                    215: extern void            vm_page_zero_fill(vm_page_t);
                    216: extern void            vm_page_copy(vm_page_t src_m, vm_page_t dest_m);
                    217: 
                    218: extern void            vm_page_wire(vm_page_t);
                    219: extern void            vm_page_unwire(vm_page_t);
                    220: 
                    221: #if    MACH_VM_DEBUG
                    222: extern unsigned int    vm_page_info(
                    223:        hash_info_bucket_t      *info,
                    224:        unsigned int            count);
                    225: #endif
                    226: 
                    227: /*
                    228:  *     Functions implemented as macros
                    229:  */
                    230: 
                    231: #define PAGE_ASSERT_WAIT(m, interruptible)                     \
                    232:                MACRO_BEGIN                                     \
                    233:                (m)->wanted = TRUE;                             \
                    234:                assert_wait((event_t) (m), (interruptible));    \
                    235:                MACRO_END
                    236: 
                    237: #define PAGE_WAKEUP_DONE(m)                                    \
                    238:                MACRO_BEGIN                                     \
                    239:                (m)->busy = FALSE;                              \
                    240:                if ((m)->wanted) {                              \
                    241:                        (m)->wanted = FALSE;                    \
                    242:                        thread_wakeup(((event_t) m));           \
                    243:                }                                               \
                    244:                MACRO_END
                    245: 
                    246: #define PAGE_WAKEUP(m)                                         \
                    247:                MACRO_BEGIN                                     \
                    248:                if ((m)->wanted) {                              \
                    249:                        (m)->wanted = FALSE;                    \
                    250:                        thread_wakeup((event_t) (m));           \
                    251:                }                                               \
                    252:                MACRO_END
                    253: 
                    254: #define VM_PAGE_FREE(p)                        \
                    255:                MACRO_BEGIN                     \
                    256:                vm_page_lock_queues();          \
                    257:                vm_page_free(p);                \
                    258:                vm_page_unlock_queues();        \
                    259:                MACRO_END
                    260: 
                    261: /*
                    262:  *     Macro to be used in place of pmap_enter()
                    263:  */
                    264: 
                    265: #define PMAP_ENTER(pmap, virtual_address, page, protection, wired) \
                    266:                MACRO_BEGIN                                     \
                    267:                pmap_enter(                                     \
                    268:                        (pmap),                                 \
                    269:                        (virtual_address),                      \
                    270:                        (page)->phys_addr,                      \
                    271:                        (protection) & ~(page)->page_lock,      \
                    272:                        (wired)                                 \
                    273:                 );                                             \
                    274:                MACRO_END
                    275: 
                    276: #define        VM_PAGE_WAIT(continuation)      vm_page_wait(continuation)
                    277: 
                    278: #define vm_page_lock_queues()  simple_lock(&vm_page_queue_lock)
                    279: #define vm_page_unlock_queues()        simple_unlock(&vm_page_queue_lock)
                    280: 
1.1.1.7 ! root      281: #define VM_PAGE_QUEUES_REMOVE(mem) vm_page_queues_remove(mem)
1.1       root      282: 
1.1.1.6   root      283: /*
                    284:  * Copyright (c) 2010-2014 Richard Braun.
                    285:  *
                    286:  * This program is free software: you can redistribute it and/or modify
                    287:  * it under the terms of the GNU General Public License as published by
                    288:  * the Free Software Foundation, either version 2 of the License, or
                    289:  * (at your option) any later version.
                    290:  *
                    291:  * This program is distributed in the hope that it will be useful,
                    292:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                    293:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                    294:  * GNU General Public License for more details.
                    295:  *
                    296:  * You should have received a copy of the GNU General Public License
                    297:  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
                    298:  *
                    299:  *
                    300:  * Physical page management.
                    301:  */
                    302: 
                    303: /*
                    304:  * Address/page conversion and rounding macros (not inline functions to
                    305:  * be easily usable on both virtual and physical addresses, which may not
                    306:  * have the same type size).
                    307:  */
                    308: #define vm_page_atop(addr)      ((addr) >> PAGE_SHIFT)
                    309: #define vm_page_ptoa(page)      ((page) << PAGE_SHIFT)
                    310: #define vm_page_trunc(addr)     P2ALIGN(addr, PAGE_SIZE)
                    311: #define vm_page_round(addr)     P2ROUND(addr, PAGE_SIZE)
                    312: #define vm_page_aligned(addr)   P2ALIGNED(addr, PAGE_SIZE)
                    313: 
                    314: /*
                    315:  * Segment selectors.
                    316:  *
                    317:  * Selector-to-segment-list translation table :
                    318:  * DMA          DMA
                    319:  * DMA32        DMA32 DMA
                    320:  * DIRECTMAP    DIRECTMAP DMA32 DMA
                    321:  * HIGHMEM      HIGHMEM DIRECTMAP DMA32 DMA
                    322:  */
                    323: #define VM_PAGE_SEL_DMA         0
                    324: #define VM_PAGE_SEL_DMA32       1
                    325: #define VM_PAGE_SEL_DIRECTMAP   2
                    326: #define VM_PAGE_SEL_HIGHMEM     3
                    327: 
                    328: /*
                    329:  * Page usage types.
                    330:  */
                    331: #define VM_PT_FREE          0   /* Page unused */
                    332: #define VM_PT_RESERVED      1   /* Page reserved at boot time */
                    333: #define VM_PT_TABLE         2   /* Page is part of the page table */
1.1.1.7 ! root      334: #define VM_PT_KERNEL        3   /* Type for generic kernel allocations */
1.1.1.6   root      335: 
                    336: static inline unsigned short
                    337: vm_page_type(const struct vm_page *page)
                    338: {
                    339:     return page->type;
                    340: }
                    341: 
                    342: void vm_page_set_type(struct vm_page *page, unsigned int order,
                    343:                       unsigned short type);
                    344: 
                    345: static inline unsigned int
                    346: vm_page_order(size_t size)
                    347: {
                    348:     return iorder2(vm_page_atop(vm_page_round(size)));
                    349: }
                    350: 
                    351: static inline phys_addr_t
                    352: vm_page_to_pa(const struct vm_page *page)
                    353: {
                    354:     return page->phys_addr;
                    355: }
                    356: 
                    357: /*
                    358:  * Associate private data with a page.
                    359:  */
                    360: static inline void
                    361: vm_page_set_priv(struct vm_page *page, void *priv)
                    362: {
                    363:     page->priv = priv;
                    364: }
                    365: 
                    366: static inline void *
                    367: vm_page_get_priv(const struct vm_page *page)
                    368: {
                    369:     return page->priv;
                    370: }
                    371: 
                    372: /*
                    373:  * Load physical memory into the vm_page module at boot time.
                    374:  *
                    375:  * All addresses must be page-aligned. Segments can be loaded in any order.
                    376:  */
1.1.1.7 ! root      377: void vm_page_load(unsigned int seg_index, phys_addr_t start, phys_addr_t end);
        !           378: 
        !           379: /*
        !           380:  * Load available physical memory into the vm_page module at boot time.
        !           381:  *
        !           382:  * The segment referred to must have been loaded with vm_page_load
        !           383:  * before loading its heap.
        !           384:  */
        !           385: void vm_page_load_heap(unsigned int seg_index, phys_addr_t start,
        !           386:                        phys_addr_t end);
1.1.1.6   root      387: 
                    388: /*
                    389:  * Return true if the vm_page module is completely initialized, false
                    390:  * otherwise, in which case only vm_page_bootalloc() can be used for
                    391:  * allocations.
                    392:  */
                    393: int vm_page_ready(void);
                    394: 
                    395: /*
                    396:  * Early allocation function.
                    397:  *
                    398:  * This function is used by the vm_resident module to implement
                    399:  * pmap_steal_memory. It can be used after physical segments have been loaded
                    400:  * and before the vm_page module is initialized.
                    401:  */
                    402: unsigned long vm_page_bootalloc(size_t size);
                    403: 
                    404: /*
                    405:  * Set up the vm_page module.
                    406:  *
                    407:  * Architecture-specific code must have loaded segments before calling this
                    408:  * function. Segments must comply with the selector-to-segment-list table,
                    409:  * e.g. HIGHMEM is loaded if and only if DIRECTMAP, DMA32 and DMA are loaded,
                    410:  * notwithstanding segment aliasing.
                    411:  *
                    412:  * Once this function returns, the vm_page module is ready, and normal
                    413:  * allocation functions can be used.
                    414:  */
                    415: void vm_page_setup(void);
                    416: 
                    417: /*
                    418:  * Make the given page managed by the vm_page module.
                    419:  *
                    420:  * If additional memory can be made usable after the VM system is initialized,
                    421:  * it should be reported through this function.
                    422:  */
                    423: void vm_page_manage(struct vm_page *page);
                    424: 
                    425: /*
                    426:  * Return the page descriptor for the given physical address.
                    427:  */
                    428: struct vm_page * vm_page_lookup_pa(phys_addr_t pa);
                    429: 
                    430: /*
                    431:  * Allocate a block of 2^order physical pages.
                    432:  *
                    433:  * The selector is used to determine the segments from which allocation can
                    434:  * be attempted.
                    435:  *
                    436:  * This function should only be used by the vm_resident module.
                    437:  */
                    438: struct vm_page * vm_page_alloc_pa(unsigned int order, unsigned int selector,
                    439:                                   unsigned short type);
                    440: 
                    441: /*
                    442:  * Release a block of 2^order physical pages.
                    443:  *
                    444:  * This function should only be used by the vm_resident module.
                    445:  */
                    446: void vm_page_free_pa(struct vm_page *page, unsigned int order);
                    447: 
                    448: /*
                    449:  * Return the name of the given segment.
                    450:  */
                    451: const char * vm_page_seg_name(unsigned int seg_index);
                    452: 
                    453: /*
                    454:  * Display internal information about the module.
                    455:  */
                    456: void vm_page_info_all(void);
                    457: 
                    458: /*
1.1.1.7 ! root      459:  * Return the maximum physical address for a given segment selector.
        !           460:  */
        !           461: phys_addr_t vm_page_seg_end(unsigned int selector);
        !           462: 
        !           463: /*
        !           464:  * Return the total number of physical pages.
        !           465:  */
        !           466: unsigned long vm_page_table_size(void);
        !           467: 
        !           468: /*
        !           469:  * Return the index of a page in the page table.
        !           470:  */
        !           471: unsigned long vm_page_table_index(phys_addr_t pa);
        !           472: 
        !           473: /*
1.1.1.6   root      474:  * Return the total amount of physical memory.
                    475:  */
                    476: phys_addr_t vm_page_mem_size(void);
                    477: 
                    478: /*
                    479:  * Return the amount of free (unused) pages.
                    480:  *
                    481:  * XXX This currently relies on the kernel being non preemptible and
                    482:  * uniprocessor.
                    483:  */
                    484: unsigned long vm_page_mem_free(void);
                    485: 
1.1.1.7 ! root      486: /*
        !           487:  * Remove the given page from any page queue it might be in.
        !           488:  */
        !           489: void vm_page_queues_remove(struct vm_page *page);
        !           490: 
        !           491: /*
        !           492:  * Balance physical pages among segments.
        !           493:  *
        !           494:  * This function should be called first by the pageout daemon
        !           495:  * on memory pressure, since it may be unnecessary to perform any
        !           496:  * other operation, let alone shrink caches, if balancing is
        !           497:  * enough to make enough free pages.
        !           498:  *
        !           499:  * Return TRUE if balancing made enough free pages for unprivileged
        !           500:  * allocations to succeed, in which case pending allocations are resumed.
        !           501:  *
        !           502:  * This function acquires vm_page_queue_free_lock, which is held on return.
        !           503:  */
        !           504: boolean_t vm_page_balance(void);
        !           505: 
        !           506: /*
        !           507:  * Evict physical pages.
        !           508:  *
        !           509:  * This function should be called by the pageout daemon after balancing
        !           510:  * the segments and shrinking kernel caches.
        !           511:  *
        !           512:  * Return TRUE if eviction made enough free pages for unprivileged
        !           513:  * allocations to succeed, in which case pending allocations are resumed.
        !           514:  *
        !           515:  * Otherwise, report whether the pageout daemon should wait (some pages
        !           516:  * have been paged out) or not (only clean pages have been released).
        !           517:  *
        !           518:  * This function acquires vm_page_queue_free_lock, which is held on return.
        !           519:  */
        !           520: boolean_t vm_page_evict(boolean_t *should_wait);
        !           521: 
        !           522: /*
        !           523:  * Turn active pages into inactive ones for second-chance LRU
        !           524:  * approximation.
        !           525:  *
        !           526:  * This function should be called by the pageout daemon on memory pressure,
        !           527:  * i.e. right before evicting pages.
        !           528:  *
        !           529:  * XXX This is probably not the best strategy, compared to keeping the
        !           530:  * active/inactive ratio in check at all times, but this means less
        !           531:  * frequent refills.
        !           532:  */
        !           533: void vm_page_refill_inactive(void);
        !           534: 
1.1       root      535: #endif /* _VM_VM_PAGE_H_ */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.