|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: */ ! 52: /* ! 53: * File: vm/vm_page.h ! 54: * Author: Avadis Tevanian, Jr., Michael Wayne Young ! 55: * Date: 1985 ! 56: * ! 57: * Resident memory system definitions. ! 58: */ ! 59: ! 60: #ifndef _VM_VM_PAGE_H_ ! 61: #define _VM_VM_PAGE_H_ ! 62: ! 63: #include <mach/boolean.h> ! 64: #include <mach/vm_prot.h> ! 65: #include <mach/vm_param.h> ! 66: #include <vm/vm_object.h> ! 67: #include <kern/queue.h> ! 68: #include <kern/lock.h> ! 69: ! 70: #include <kern/macro_help.h> ! 71: ! 72: /* ! 73: * Management of resident (logical) pages. ! 74: * ! 75: * A small structure is kept for each resident ! 76: * page, indexed by page number. Each structure ! 77: * is an element of several lists: ! 78: * ! 79: * A hash table bucket used to quickly ! 80: * perform object/offset lookups ! 81: * ! 82: * A list of all pages for a given object, ! 83: * so they can be quickly deactivated at ! 84: * time of deallocation. ! 85: * ! 86: * An ordered list of pages due for pageout. ! 87: * ! 88: * In addition, the structure contains the object ! 89: * and offset to which this page belongs (for pageout), ! 90: * and sundry status bits. ! 91: * ! 92: * Fields in this structure are locked either by the lock on the ! 93: * object that the page belongs to (O) or by the lock on the page ! 94: * queues (P). [Some fields require that both locks be held to ! 95: * change that field; holding either lock is sufficient to read.] ! 96: */ ! 97: ! 98: struct vm_page { ! 99: queue_chain_t pageq; /* queue info for FIFO ! 100: * queue or free list (P) */ ! 101: queue_chain_t listq; /* all pages in same object (O) */ ! 102: struct vm_page *next; /* VP bucket link (O) */ ! 103: ! 104: vm_object_t object; /* which object am I in (O&P) */ ! 105: vm_offset_t offset; /* offset into that object (O,P) */ ! 106: ! 107: unsigned int wire_count:16, /* how many wired down maps use me? ! 108: (O&P) */ ! 109: /* boolean_t */ inactive:1, /* page is in inactive list (P) */ ! 110: active:1, /* page is in active list (P) */ ! 111: laundry:1, /* page is being cleaned now (P)*/ ! 112: free:1, /* page is on free list (P) */ ! 113: reference:1, /* page has been used (P) */ ! 114: limbo:1, /* page prepped then stolen (P) */ ! 115: pageout:1, /* page wired & busy for pageout (P) */ ! 116: gobbled:1, /* page used internally (P) */ ! 117: :0; /* (force to 'long' boundary) */ ! 118: #ifdef ns32000 ! 119: int pad; /* extra space for ns32000 bit ops */ ! 120: #endif /* ns32000 */ ! 121: ! 122: unsigned int ! 123: /* boolean_t */ busy:1, /* page is in transit (O) */ ! 124: wanted:1, /* someone is waiting for page (O) */ ! 125: tabled:1, /* page is in VP table (O) */ ! 126: fictitious:1, /* Physical page doesn't exist (O) */ ! 127: private:1, /* Page should not be returned to ! 128: * the free list (O) */ ! 129: absent:1, /* Data has been requested, but is ! 130: * not yet available (O) */ ! 131: error:1, /* Data manager was unable to provide ! 132: * data due to error (O) */ ! 133: dirty:1, /* Page must be cleaned (O) */ ! 134: cleaning:1, /* Page clean has begun (O) */ ! 135: precious:1, /* Page is precious; data must be ! 136: * returned even if clean (O) */ ! 137: clustered:1, /* page is not the faulted page (O) */ ! 138: overwriting:1, /* Request to unlock has been made ! 139: * without having data. (O) ! 140: * [See vm_fault_page_overwrite] */ ! 141: restart:1, /* Page was pushed higher in shadow ! 142: chain by copy_call-related pagers; ! 143: start again at top of chain */ ! 144: lock_supplied:1,/* protection supplied by pager (O) */ ! 145: /* vm_prot_t */ page_lock:3, /* Uses prohibited by pager (O) */ ! 146: /* vm_prot_t */ unlock_request:3,/* Outstanding unlock request (O) */ ! 147: unusual:1, /* Page is absent, error, restart or ! 148: page locked */ ! 149: discard_request:1,/* a memory_object_discard_request() ! 150: * has been sent */ ! 151: list_req_pending:1, /* pagein/pageout alt mechanism */ ! 152: /* allows creation of list */ ! 153: /* requests on pages that are */ ! 154: /* actively being paged. */ ! 155: :0; ! 156: ! 157: vm_offset_t phys_addr; /* Physical address of page, passed ! 158: * to pmap_enter (read-only) */ ! 159: kern_return_t page_error; ! 160: ! 161: union { ! 162: struct { ! 163: unsigned int prep:16, /* page prep count */ ! 164: pin:16; /* page pin pount */ ! 165: } pp_counts; ! 166: unsigned int pp_both; /* used to test for both zero */ ! 167: } prep_pin_u; ! 168: }; ! 169: ! 170: typedef struct vm_page *vm_page_t; ! 171: ! 172: #define prep_count prep_pin_u.pp_counts.prep ! 173: #define pin_count prep_pin_u.pp_counts.pin ! 174: #define prep_pin_count prep_pin_u.pp_both ! 175: ! 176: #define VM_PAGE_NULL ((vm_page_t) 0) ! 177: #define NEXT_PAGE(m) ((vm_page_t) (m)->pageq.next) ! 178: ! 179: /* ! 180: * XXX The unusual bit should not be necessary. Most of the bit ! 181: * XXX fields above really want to be masks. ! 182: */ ! 183: ! 184: /* ! 185: * For debugging, this macro can be defined to perform ! 186: * some useful check on a page structure. ! 187: */ ! 188: ! 189: #define VM_PAGE_CHECK(mem) ! 190: ! 191: /* ! 192: * Each pageable resident page falls into one of three lists: ! 193: * ! 194: * free ! 195: * Available for allocation now. ! 196: * inactive ! 197: * Not referenced in any map, but still has an ! 198: * object/offset-page mapping, and may be dirty. ! 199: * This is the list of pages that should be ! 200: * paged out next. ! 201: * active ! 202: * A list of pages which have been placed in ! 203: * at least one physical map. This list is ! 204: * ordered, in LRU-like fashion. ! 205: */ ! 206: ! 207: extern ! 208: vm_page_t vm_page_queue_free; /* memory free queue */ ! 209: extern ! 210: vm_page_t vm_page_queue_fictitious; /* fictitious free queue */ ! 211: extern ! 212: queue_head_t vm_page_queue_active; /* active memory queue */ ! 213: extern ! 214: queue_head_t vm_page_queue_inactive; /* inactive memory queue */ ! 215: ! 216: extern ! 217: vm_offset_t first_phys_addr; /* physical address for first_page */ ! 218: extern ! 219: vm_offset_t last_phys_addr; /* physical address for last_page */ ! 220: ! 221: extern ! 222: int vm_page_free_count; /* How many pages are free? */ ! 223: extern ! 224: int vm_page_fictitious_count;/* How many fictitious pages are free? */ ! 225: extern ! 226: int vm_page_active_count; /* How many pages are active? */ ! 227: extern ! 228: int vm_page_inactive_count; /* How many pages are inactive? */ ! 229: extern ! 230: int vm_page_wire_count; /* How many pages are wired? */ ! 231: extern ! 232: int vm_page_free_target; /* How many do we want free? */ ! 233: extern ! 234: int vm_page_free_min; /* When to wakeup pageout */ ! 235: extern ! 236: int vm_page_inactive_target;/* How many do we want inactive? */ ! 237: extern ! 238: int vm_page_free_reserved; /* How many pages reserved to do pageout */ ! 239: extern ! 240: int vm_page_laundry_count; /* How many pages being laundered? */ ! 241: ! 242: decl_mutex_data(,vm_page_queue_lock) ! 243: /* lock on active and inactive page queues */ ! 244: decl_mutex_data(,vm_page_queue_free_lock) ! 245: /* lock on free page queue */ ! 246: decl_simple_lock_data(extern,vm_page_preppin_lock) /* lock for prep/pin */ ! 247: ! 248: extern unsigned int vm_page_free_wanted; ! 249: /* how many threads are waiting for memory */ ! 250: ! 251: extern vm_offset_t vm_page_fictitious_addr; ! 252: /* (fake) phys_addr of fictitious pages */ ! 253: ! 254: /* ! 255: * Prototypes for functions exported by this module. ! 256: */ ! 257: extern void vm_page_bootstrap( ! 258: vm_offset_t *startp, ! 259: vm_offset_t *endp); ! 260: ! 261: extern void vm_page_module_init(void); ! 262: ! 263: extern void vm_page_create( ! 264: vm_offset_t start, ! 265: vm_offset_t end); ! 266: ! 267: extern vm_page_t vm_page_lookup( ! 268: vm_object_t object, ! 269: vm_offset_t offset); ! 270: ! 271: extern vm_page_t vm_page_grab_fictitious(void); ! 272: ! 273: extern void vm_page_release_fictitious( ! 274: vm_page_t page); ! 275: ! 276: extern boolean_t vm_page_convert( ! 277: vm_page_t page); ! 278: ! 279: extern void vm_page_more_fictitious(void); ! 280: ! 281: extern int vm_pool_low(void); ! 282: ! 283: extern vm_page_t vm_page_grab(void); ! 284: ! 285: extern void vm_page_release( ! 286: vm_page_t page); ! 287: ! 288: extern void vm_page_release_limbo( ! 289: vm_page_t page); ! 290: ! 291: extern void vm_page_limbo_exchange( ! 292: vm_page_t limbo_m, ! 293: vm_page_t new_m); ! 294: ! 295: extern void vm_page_wait( void ); ! 296: ! 297: extern vm_page_t vm_page_alloc( ! 298: vm_object_t object, ! 299: vm_offset_t offset); ! 300: ! 301: extern void vm_page_init( ! 302: vm_page_t page, ! 303: vm_offset_t phys_addr); ! 304: ! 305: extern void vm_page_free( ! 306: vm_page_t page); ! 307: ! 308: extern void vm_page_activate( ! 309: vm_page_t page); ! 310: ! 311: extern void vm_page_deactivate( ! 312: vm_page_t page); ! 313: ! 314: extern void vm_page_rename( ! 315: vm_page_t page, ! 316: vm_object_t new_object, ! 317: vm_offset_t new_offset); ! 318: ! 319: extern void vm_page_insert( ! 320: vm_page_t page, ! 321: vm_object_t object, ! 322: vm_offset_t offset); ! 323: ! 324: extern void vm_page_replace( ! 325: vm_page_t mem, ! 326: vm_object_t object, ! 327: vm_offset_t offset); ! 328: ! 329: extern void vm_page_remove( ! 330: vm_page_t page); ! 331: ! 332: extern void vm_page_zero_fill( ! 333: vm_page_t page); ! 334: ! 335: extern void vm_page_part_zero_fill( ! 336: vm_page_t m, ! 337: vm_offset_t m_pa, ! 338: vm_size_t len); ! 339: ! 340: extern void vm_page_copy( ! 341: vm_page_t src_page, ! 342: vm_page_t dest_page); ! 343: ! 344: extern void vm_page_part_copy( ! 345: vm_page_t src_m, ! 346: vm_offset_t src_pa, ! 347: vm_page_t dst_m, ! 348: vm_offset_t dst_pa, ! 349: vm_size_t len); ! 350: ! 351: extern void vm_page_wire( ! 352: vm_page_t page); ! 353: ! 354: extern void vm_page_unwire( ! 355: vm_page_t page); ! 356: ! 357: extern void vm_set_page_size(void); ! 358: ! 359: extern void vm_page_gobble( ! 360: vm_page_t page); ! 361: ! 362: extern kern_return_t vm_page_prep( ! 363: vm_page_t m); ! 364: ! 365: extern kern_return_t vm_page_pin( ! 366: vm_page_t m); ! 367: ! 368: extern kern_return_t vm_page_unprep( ! 369: vm_page_t m); ! 370: ! 371: extern kern_return_t vm_page_unpin( ! 372: vm_page_t m); ! 373: ! 374: extern void cleanup_limbo_queue(void); ! 375: ! 376: /* ! 377: * Functions implemented as macros. m->wanted and m->busy are ! 378: * protected by the object lock. ! 379: */ ! 380: ! 381: #define PAGE_ASSERT_WAIT(m, interruptible) \ ! 382: MACRO_BEGIN \ ! 383: (m)->wanted = TRUE; \ ! 384: assert_wait((event_t) (m), (interruptible)); \ ! 385: MACRO_END ! 386: ! 387: #define PAGE_WAKEUP_DONE(m) \ ! 388: MACRO_BEGIN \ ! 389: (m)->busy = FALSE; \ ! 390: if ((m)->wanted) { \ ! 391: (m)->wanted = FALSE; \ ! 392: thread_wakeup((event_t) (m)); \ ! 393: } \ ! 394: MACRO_END ! 395: ! 396: #define PAGE_WAKEUP(m) \ ! 397: MACRO_BEGIN \ ! 398: if ((m)->wanted) { \ ! 399: (m)->wanted = FALSE; \ ! 400: thread_wakeup((event_t) (m)); \ ! 401: } \ ! 402: MACRO_END ! 403: ! 404: #define VM_PAGE_FREE(p) \ ! 405: MACRO_BEGIN \ ! 406: vm_page_lock_queues(); \ ! 407: vm_page_free(p); \ ! 408: vm_page_unlock_queues(); \ ! 409: MACRO_END ! 410: ! 411: #define VM_PAGE_GRAB_FICTITIOUS(M) \ ! 412: MACRO_BEGIN \ ! 413: while ((M = vm_page_grab_fictitious()) == VM_PAGE_NULL) \ ! 414: vm_page_more_fictitious(); \ ! 415: MACRO_END ! 416: ! 417: #define VM_PAGE_WAIT() vm_page_wait() ! 418: ! 419: #define vm_page_lock_queues() mutex_lock(&vm_page_queue_lock) ! 420: #define vm_page_unlock_queues() mutex_unlock(&vm_page_queue_lock) ! 421: #define vm_page_pin_lock() simple_lock(&vm_page_preppin_lock) ! 422: #define vm_page_pin_unlock() simple_unlock(&vm_page_preppin_lock) ! 423: ! 424: #define VM_PAGE_QUEUES_REMOVE(mem) \ ! 425: MACRO_BEGIN \ ! 426: if (mem->active) { \ ! 427: assert(!mem->inactive); \ ! 428: queue_remove(&vm_page_queue_active, \ ! 429: mem, vm_page_t, pageq); \ ! 430: mem->active = FALSE; \ ! 431: if (!mem->fictitious) \ ! 432: vm_page_active_count--; \ ! 433: } \ ! 434: \ ! 435: if (mem->inactive) { \ ! 436: assert(!mem->active); \ ! 437: queue_remove(&vm_page_queue_inactive, \ ! 438: mem, vm_page_t, pageq); \ ! 439: mem->inactive = FALSE; \ ! 440: if (!mem->fictitious) \ ! 441: vm_page_inactive_count--; \ ! 442: } \ ! 443: MACRO_END ! 444: ! 445: /* ! 446: * Data structure for automatic physical memory reservation. Declared ! 447: * here, defined in vm_resident.c. ! 448: * ! 449: * The following data structure is used to specify contiguous ranges ! 450: * of physical memory that should be allocated before virtual memory ! 451: * initialization. Each element is a pair of addresses--the address ! 452: * of the size of the chunk that should be allocated, the second the ! 453: * location at which to place the pointer to that section when it is ! 454: * allocated. ! 455: * ! 456: * The actual mechanism for allocating the contiguous physical memory ! 457: * is machine dependent, and occurs during the machine dependent VM ! 458: * initialization. ! 459: * ! 460: * This is defined as a pointer rather than a dimensionless array ! 461: * because the PGI (intel 860) compiler can't handle dimensionless ! 462: * arrays. ! 463: */ ! 464: ! 465: extern struct pmem_reserve { ! 466: unsigned long *pmem_size; /* In */ ! 467: vm_offset_t *pmem_addr; /* Out */ ! 468: } *pmem_reserve_ctl; ! 469: ! 470: extern int pmem_reserve_ctl_size; ! 471: ! 472: #endif /* _VM_VM_PAGE_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.