vm_page.h revision 1827
159138Smsmith/* 259138Smsmith * Copyright (c) 1991, 1993 359138Smsmith * The Regents of the University of California. All rights reserved. 459138Smsmith * 559138Smsmith * This code is derived from software contributed to Berkeley by 659138Smsmith * The Mach Operating System project at Carnegie-Mellon University. 759138Smsmith * 859138Smsmith * Redistribution and use in source and binary forms, with or without 959138Smsmith * modification, are permitted provided that the following conditions 1059138Smsmith * are met: 1159138Smsmith * 1. Redistributions of source code must retain the above copyright 1259138Smsmith * notice, this list of conditions and the following disclaimer. 1359138Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1459138Smsmith * notice, this list of conditions and the following disclaimer in the 1559138Smsmith * documentation and/or other materials provided with the distribution. 1659138Smsmith * 3. All advertising materials mentioning features or use of this software 1759138Smsmith * must display the following acknowledgement: 1859138Smsmith * This product includes software developed by the University of 1959138Smsmith * California, Berkeley and its contributors. 2059138Smsmith * 4. Neither the name of the University nor the names of its contributors 2159138Smsmith * may be used to endorse or promote products derived from this software 2259138Smsmith * without specific prior written permission. 2359138Smsmith * 2459138Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2559138Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2659138Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2759138Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2859138Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2959138Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3059138Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3159138Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3259138Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3359138Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3459138Smsmith * SUCH DAMAGE. 3559138Smsmith * 3659138Smsmith * from: @(#)vm_page.h 8.2 (Berkeley) 12/13/93 3759138Smsmith * 3859138Smsmith * 3959138Smsmith * Copyright (c) 1987, 1990 Carnegie-Mellon University. 4059138Smsmith * All rights reserved. 4159138Smsmith * 4259138Smsmith * Authors: Avadis Tevanian, Jr., Michael Wayne Young 4359138Smsmith * 4459138Smsmith * Permission to use, copy, modify and distribute this software and 4559138Smsmith * its documentation is hereby granted, provided that both the copyright 4659138Smsmith * notice and this permission notice appear in all copies of the 4759138Smsmith * software, derivative works or modified versions, and any portions 4859138Smsmith * thereof, and that both notices appear in supporting documentation. 4959138Smsmith * 5059138Smsmith * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 5159138Smsmith * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 5259138Smsmith * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 5359138Smsmith * 5459138Smsmith * Carnegie Mellon requests users of this software to return to 5559138Smsmith * 5659138Smsmith * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 5759138Smsmith * School of Computer Science 5859138Smsmith * Carnegie Mellon University 5959138Smsmith * Pittsburgh PA 15213-3890 6059138Smsmith * 6159138Smsmith * any improvements or extensions that they make and grant Carnegie the 6259138Smsmith * rights to redistribute these changes. 6359138Smsmith * 6459138Smsmith * $Id: vm_page.h,v 1.3 1994/08/02 07:55:32 davidg Exp $ 6559138Smsmith */ 6659138Smsmith 6759138Smsmith/* 6859138Smsmith * Resident memory system definitions. 6959138Smsmith */ 7059138Smsmith 7159138Smsmith#ifndef _VM_PAGE_ 7259138Smsmith#define _VM_PAGE_ 7359138Smsmith 7459138Smsmith/* 7559138Smsmith * Management of resident (logical) pages. 7659138Smsmith * 7759138Smsmith * A small structure is kept for each resident 7859138Smsmith * page, indexed by page number. Each structure 7959138Smsmith * is an element of several lists: 8059138Smsmith * 8159138Smsmith * A hash table bucket used to quickly 8259138Smsmith * perform object/offset lookups 8359138Smsmith * 8459138Smsmith * A list of all pages for a given object, 8559138Smsmith * so they can be quickly deactivated at 8659138Smsmith * time of deallocation. 8759138Smsmith * 8859138Smsmith * An ordered list of pages due for pageout. 8959138Smsmith * 9059138Smsmith * In addition, the structure contains the object 9159138Smsmith * and offset to which this page belongs (for pageout), 9259138Smsmith * and sundry status bits. 9359138Smsmith * 9459138Smsmith * Fields in this structure are locked either by the lock on the 9559138Smsmith * object that the page belongs to (O) or by the lock on the page 9659138Smsmith * queues (P). 9759138Smsmith */ 9859138Smsmith 9959138SmsmithTAILQ_HEAD(pglist, vm_page); 10059138Smsmith 10159138Smsmithstruct vm_page { 10259138Smsmith TAILQ_ENTRY(vm_page) pageq; /* queue info for FIFO 10359138Smsmith * queue or free list (P) */ 10459138Smsmith TAILQ_ENTRY(vm_page) hashq; /* hash table links (O)*/ 10559138Smsmith TAILQ_ENTRY(vm_page) listq; /* pages in same object (O)*/ 10659138Smsmith 10759138Smsmith vm_object_t object; /* which object am I in (O,P)*/ 10859138Smsmith vm_offset_t offset; /* offset into object (O,P) */ 10959138Smsmith 11059138Smsmith u_short wire_count; /* wired down maps refs (P) */ 11159138Smsmith u_short flags; /* see below */ 11259138Smsmith short hold_count; /* page hold count */ 11359138Smsmith u_short act_count; /* page usage count */ 11459138Smsmith 11559138Smsmith vm_offset_t phys_addr; /* physical address of page */ 11659138Smsmith}; 11759138Smsmith 11859138Smsmith/* 11959138Smsmith * These are the flags defined for vm_page. 12059138Smsmith * 12159138Smsmith * Note: PG_FILLED and PG_DIRTY are added for the filesystems. 12259138Smsmith */ 12359138Smsmith#define PG_INACTIVE 0x0001 /* page is in inactive list (P) */ 12459138Smsmith#define PG_ACTIVE 0x0002 /* page is in active list (P) */ 12559138Smsmith#define PG_LAUNDRY 0x0004 /* page is being cleaned now (P)*/ 12659138Smsmith#define PG_CLEAN 0x0008 /* page has not been modified */ 12759138Smsmith#define PG_BUSY 0x0010 /* page is in transit (O) */ 12859138Smsmith#define PG_WANTED 0x0020 /* someone is waiting for page (O) */ 12959138Smsmith#define PG_TABLED 0x0040 /* page is in VP table (O) */ 13059138Smsmith#define PG_COPYONWRITE 0x0080 /* must copy page before changing (O) */ 13159138Smsmith#define PG_FICTITIOUS 0x0100 /* physical page doesn't exist (O) */ 13259138Smsmith#define PG_FAKE 0x0200 /* page is placeholder for pagein (O) */ 13359138Smsmith#define PG_FILLED 0x0400 /* client flag to set when filled */ 13459138Smsmith#define PG_DIRTY 0x0800 /* client flag to set when dirty */ 13559138Smsmith#define PG_REFERENCED 0x1000 /* page has been referenced */ 13659138Smsmith#define PG_PAGEROWNED 0x4000 /* DEBUG: async paging op in progress */ 13759138Smsmith#define PG_PTPAGE 0x8000 /* DEBUG: is a user page table page */ 13859138Smsmith 13959138Smsmith#if VM_PAGE_DEBUG 14059138Smsmith#define VM_PAGE_CHECK(mem) { \ 14159138Smsmith if ((((unsigned int) mem) < ((unsigned int) &vm_page_array[0])) || \ 14259138Smsmith (((unsigned int) mem) > \ 14359138Smsmith ((unsigned int) &vm_page_array[last_page-first_page])) || \ 14459138Smsmith ((mem->flags & (PG_ACTIVE | PG_INACTIVE)) == \ 14559138Smsmith (PG_ACTIVE | PG_INACTIVE))) \ 14659138Smsmith panic("vm_page_check: not valid!"); \ 14759138Smsmith} 14859138Smsmith#else /* VM_PAGE_DEBUG */ 14959138Smsmith#define VM_PAGE_CHECK(mem) 15059138Smsmith#endif /* VM_PAGE_DEBUG */ 15159138Smsmith 15259138Smsmith#ifdef KERNEL 15359138Smsmith/* 15459138Smsmith * Each pageable resident page falls into one of three lists: 15559138Smsmith * 15659138Smsmith * free 15759138Smsmith * Available for allocation now. 15859138Smsmith * inactive 15959138Smsmith * Not referenced in any map, but still has an 16059138Smsmith * object/offset-page mapping, and may be dirty. 16159138Smsmith * This is the list of pages that should be 16259138Smsmith * paged out next. 16359138Smsmith * active 16459138Smsmith * A list of pages which have been placed in 16559138Smsmith * at least one physical map. This list is 16659138Smsmith * ordered, in LRU-like fashion. 16759138Smsmith */ 16859138Smsmith 16959138Smsmithextern 17059138Smsmithstruct pglist vm_page_queue_free; /* memory free queue */ 17159138Smsmithextern 17259138Smsmithstruct pglist vm_page_queue_active; /* active memory queue */ 17359138Smsmithextern 17459138Smsmithstruct pglist vm_page_queue_inactive; /* inactive memory queue */ 17559138Smsmith 17659138Smsmithextern 17759138Smsmithvm_page_t vm_page_array; /* First resident page in table */ 17859138Smsmithextern 17959138Smsmithlong first_page; /* first physical page number */ 18059138Smsmith /* ... represented in vm_page_array */ 18159138Smsmithextern 18259138Smsmithlong last_page; /* last physical page number */ 18359138Smsmith /* ... represented in vm_page_array */ 18459138Smsmith /* [INCLUSIVE] */ 18559138Smsmithextern 18659138Smsmithvm_offset_t first_phys_addr; /* physical address for first_page */ 18759138Smsmithextern 18859138Smsmithvm_offset_t last_phys_addr; /* physical address for last_page */ 18959138Smsmith 19059138Smsmith#define VM_PAGE_TO_PHYS(entry) ((entry)->phys_addr) 19159138Smsmith 19259138Smsmith#define IS_VM_PHYSADDR(pa) \ 19359138Smsmith ((pa) >= first_phys_addr && (pa) <= last_phys_addr) 19459138Smsmith 19559138Smsmith#define PHYS_TO_VM_PAGE(pa) \ 19659138Smsmith (&vm_page_array[atop(pa) - first_page ]) 19759138Smsmith 19859138Smsmithextern 19959138Smsmithsimple_lock_data_t vm_page_queue_lock; /* lock on active and inactive 20059138Smsmith page queues */ 20159138Smsmithextern /* lock on free page queue */ 20259138Smsmithsimple_lock_data_t vm_page_queue_free_lock; 20359138Smsmith 20459138Smsmith/* 20559138Smsmith * Functions implemented as macros 20659138Smsmith */ 20759138Smsmith 20859138Smsmith#define PAGE_ASSERT_WAIT(m, interruptible) { \ 20959138Smsmith (m)->flags |= PG_WANTED; \ 21059138Smsmith assert_wait((int) (m), (interruptible)); \ 21159138Smsmith } 21259138Smsmith 21359138Smsmith#define PAGE_WAKEUP(m) { \ 21459138Smsmith (m)->flags &= ~PG_BUSY; \ 21559138Smsmith if ((m)->flags & PG_WANTED) { \ 21659138Smsmith (m)->flags &= ~PG_WANTED; \ 21759138Smsmith wakeup((caddr_t) (m)); \ 21859138Smsmith } \ 21959138Smsmith } 22059138Smsmith 22159138Smsmith#define vm_page_lock_queues() simple_lock(&vm_page_queue_lock) 22259138Smsmith#define vm_page_unlock_queues() simple_unlock(&vm_page_queue_lock) 22359138Smsmith 22459138Smsmith#define vm_page_set_modified(m) { (m)->flags &= ~PG_CLEAN; } 22559138Smsmith 22659138Smsmith#define VM_PAGE_INIT(mem, object, offset) { \ 22759138Smsmith (mem)->flags = PG_BUSY | PG_CLEAN | PG_FAKE; \ 22859138Smsmith vm_page_insert((mem), (object), (offset)); \ 22959138Smsmith (mem)->wire_count = 0; \ 23059138Smsmith (mem)->hold_count = 0; \ 23159138Smsmith (mem)->act_count = 0; \ 23259138Smsmith} 23359138Smsmith 23459138Smsmithvoid vm_page_activate __P((vm_page_t)); 23559138Smsmithvm_page_t vm_page_alloc __P((vm_object_t, vm_offset_t)); 23659138Smsmithvoid vm_page_copy __P((vm_page_t, vm_page_t)); 23759138Smsmithvoid vm_page_deactivate __P((vm_page_t)); 23859138Smsmithvoid vm_page_free __P((vm_page_t)); 23959138Smsmithvoid vm_page_insert __P((vm_page_t, vm_object_t, vm_offset_t)); 24059138Smsmithvm_page_t vm_page_lookup __P((vm_object_t, vm_offset_t)); 24159138Smsmithvoid vm_page_remove __P((vm_page_t)); 24259138Smsmithvoid vm_page_rename __P((vm_page_t, vm_object_t, vm_offset_t)); 24359138Smsmithvm_offset_t vm_page_startup __P((vm_offset_t, vm_offset_t, vm_offset_t)); 24459138Smsmithvoid vm_page_unwire __P((vm_page_t)); 24559138Smsmithvoid vm_page_wire __P((vm_page_t)); 24659138Smsmithboolean_t vm_page_zero_fill __P((vm_page_t)); 24759138Smsmith 24859138Smsmith 24959138Smsmith/* 25059138Smsmith * Keep page from being freed by the page daemon 25159138Smsmith * much of the same effect as wiring, except much lower 25259138Smsmith * overhead and should be used only for *very* temporary 25359138Smsmith * holding ("wiring"). 25459138Smsmith */ 25559138Smsmithstatic inline void 25659138Smsmithvm_page_hold(mem) 25759138Smsmith vm_page_t mem; 25859138Smsmith{ 25959138Smsmith mem->hold_count++; 26059138Smsmith} 26159138Smsmith 26259138Smsmithstatic inline void 26359138Smsmithvm_page_unhold(mem) 26459138Smsmith vm_page_t mem; 26559138Smsmith{ 26659138Smsmith if( --mem->hold_count < 0) 26759138Smsmith panic("vm_page_unhold: hold count < 0!!!"); 26859138Smsmith} 26959138Smsmith 27059138Smsmith#endif /* KERNEL */ 27159138Smsmith#endif /* !_VM_PAGE_ */ 27259138Smsmith