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