|
|
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_vm_debug.h> ! 38: ! 39: #include <mach/boolean.h> ! 40: #include <mach/vm_prot.h> ! 41: #include <mach/vm_param.h> ! 42: #include <vm/vm_object.h> ! 43: #include <kern/queue.h> ! 44: #include <kern/lock.h> ! 45: #include <kern/zalloc.h> ! 46: ! 47: #include <kern/macro_help.h> ! 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 { ! 81: queue_chain_t pageq; /* queue info for FIFO ! 82: * queue or free list (P) */ ! 83: queue_chain_t listq; /* all pages in same object (O) */ ! 84: struct vm_page *next; /* VP bucket link (O) */ ! 85: ! 86: vm_object_t object; /* which object am I in (O,P) */ ! 87: vm_offset_t offset; /* offset into that object (O,P) */ ! 88: ! 89: unsigned int wire_count:16, /* how many wired down maps use me? ! 90: (O&P) */ ! 91: /* boolean_t */ inactive:1, /* page is in inactive list (P) */ ! 92: active:1, /* page is in active list (P) */ ! 93: laundry:1, /* page is being cleaned now (P)*/ ! 94: free:1, /* page is on free list (P) */ ! 95: reference:1, /* page has been used (P) */ ! 96: :0; /* (force to 'long' boundary) */ ! 97: #ifdef ns32000 ! 98: int pad; /* extra space for ns32000 bit ops */ ! 99: #endif /* ns32000 */ ! 100: ! 101: unsigned int ! 102: /* boolean_t */ busy:1, /* page is in transit (O) */ ! 103: wanted:1, /* someone is waiting for page (O) */ ! 104: tabled:1, /* page is in VP table (O) */ ! 105: fictitious:1, /* Physical page doesn't exist (O) */ ! 106: private:1, /* Page should not be returned to ! 107: * the free list (O) */ ! 108: absent:1, /* Data has been requested, but is ! 109: * not yet available (O) */ ! 110: error:1, /* Data manager was unable to provide ! 111: * data due to error (O) */ ! 112: dirty:1, /* Page must be cleaned (O) */ ! 113: precious:1, /* Page is precious; data must be ! 114: * returned even if clean (O) */ ! 115: overwriting:1, /* Request to unlock has been made ! 116: * without having data. (O) ! 117: * [See vm_object_overwrite] */ ! 118: :0; ! 119: ! 120: vm_offset_t phys_addr; /* Physical address of page, passed ! 121: * to pmap_enter (read-only) */ ! 122: vm_prot_t page_lock; /* Uses prohibited by data manager (O) */ ! 123: vm_prot_t unlock_request; /* Outstanding unlock request (O) */ ! 124: }; ! 125: ! 126: typedef struct vm_page *vm_page_t; ! 127: ! 128: #define VM_PAGE_NULL ((vm_page_t) 0) ! 129: ! 130: /* ! 131: * For debugging, this macro can be defined to perform ! 132: * some useful check on a page structure. ! 133: */ ! 134: ! 135: #define VM_PAGE_CHECK(mem) ! 136: ! 137: /* ! 138: * Each pageable resident page falls into one of three lists: ! 139: * ! 140: * free ! 141: * Available for allocation now. ! 142: * inactive ! 143: * Not referenced in any map, but still has an ! 144: * object/offset-page mapping, and may be dirty. ! 145: * This is the list of pages that should be ! 146: * paged out next. ! 147: * active ! 148: * A list of pages which have been placed in ! 149: * at least one physical map. This list is ! 150: * ordered, in LRU-like fashion. ! 151: */ ! 152: ! 153: extern ! 154: vm_page_t vm_page_queue_free; /* memory free queue */ ! 155: extern ! 156: vm_page_t vm_page_queue_fictitious; /* fictitious free queue */ ! 157: extern ! 158: queue_head_t vm_page_queue_active; /* active memory queue */ ! 159: extern ! 160: queue_head_t vm_page_queue_inactive; /* inactive memory queue */ ! 161: ! 162: extern ! 163: vm_offset_t first_phys_addr; /* physical address for first_page */ ! 164: extern ! 165: vm_offset_t last_phys_addr; /* physical address for last_page */ ! 166: ! 167: extern ! 168: int vm_page_free_count; /* How many pages are free? */ ! 169: extern ! 170: int vm_page_fictitious_count;/* How many fictitious pages are free? */ ! 171: extern ! 172: int vm_page_active_count; /* How many pages are active? */ ! 173: extern ! 174: int vm_page_inactive_count; /* How many pages are inactive? */ ! 175: extern ! 176: int vm_page_wire_count; /* How many pages are wired? */ ! 177: extern ! 178: int vm_page_free_target; /* How many do we want free? */ ! 179: extern ! 180: int vm_page_free_min; /* When to wakeup pageout */ ! 181: extern ! 182: int vm_page_inactive_target;/* How many do we want inactive? */ ! 183: extern ! 184: int vm_page_free_reserved; /* How many pages reserved to do pageout */ ! 185: extern ! 186: int vm_page_laundry_count; /* How many pages being laundered? */ ! 187: ! 188: decl_simple_lock_data(extern,vm_page_queue_lock)/* lock on active and inactive ! 189: page queues */ ! 190: decl_simple_lock_data(extern,vm_page_queue_free_lock) ! 191: /* lock on free page queue */ ! 192: ! 193: extern unsigned int vm_page_free_wanted; ! 194: /* how many threads are waiting for memory */ ! 195: ! 196: extern vm_offset_t vm_page_fictitious_addr; ! 197: /* (fake) phys_addr of fictitious pages */ ! 198: ! 199: extern void vm_page_bootstrap( ! 200: vm_offset_t *startp, ! 201: vm_offset_t *endp); ! 202: extern void vm_page_module_init(void); ! 203: ! 204: extern void vm_page_create( ! 205: vm_offset_t start, ! 206: vm_offset_t end); ! 207: extern vm_page_t vm_page_lookup( ! 208: vm_object_t object, ! 209: vm_offset_t offset); ! 210: extern vm_page_t vm_page_grab_fictitious(void); ! 211: extern void vm_page_release_fictitious(vm_page_t); ! 212: extern boolean_t vm_page_convert(vm_page_t); ! 213: extern void vm_page_more_fictitious(void); ! 214: extern vm_page_t vm_page_grab(void); ! 215: extern void vm_page_release(vm_page_t); ! 216: extern void vm_page_wait(void (*)(void)); ! 217: extern vm_page_t vm_page_alloc( ! 218: vm_object_t object, ! 219: vm_offset_t offset); ! 220: extern void vm_page_init( ! 221: vm_page_t mem, ! 222: vm_offset_t phys_addr); ! 223: extern void vm_page_free(vm_page_t); ! 224: extern void vm_page_activate(vm_page_t); ! 225: extern void vm_page_deactivate(vm_page_t); ! 226: extern void vm_page_rename( ! 227: vm_page_t mem, ! 228: vm_object_t new_object, ! 229: vm_offset_t new_offset); ! 230: extern void vm_page_insert( ! 231: vm_page_t mem, ! 232: vm_object_t object, ! 233: vm_offset_t offset); ! 234: extern void vm_page_remove( ! 235: vm_page_t mem); ! 236: ! 237: extern void vm_page_zero_fill(vm_page_t); ! 238: extern void vm_page_copy(vm_page_t src_m, vm_page_t dest_m); ! 239: ! 240: extern void vm_page_wire(vm_page_t); ! 241: extern void vm_page_unwire(vm_page_t); ! 242: ! 243: extern void vm_set_page_size(void); ! 244: ! 245: #if MACH_VM_DEBUG ! 246: extern unsigned int vm_page_info( ! 247: hash_info_bucket_t *info, ! 248: unsigned int count); ! 249: #endif ! 250: ! 251: /* ! 252: * Functions implemented as macros ! 253: */ ! 254: ! 255: #define PAGE_ASSERT_WAIT(m, interruptible) \ ! 256: MACRO_BEGIN \ ! 257: (m)->wanted = TRUE; \ ! 258: assert_wait((event_t) (m), (interruptible)); \ ! 259: MACRO_END ! 260: ! 261: #define PAGE_WAKEUP_DONE(m) \ ! 262: MACRO_BEGIN \ ! 263: (m)->busy = FALSE; \ ! 264: if ((m)->wanted) { \ ! 265: (m)->wanted = FALSE; \ ! 266: thread_wakeup(((event_t) m)); \ ! 267: } \ ! 268: MACRO_END ! 269: ! 270: #define PAGE_WAKEUP(m) \ ! 271: MACRO_BEGIN \ ! 272: if ((m)->wanted) { \ ! 273: (m)->wanted = FALSE; \ ! 274: thread_wakeup((event_t) (m)); \ ! 275: } \ ! 276: MACRO_END ! 277: ! 278: #define VM_PAGE_FREE(p) \ ! 279: MACRO_BEGIN \ ! 280: vm_page_lock_queues(); \ ! 281: vm_page_free(p); \ ! 282: vm_page_unlock_queues(); \ ! 283: MACRO_END ! 284: ! 285: /* ! 286: * Macro to be used in place of pmap_enter() ! 287: */ ! 288: ! 289: #define PMAP_ENTER(pmap, virtual_address, page, protection, wired) \ ! 290: MACRO_BEGIN \ ! 291: pmap_enter( \ ! 292: (pmap), \ ! 293: (virtual_address), \ ! 294: (page)->phys_addr, \ ! 295: (protection) & ~(page)->page_lock, \ ! 296: (wired) \ ! 297: ); \ ! 298: MACRO_END ! 299: ! 300: #define VM_PAGE_WAIT(continuation) vm_page_wait(continuation) ! 301: ! 302: #define vm_page_lock_queues() simple_lock(&vm_page_queue_lock) ! 303: #define vm_page_unlock_queues() simple_unlock(&vm_page_queue_lock) ! 304: ! 305: #define VM_PAGE_QUEUES_REMOVE(mem) \ ! 306: MACRO_BEGIN \ ! 307: if (mem->active) { \ ! 308: queue_remove(&vm_page_queue_active, \ ! 309: mem, vm_page_t, pageq); \ ! 310: mem->active = FALSE; \ ! 311: vm_page_active_count--; \ ! 312: } \ ! 313: \ ! 314: if (mem->inactive) { \ ! 315: queue_remove(&vm_page_queue_inactive, \ ! 316: mem, vm_page_t, pageq); \ ! 317: mem->inactive = FALSE; \ ! 318: vm_page_inactive_count--; \ ! 319: } \ ! 320: MACRO_END ! 321: ! 322: #endif /* _VM_VM_PAGE_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.