|
|
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,1987 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_object.h ! 54: * Author: Avadis Tevanian, Jr., Michael Wayne Young ! 55: * Date: 1985 ! 56: * ! 57: * Virtual memory object module definitions. ! 58: */ ! 59: ! 60: #ifndef _VM_VM_OBJECT_H_ ! 61: #define _VM_VM_OBJECT_H_ ! 62: ! 63: #include <mach_pagemap.h> ! 64: #include <task_swapper.h> ! 65: ! 66: #include <mach/kern_return.h> ! 67: #include <mach/boolean.h> ! 68: #include <mach/memory_object_types.h> ! 69: #include <mach/port.h> ! 70: #include <mach/vm_prot.h> ! 71: #include <mach/machine/vm_types.h> ! 72: #include <kern/queue.h> ! 73: #include <kern/lock.h> ! 74: #include <kern/assert.h> ! 75: #include <kern/macro_help.h> ! 76: #include <ipc/ipc_types.h> ! 77: #include <vm/pmap.h> ! 78: #include <kern/misc_protos.h> ! 79: ! 80: #if MACH_PAGEMAP ! 81: #include <vm/vm_external.h> ! 82: #endif /* MACH_PAGEMAP */ ! 83: ! 84: typedef struct ipc_port * pager_request_t; ! 85: #define PAGER_REQUEST_NULL ((pager_request_t) 0) ! 86: ! 87: /* ! 88: * Types defined: ! 89: * ! 90: * vm_object_t Virtual memory object. ! 91: * ! 92: * We use "struct ipc_port *" instead of "ipc_port_t" ! 93: * to avoid include file circularities. ! 94: */ ! 95: ! 96: struct vm_object { ! 97: queue_head_t memq; /* Resident memory */ ! 98: decl_mutex_data(, Lock) /* Synchronization */ ! 99: ! 100: vm_size_t size; /* Object size (only valid ! 101: * if internal) ! 102: */ ! 103: vm_size_t frozen_size; /* How much has been marked ! 104: * copy-on-write (only ! 105: * valid if copy_symmetric) ! 106: */ ! 107: int ref_count; /* Number of references */ ! 108: #if TASK_SWAPPER ! 109: int res_count; /* Residency references (swap)*/ ! 110: #endif /* TASK_SWAPPER */ ! 111: unsigned int resident_page_count; ! 112: /* number of resident pages */ ! 113: ! 114: struct vm_object *copy; /* Object that should receive ! 115: * a copy of my changed pages, ! 116: * for copy_delay, or just the ! 117: * temporary object that ! 118: * shadows this object, for ! 119: * copy_call. ! 120: */ ! 121: struct vm_object *shadow; /* My shadow */ ! 122: vm_offset_t shadow_offset; /* Offset into shadow */ ! 123: ! 124: struct ipc_port *pager; /* Where to get data */ ! 125: vm_offset_t paging_offset; /* Offset into memory object */ ! 126: pager_request_t pager_request; /* Where data comes back */ ! 127: ! 128: memory_object_copy_strategy_t ! 129: copy_strategy; /* How to handle data copy */ ! 130: ! 131: unsigned int absent_count; /* The number of pages that ! 132: * have been requested but ! 133: * not filled. That is, the ! 134: * number of pages for which ! 135: * the "absent" attribute is ! 136: * asserted. ! 137: */ ! 138: ! 139: unsigned int paging_in_progress; ! 140: /* The memory object ports are ! 141: * being used (e.g., for pagein ! 142: * or pageout) -- don't change ! 143: * any of these fields (i.e., ! 144: * don't collapse, destroy or ! 145: * terminate) ! 146: */ ! 147: unsigned int ! 148: /* boolean_t array */ all_wanted:11, /* Bit array of "want to be ! 149: * awakened" notations. See ! 150: * VM_OBJECT_EVENT_* items ! 151: * below */ ! 152: /* boolean_t */ pager_created:1, /* Has pager been created? */ ! 153: /* boolean_t */ pager_initialized:1, /* Are fields ready to use? */ ! 154: /* boolean_t */ pager_ready:1, /* Will pager take requests? */ ! 155: ! 156: /* boolean_t */ pager_trusted:1,/* The pager for this object ! 157: * is trusted. This is true for ! 158: * all internal objects (backed ! 159: * by the default pager) ! 160: */ ! 161: /* boolean_t */ can_persist:1, /* The kernel may keep the data ! 162: * for this object (and rights ! 163: * to the memory object) after ! 164: * all address map references ! 165: * are deallocated? ! 166: */ ! 167: /* boolean_t */ internal:1, /* Created by the kernel (and ! 168: * therefore, managed by the ! 169: * default memory manger) ! 170: */ ! 171: /* boolean_t */ temporary:1, /* Permanent objects may be ! 172: * changed externally by the ! 173: * memory manager, and changes ! 174: * made in memory must be ! 175: * reflected back to the memory ! 176: * manager. Temporary objects ! 177: * lack both of these ! 178: * characteristics. ! 179: */ ! 180: /* boolean_t */ private:1, /* magic device_pager object, ! 181: * holds private pages only */ ! 182: /* boolean_t */ pageout:1, /* pageout object. contains ! 183: * private pages that refer to ! 184: * a real memory object. */ ! 185: /* boolean_t */ alive:1, /* Not yet terminated */ ! 186: ! 187: /* boolean_t */ lock_in_progress:1, ! 188: /* Is a multi-page lock ! 189: * request in progress? ! 190: */ ! 191: /* boolean_t */ lock_restart:1, ! 192: /* Should lock request in ! 193: * progress restart search? ! 194: */ ! 195: /* boolean_t */ shadowed:1, /* Shadow may exist */ ! 196: /* boolean_t */ silent_overwrite:1, ! 197: /* Allow full page overwrite ! 198: * without data_request if ! 199: * page is absent */ ! 200: /* boolean_t */ advisory_pageout:1, ! 201: /* Instead of sending page ! 202: * via OOL, just notify ! 203: * pager that the kernel ! 204: * wants to discard it, page ! 205: * remains in object */ ! 206: /* boolean_t */ true_share:1; ! 207: /* This object is mapped ! 208: * in more than one place ! 209: * and hence cannot be ! 210: * coalesced */ ! 211: ! 212: ! 213: queue_chain_t cached_list; /* Attachment point for the ! 214: * list of objects cached as a ! 215: * result of their can_persist ! 216: * value ! 217: */ ! 218: ! 219: queue_head_t msr_q; /* memory object synchronise ! 220: request queue */ ! 221: ! 222: vm_offset_t last_alloc; /* last allocation offset */ ! 223: vm_size_t cluster_size; /* size of paging cluster */ ! 224: #if MACH_PAGEMAP ! 225: vm_external_map_t existence_map; /* bitmap of pages written to ! 226: * backing storage */ ! 227: #endif /* MACH_PAGEMAP */ ! 228: #if MACH_ASSERT ! 229: struct vm_object *paging_object; /* object which pages to be ! 230: * swapped out are temporary ! 231: * put in current object ! 232: */ ! 233: #endif ! 234: }; ! 235: ! 236: extern ! 237: vm_object_t kernel_object; /* the single kernel object */ ! 238: ! 239: int vm_object_absent_max; /* maximum number of absent pages ! 240: at a time for each object */ ! 241: ! 242: # define VM_MSYNC_INITIALIZED 0 ! 243: # define VM_MSYNC_SYNCHRONIZING 1 ! 244: # define VM_MSYNC_DONE 2 ! 245: ! 246: struct msync_req { ! 247: queue_chain_t msr_q; /* object request queue */ ! 248: queue_chain_t req_q; /* vm_msync request queue */ ! 249: unsigned int flag; ! 250: vm_offset_t offset; ! 251: vm_offset_t length; ! 252: vm_object_t object; /* back pointer */ ! 253: decl_mutex_data(, msync_req_lock) /* Lock for this structure */ ! 254: }; ! 255: ! 256: typedef struct msync_req *msync_req_t; ! 257: #define MSYNC_REQ_NULL ((msync_req_t) 0) ! 258: ! 259: /* ! 260: * Macros to allocate and free msync_reqs ! 261: */ ! 262: #define msync_req_alloc(msr) \ ! 263: MACRO_BEGIN \ ! 264: (msr) = (msync_req_t)kalloc(sizeof(struct msync_req)); \ ! 265: mutex_init(&(msr)->msync_req_lock, ETAP_VM_MSYNC); \ ! 266: msr->flag = VM_MSYNC_INITIALIZED; \ ! 267: MACRO_END ! 268: ! 269: #define msync_req_free(msr) \ ! 270: (kfree((vm_offset_t)(msr), sizeof(struct msync_req))) ! 271: ! 272: #define msr_lock(msr) mutex_lock(&(msr)->msync_req_lock) ! 273: #define msr_unlock(msr) mutex_unlock(&(msr)->msync_req_lock) ! 274: ! 275: /* ! 276: * Declare procedures that operate on VM objects. ! 277: */ ! 278: ! 279: extern void vm_object_bootstrap(void); ! 280: ! 281: extern void vm_object_init(void); ! 282: ! 283: extern vm_object_t vm_object_allocate( ! 284: vm_size_t size); ! 285: ! 286: #if MACH_ASSERT ! 287: extern void vm_object_reference( ! 288: vm_object_t object); ! 289: #else /* MACH_ASSERT */ ! 290: #define vm_object_reference(object) \ ! 291: MACRO_BEGIN \ ! 292: vm_object_t Object = (object); \ ! 293: if (Object) { \ ! 294: vm_object_lock(Object); \ ! 295: Object->ref_count++; \ ! 296: vm_object_res_reference(Object); \ ! 297: vm_object_unlock(Object); \ ! 298: } \ ! 299: MACRO_END ! 300: #endif /* MACH_ASSERT */ ! 301: ! 302: extern void vm_object_deallocate( ! 303: vm_object_t object); ! 304: ! 305: extern void vm_object_pmap_protect( ! 306: vm_object_t object, ! 307: vm_offset_t offset, ! 308: vm_offset_t size, ! 309: pmap_t pmap, ! 310: vm_offset_t pmap_start, ! 311: vm_prot_t prot); ! 312: ! 313: extern void vm_object_page_remove( ! 314: vm_object_t object, ! 315: vm_offset_t start, ! 316: vm_offset_t end); ! 317: ! 318: extern boolean_t vm_object_coalesce( ! 319: vm_object_t prev_object, ! 320: vm_object_t next_object, ! 321: vm_offset_t prev_offset, ! 322: vm_offset_t next_offset, ! 323: vm_size_t prev_size, ! 324: vm_size_t next_size); ! 325: ! 326: extern boolean_t vm_object_shadow( ! 327: vm_object_t *object, ! 328: vm_offset_t *offset, ! 329: vm_size_t length); ! 330: ! 331: extern void vm_object_collapse( ! 332: vm_object_t object); ! 333: ! 334: extern vm_object_t vm_object_lookup( ! 335: ipc_port_t port); ! 336: ! 337: extern ipc_port_t vm_object_name( ! 338: vm_object_t object); ! 339: ! 340: extern boolean_t vm_object_copy_quickly( ! 341: vm_object_t *_object, ! 342: vm_offset_t src_offset, ! 343: vm_size_t size, ! 344: boolean_t *_src_needs_copy, ! 345: boolean_t *_dst_needs_copy); ! 346: ! 347: extern kern_return_t vm_object_copy_strategically( ! 348: vm_object_t src_object, ! 349: vm_offset_t src_offset, ! 350: vm_size_t size, ! 351: vm_object_t *dst_object, ! 352: vm_offset_t *dst_offset, ! 353: boolean_t *dst_needs_copy); ! 354: ! 355: extern kern_return_t vm_object_copy_slowly( ! 356: vm_object_t src_object, ! 357: vm_offset_t src_offset, ! 358: vm_size_t size, ! 359: boolean_t interruptible, ! 360: vm_object_t *_result_object); ! 361: ! 362: extern void vm_object_pager_create( ! 363: vm_object_t object); ! 364: ! 365: extern void vm_object_destroy( ! 366: ipc_port_t pager); ! 367: ! 368: extern void vm_object_pager_wakeup( ! 369: ipc_port_t pager); ! 370: ! 371: extern void vm_object_page_map( ! 372: vm_object_t object, ! 373: vm_offset_t offset, ! 374: vm_size_t size, ! 375: vm_offset_t (*map_fn) ! 376: (void *, vm_offset_t), ! 377: void *map_fn_data); ! 378: ! 379: #if TASK_SWAPPER ! 380: ! 381: extern void vm_object_res_reference( ! 382: vm_object_t object); ! 383: extern void vm_object_res_deallocate( ! 384: vm_object_t object); ! 385: #define VM_OBJ_RES_INCR(object) (object)->res_count++ ! 386: #define VM_OBJ_RES_DECR(object) (object)->res_count-- ! 387: ! 388: #else /* TASK_SWAPPER */ ! 389: ! 390: #define VM_OBJ_RES_INCR(object) ! 391: #define VM_OBJ_RES_DECR(object) ! 392: #define vm_object_res_reference(object) ! 393: #define vm_object_res_deallocate(object) ! 394: ! 395: #endif /* TASK_SWAPPER */ ! 396: ! 397: extern vm_object_t vm_object_enter( ! 398: ipc_port_t pager, ! 399: vm_size_t size, ! 400: boolean_t internal, ! 401: boolean_t init); ! 402: ! 403: ! 404: extern vm_object_t vm_object_copy_delayed( ! 405: vm_object_t src_object, ! 406: vm_offset_t src_offset, ! 407: vm_size_t size); ! 408: ! 409: ! 410: /* ! 411: * Event waiting handling ! 412: */ ! 413: ! 414: #define VM_OBJECT_EVENT_INITIALIZED 0 ! 415: #define VM_OBJECT_EVENT_PAGER_READY 1 ! 416: #define VM_OBJECT_EVENT_PAGING_IN_PROGRESS 2 ! 417: #define VM_OBJECT_EVENT_ABSENT_COUNT 3 ! 418: #define VM_OBJECT_EVENT_LOCK_IN_PROGRESS 4 ! 419: #define VM_OBJECT_EVENT_UNCACHING 5 ! 420: #define VM_OBJECT_EVENT_COPY_CALL 6 ! 421: #define VM_OBJECT_EVENT_CACHING 7 ! 422: ! 423: #define vm_object_assert_wait(object, event, interruptible) \ ! 424: MACRO_BEGIN \ ! 425: (object)->all_wanted |= 1 << (event); \ ! 426: assert_wait((event_t)((vm_offset_t)(object)+(event)),(interruptible)); \ ! 427: MACRO_END ! 428: ! 429: #define vm_object_wait(object, event, interruptible) \ ! 430: MACRO_BEGIN \ ! 431: vm_object_assert_wait((object),(event),(interruptible)); \ ! 432: vm_object_unlock(object); \ ! 433: thread_block((void (*)(void)) 0); \ ! 434: MACRO_END ! 435: ! 436: #define vm_object_wakeup(object, event) \ ! 437: MACRO_BEGIN \ ! 438: if ((object)->all_wanted & (1 << (event))) \ ! 439: thread_wakeup((event_t)((vm_offset_t)(object) + (event))); \ ! 440: (object)->all_wanted &= ~(1 << (event)); \ ! 441: MACRO_END ! 442: ! 443: #define vm_object_set_wanted(object, event) \ ! 444: MACRO_BEGIN \ ! 445: ((object)->all_wanted |= (1 << (event))); \ ! 446: MACRO_END ! 447: ! 448: #define vm_object_wanted(object, event) \ ! 449: ((object)->all_wanted & (1 << (event))) ! 450: ! 451: /* ! 452: * Routines implemented as macros ! 453: */ ! 454: ! 455: #define vm_object_paging_begin(object) \ ! 456: MACRO_BEGIN \ ! 457: (object)->paging_in_progress++; \ ! 458: MACRO_END ! 459: ! 460: #define vm_object_paging_end(object) \ ! 461: MACRO_BEGIN \ ! 462: assert((object)->paging_in_progress != 0); \ ! 463: if (--(object)->paging_in_progress == 0) { \ ! 464: vm_object_wakeup(object, \ ! 465: VM_OBJECT_EVENT_PAGING_IN_PROGRESS); \ ! 466: } \ ! 467: MACRO_END ! 468: ! 469: #define vm_object_paging_wait(object, interruptible) \ ! 470: MACRO_BEGIN \ ! 471: while ((object)->paging_in_progress != 0) { \ ! 472: vm_object_wait( (object), \ ! 473: VM_OBJECT_EVENT_PAGING_IN_PROGRESS, \ ! 474: (interruptible)); \ ! 475: vm_object_lock(object); \ ! 476: \ ! 477: /*XXX if ((interruptible) && */ \ ! 478: /*XXX (current_thread()->wait_result != THREAD_AWAKENED))*/ \ ! 479: /*XXX break; */ \ ! 480: } \ ! 481: MACRO_END ! 482: ! 483: #define vm_object_absent_assert_wait(object, interruptible) \ ! 484: MACRO_BEGIN \ ! 485: vm_object_assert_wait( (object), \ ! 486: VM_OBJECT_EVENT_ABSENT_COUNT, \ ! 487: (interruptible)); \ ! 488: MACRO_END ! 489: ! 490: ! 491: #define vm_object_absent_release(object) \ ! 492: MACRO_BEGIN \ ! 493: (object)->absent_count--; \ ! 494: vm_object_wakeup((object), \ ! 495: VM_OBJECT_EVENT_ABSENT_COUNT); \ ! 496: MACRO_END ! 497: ! 498: /* ! 499: * Object locking macros ! 500: */ ! 501: ! 502: #define vm_object_lock_init(object) mutex_init(&(object)->Lock, ETAP_VM_OBJ) ! 503: #define vm_object_lock(object) mutex_lock(&(object)->Lock) ! 504: #define vm_object_unlock(object) mutex_unlock(&(object)->Lock) ! 505: #define vm_object_lock_try(object) mutex_try(&(object)->Lock) ! 506: ! 507: #endif /* _VM_VM_OBJECT_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.