|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1991 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * The Mach Operating System project at Carnegie-Mellon University. ! 7: * ! 8: * Redistribution and use in source and binary forms, with or without ! 9: * modification, are permitted provided that the following conditions ! 10: * are met: ! 11: * 1. Redistributions of source code must retain the above copyright ! 12: * notice, this list of conditions and the following disclaimer. ! 13: * 2. Redistributions in binary form must reproduce the above copyright ! 14: * notice, this list of conditions and the following disclaimer in the ! 15: * documentation and/or other materials provided with the distribution. ! 16: * 3. All advertising materials mentioning features or use of this software ! 17: * must display the following acknowledgement: ! 18: * This product includes software developed by the University of ! 19: * California, Berkeley and its contributors. ! 20: * 4. Neither the name of the University nor the names of its contributors ! 21: * may be used to endorse or promote products derived from this software ! 22: * without specific prior written permission. ! 23: * ! 24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 34: * SUCH DAMAGE. ! 35: * ! 36: * @(#)vm_page.c 7.4 (Berkeley) 5/7/91 ! 37: * ! 38: * ! 39: * Copyright (c) 1987, 1990 Carnegie-Mellon University. ! 40: * All rights reserved. ! 41: * ! 42: * Authors: Avadis Tevanian, Jr., Michael Wayne Young ! 43: * ! 44: * Permission to use, copy, modify and distribute this software and ! 45: * its documentation is hereby granted, provided that both the copyright ! 46: * notice and this permission notice appear in all copies of the ! 47: * software, derivative works or modified versions, and any portions ! 48: * thereof, and that both notices appear in supporting documentation. ! 49: * ! 50: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 51: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND ! 52: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 53: * ! 54: * Carnegie Mellon requests users of this software to return to ! 55: * ! 56: * Software Distribution Coordinator or [email protected] ! 57: * School of Computer Science ! 58: * Carnegie Mellon University ! 59: * Pittsburgh PA 15213-3890 ! 60: * ! 61: * any improvements or extensions that they make and grant Carnegie the ! 62: * rights to redistribute these changes. ! 63: */ ! 64: ! 65: /* ! 66: * Resident memory management module. ! 67: */ ! 68: ! 69: #include "param.h" ! 70: ! 71: #include "vm.h" ! 72: #include "vm_map.h" ! 73: #include "vm_page.h" ! 74: #include "vm_pageout.h" ! 75: ! 76: /* ! 77: * Associated with page of user-allocatable memory is a ! 78: * page structure. ! 79: */ ! 80: ! 81: queue_head_t *vm_page_buckets; /* Array of buckets */ ! 82: int vm_page_bucket_count = 0; /* How big is array? */ ! 83: int vm_page_hash_mask; /* Mask for hash function */ ! 84: simple_lock_data_t bucket_lock; /* lock for all buckets XXX */ ! 85: ! 86: vm_size_t page_size = 4096; ! 87: vm_size_t page_mask = 4095; ! 88: int page_shift = 12; ! 89: ! 90: queue_head_t vm_page_queue_free; ! 91: queue_head_t vm_page_queue_active; ! 92: queue_head_t vm_page_queue_inactive; ! 93: simple_lock_data_t vm_page_queue_lock; ! 94: simple_lock_data_t vm_page_queue_free_lock; ! 95: ! 96: vm_page_t vm_page_array; ! 97: long first_page; ! 98: long last_page; ! 99: vm_offset_t first_phys_addr; ! 100: vm_offset_t last_phys_addr; ! 101: ! 102: int vm_page_free_count; ! 103: int vm_page_active_count; ! 104: int vm_page_inactive_count; ! 105: int vm_page_wire_count; ! 106: int vm_page_laundry_count; ! 107: ! 108: int vm_page_free_target = 0; ! 109: int vm_page_free_min = 0; ! 110: int vm_page_inactive_target = 0; ! 111: int vm_page_free_reserved = 0; ! 112: ! 113: /* ! 114: * vm_set_page_size: ! 115: * ! 116: * Sets the page size, perhaps based upon the memory ! 117: * size. Must be called before any use of page-size ! 118: * dependent functions. ! 119: * ! 120: * Sets page_shift and page_mask from page_size. ! 121: */ ! 122: void vm_set_page_size() ! 123: { ! 124: page_mask = page_size - 1; ! 125: ! 126: if ((page_mask & page_size) != 0) ! 127: panic("vm_set_page_size: page size not a power of two"); ! 128: ! 129: for (page_shift = 0; ; page_shift++) ! 130: if ((1 << page_shift) == page_size) ! 131: break; ! 132: } ! 133: ! 134: ! 135: /* ! 136: * vm_page_startup: ! 137: * ! 138: * Initializes the resident memory module. ! 139: * ! 140: * Allocates memory for the page cells, and ! 141: * for the object/offset-to-page hash table headers. ! 142: * Each page cell is initialized and placed on the free list. ! 143: */ ! 144: vm_offset_t vm_page_startup(start, end, vaddr) ! 145: register vm_offset_t start; ! 146: vm_offset_t end; ! 147: register vm_offset_t vaddr; ! 148: { ! 149: register vm_offset_t mapped; ! 150: register vm_page_t m; ! 151: register queue_t bucket; ! 152: vm_size_t npages; ! 153: register vm_offset_t new_start; ! 154: int i; ! 155: vm_offset_t pa; ! 156: ! 157: extern vm_offset_t kentry_data; ! 158: extern vm_size_t kentry_data_size; ! 159: ! 160: ! 161: /* ! 162: * Initialize the locks ! 163: */ ! 164: ! 165: simple_lock_init(&vm_page_queue_free_lock); ! 166: simple_lock_init(&vm_page_queue_lock); ! 167: ! 168: /* ! 169: * Initialize the queue headers for the free queue, ! 170: * the active queue and the inactive queue. ! 171: */ ! 172: ! 173: queue_init(&vm_page_queue_free); ! 174: queue_init(&vm_page_queue_active); ! 175: queue_init(&vm_page_queue_inactive); ! 176: ! 177: /* ! 178: * Allocate (and initialize) the hash table buckets. ! 179: * ! 180: * The number of buckets MUST BE a power of 2, and ! 181: * the actual value is the next power of 2 greater ! 182: * than the number of physical pages in the system. ! 183: * ! 184: * Note: ! 185: * This computation can be tweaked if desired. ! 186: */ ! 187: ! 188: vm_page_buckets = (queue_t) vaddr; ! 189: bucket = vm_page_buckets; ! 190: if (vm_page_bucket_count == 0) { ! 191: vm_page_bucket_count = 1; ! 192: while (vm_page_bucket_count < atop(end - start)) ! 193: vm_page_bucket_count <<= 1; ! 194: } ! 195: ! 196: vm_page_hash_mask = vm_page_bucket_count - 1; ! 197: ! 198: /* ! 199: * Validate these addresses. ! 200: */ ! 201: ! 202: new_start = round_page(((queue_t)start) + vm_page_bucket_count); ! 203: mapped = vaddr; ! 204: vaddr = pmap_map(mapped, start, new_start, ! 205: VM_PROT_READ|VM_PROT_WRITE); ! 206: start = new_start; ! 207: blkclr((caddr_t) mapped, vaddr - mapped); ! 208: mapped = vaddr; ! 209: ! 210: for (i = vm_page_bucket_count; i--;) { ! 211: queue_init(bucket); ! 212: bucket++; ! 213: } ! 214: ! 215: simple_lock_init(&bucket_lock); ! 216: ! 217: /* ! 218: * round (or truncate) the addresses to our page size. ! 219: */ ! 220: ! 221: end = trunc_page(end); ! 222: ! 223: /* ! 224: * Pre-allocate maps and map entries that cannot be dynamically ! 225: * allocated via malloc(). The maps include the kernel_map and ! 226: * kmem_map which must be initialized before malloc() will ! 227: * work (obviously). Also could include pager maps which would ! 228: * be allocated before kmeminit. ! 229: * ! 230: * Allow some kernel map entries... this should be plenty ! 231: * since people shouldn't be cluttering up the kernel ! 232: * map (they should use their own maps). ! 233: */ ! 234: ! 235: kentry_data_size = MAX_KMAP * sizeof(struct vm_map) + ! 236: MAX_KMAPENT * sizeof(struct vm_map_entry); ! 237: kentry_data_size = round_page(kentry_data_size); ! 238: kentry_data = (vm_offset_t) vaddr; ! 239: vaddr += kentry_data_size; ! 240: ! 241: /* ! 242: * Validate these zone addresses. ! 243: */ ! 244: ! 245: new_start = start + (vaddr - mapped); ! 246: pmap_map(mapped, start, new_start, VM_PROT_READ|VM_PROT_WRITE); ! 247: blkclr((caddr_t) mapped, (vaddr - mapped)); ! 248: mapped = vaddr; ! 249: start = new_start; ! 250: ! 251: /* ! 252: * Compute the number of pages of memory that will be ! 253: * available for use (taking into account the overhead ! 254: * of a page structure per page). ! 255: */ ! 256: ! 257: vm_page_free_count = npages = ! 258: (end - start)/(PAGE_SIZE + sizeof(struct vm_page)); ! 259: ! 260: /* ! 261: * Initialize the mem entry structures now, and ! 262: * put them in the free queue. ! 263: */ ! 264: ! 265: m = vm_page_array = (vm_page_t) vaddr; ! 266: first_page = start; ! 267: first_page += npages*sizeof(struct vm_page); ! 268: first_page = atop(round_page(first_page)); ! 269: last_page = first_page + npages - 1; ! 270: ! 271: first_phys_addr = ptoa(first_page); ! 272: last_phys_addr = ptoa(last_page) + page_mask; ! 273: ! 274: /* ! 275: * Validate these addresses. ! 276: */ ! 277: ! 278: new_start = start + (round_page(m + npages) - mapped); ! 279: mapped = pmap_map(mapped, start, new_start, ! 280: VM_PROT_READ|VM_PROT_WRITE); ! 281: start = new_start; ! 282: ! 283: /* ! 284: * Clear all of the page structures ! 285: */ ! 286: blkclr((caddr_t)m, npages * sizeof(*m)); ! 287: ! 288: pa = first_phys_addr; ! 289: while (npages--) { ! 290: m->copy_on_write = FALSE; ! 291: m->wanted = FALSE; ! 292: m->inactive = FALSE; ! 293: m->active = FALSE; ! 294: m->busy = FALSE; ! 295: m->object = NULL; ! 296: m->phys_addr = pa; ! 297: queue_enter(&vm_page_queue_free, m, vm_page_t, pageq); ! 298: m++; ! 299: pa += PAGE_SIZE; ! 300: } ! 301: ! 302: /* ! 303: * Initialize vm_pages_needed lock here - don't wait for pageout ! 304: * daemon XXX ! 305: */ ! 306: simple_lock_init(&vm_pages_needed_lock); ! 307: ! 308: return(mapped); ! 309: } ! 310: ! 311: /* ! 312: * vm_page_hash: ! 313: * ! 314: * Distributes the object/offset key pair among hash buckets. ! 315: * ! 316: * NOTE: This macro depends on vm_page_bucket_count being a power of 2. ! 317: */ ! 318: #define vm_page_hash(object, offset) \ ! 319: (((unsigned)object+(unsigned)atop(offset))&vm_page_hash_mask) ! 320: ! 321: /* ! 322: * vm_page_insert: [ internal use only ] ! 323: * ! 324: * Inserts the given mem entry into the object/object-page ! 325: * table and object list. ! 326: * ! 327: * The object and page must be locked. ! 328: */ ! 329: ! 330: void vm_page_insert(mem, object, offset) ! 331: register vm_page_t mem; ! 332: register vm_object_t object; ! 333: register vm_offset_t offset; ! 334: { ! 335: register queue_t bucket; ! 336: int spl; ! 337: ! 338: VM_PAGE_CHECK(mem); ! 339: ! 340: if (mem->tabled) ! 341: panic("vm_page_insert: already inserted"); ! 342: ! 343: /* ! 344: * Record the object/offset pair in this page ! 345: */ ! 346: ! 347: mem->object = object; ! 348: mem->offset = offset; ! 349: ! 350: /* ! 351: * Insert it into the object_object/offset hash table ! 352: */ ! 353: ! 354: bucket = &vm_page_buckets[vm_page_hash(object, offset)]; ! 355: spl = splimp(); ! 356: simple_lock(&bucket_lock); ! 357: queue_enter(bucket, mem, vm_page_t, hashq); ! 358: simple_unlock(&bucket_lock); ! 359: (void) splx(spl); ! 360: ! 361: /* ! 362: * Now link into the object's list of backed pages. ! 363: */ ! 364: ! 365: queue_enter(&object->memq, mem, vm_page_t, listq); ! 366: mem->tabled = TRUE; ! 367: ! 368: /* ! 369: * And show that the object has one more resident ! 370: * page. ! 371: */ ! 372: ! 373: object->resident_page_count++; ! 374: } ! 375: ! 376: /* ! 377: * vm_page_remove: [ internal use only ] ! 378: * ! 379: * Removes the given mem entry from the object/offset-page ! 380: * table and the object page list. ! 381: * ! 382: * The object and page must be locked. ! 383: */ ! 384: ! 385: void vm_page_remove(mem) ! 386: register vm_page_t mem; ! 387: { ! 388: register queue_t bucket; ! 389: int spl; ! 390: ! 391: VM_PAGE_CHECK(mem); ! 392: ! 393: if (!mem->tabled) ! 394: return; ! 395: ! 396: /* ! 397: * Remove from the object_object/offset hash table ! 398: */ ! 399: ! 400: bucket = &vm_page_buckets[vm_page_hash(mem->object, mem->offset)]; ! 401: spl = splimp(); ! 402: simple_lock(&bucket_lock); ! 403: queue_remove(bucket, mem, vm_page_t, hashq); ! 404: simple_unlock(&bucket_lock); ! 405: (void) splx(spl); ! 406: ! 407: /* ! 408: * Now remove from the object's list of backed pages. ! 409: */ ! 410: ! 411: queue_remove(&mem->object->memq, mem, vm_page_t, listq); ! 412: ! 413: /* ! 414: * And show that the object has one fewer resident ! 415: * page. ! 416: */ ! 417: ! 418: mem->object->resident_page_count--; ! 419: ! 420: mem->tabled = FALSE; ! 421: } ! 422: ! 423: /* ! 424: * vm_page_lookup: ! 425: * ! 426: * Returns the page associated with the object/offset ! 427: * pair specified; if none is found, NULL is returned. ! 428: * ! 429: * The object must be locked. No side effects. ! 430: */ ! 431: ! 432: vm_page_t vm_page_lookup(object, offset) ! 433: register vm_object_t object; ! 434: register vm_offset_t offset; ! 435: { ! 436: register vm_page_t mem; ! 437: register queue_t bucket; ! 438: int spl; ! 439: ! 440: /* ! 441: * Search the hash table for this object/offset pair ! 442: */ ! 443: ! 444: bucket = &vm_page_buckets[vm_page_hash(object, offset)]; ! 445: ! 446: spl = splimp(); ! 447: simple_lock(&bucket_lock); ! 448: mem = (vm_page_t) queue_first(bucket); ! 449: while (!queue_end(bucket, (queue_entry_t) mem)) { ! 450: VM_PAGE_CHECK(mem); ! 451: if ((mem->object == object) && (mem->offset == offset)) { ! 452: simple_unlock(&bucket_lock); ! 453: splx(spl); ! 454: return(mem); ! 455: } ! 456: mem = (vm_page_t) queue_next(&mem->hashq); ! 457: } ! 458: ! 459: simple_unlock(&bucket_lock); ! 460: splx(spl); ! 461: return(NULL); ! 462: } ! 463: ! 464: /* ! 465: * vm_page_rename: ! 466: * ! 467: * Move the given memory entry from its ! 468: * current object to the specified target object/offset. ! 469: * ! 470: * The object must be locked. ! 471: */ ! 472: void vm_page_rename(mem, new_object, new_offset) ! 473: register vm_page_t mem; ! 474: register vm_object_t new_object; ! 475: vm_offset_t new_offset; ! 476: { ! 477: if (mem->object == new_object) ! 478: return; ! 479: ! 480: vm_page_lock_queues(); /* keep page from moving out from ! 481: under pageout daemon */ ! 482: vm_page_remove(mem); ! 483: vm_page_insert(mem, new_object, new_offset); ! 484: vm_page_unlock_queues(); ! 485: } ! 486: ! 487: void vm_page_init(mem, object, offset) ! 488: vm_page_t mem; ! 489: vm_object_t object; ! 490: vm_offset_t offset; ! 491: { ! 492: #ifdef DEBUG ! 493: #define vm_page_init(mem, object, offset) {\ ! 494: (mem)->busy = TRUE; \ ! 495: (mem)->tabled = FALSE; \ ! 496: vm_page_insert((mem), (object), (offset)); \ ! 497: (mem)->absent = FALSE; \ ! 498: (mem)->fictitious = FALSE; \ ! 499: (mem)->page_lock = VM_PROT_NONE; \ ! 500: (mem)->unlock_request = VM_PROT_NONE; \ ! 501: (mem)->laundry = FALSE; \ ! 502: (mem)->active = FALSE; \ ! 503: (mem)->inactive = FALSE; \ ! 504: (mem)->wire_count = 0; \ ! 505: (mem)->clean = TRUE; \ ! 506: (mem)->copy_on_write = FALSE; \ ! 507: (mem)->fake = TRUE; \ ! 508: (mem)->pagerowned = FALSE; \ ! 509: (mem)->ptpage = FALSE; \ ! 510: } ! 511: #else ! 512: #define vm_page_init(mem, object, offset) {\ ! 513: (mem)->busy = TRUE; \ ! 514: (mem)->tabled = FALSE; \ ! 515: vm_page_insert((mem), (object), (offset)); \ ! 516: (mem)->absent = FALSE; \ ! 517: (mem)->fictitious = FALSE; \ ! 518: (mem)->page_lock = VM_PROT_NONE; \ ! 519: (mem)->unlock_request = VM_PROT_NONE; \ ! 520: (mem)->laundry = FALSE; \ ! 521: (mem)->active = FALSE; \ ! 522: (mem)->inactive = FALSE; \ ! 523: (mem)->wire_count = 0; \ ! 524: (mem)->clean = TRUE; \ ! 525: (mem)->copy_on_write = FALSE; \ ! 526: (mem)->fake = TRUE; \ ! 527: } ! 528: #endif ! 529: ! 530: vm_page_init(mem, object, offset); ! 531: } ! 532: ! 533: /* ! 534: * vm_page_alloc: ! 535: * ! 536: * Allocate and return a memory cell associated ! 537: * with this VM object/offset pair. ! 538: * ! 539: * Object must be locked. ! 540: */ ! 541: vm_page_t vm_page_alloc(object, offset) ! 542: vm_object_t object; ! 543: vm_offset_t offset; ! 544: { ! 545: register vm_page_t mem; ! 546: int spl; ! 547: ! 548: spl = splimp(); /* XXX */ ! 549: simple_lock(&vm_page_queue_free_lock); ! 550: if (queue_empty(&vm_page_queue_free)) { ! 551: simple_unlock(&vm_page_queue_free_lock); ! 552: splx(spl); ! 553: return(NULL); ! 554: } ! 555: ! 556: queue_remove_first(&vm_page_queue_free, mem, vm_page_t, pageq); ! 557: ! 558: vm_page_free_count--; ! 559: simple_unlock(&vm_page_queue_free_lock); ! 560: splx(spl); ! 561: ! 562: vm_page_init(mem, object, offset); ! 563: ! 564: /* ! 565: * Decide if we should poke the pageout daemon. ! 566: * We do this if the free count is less than the low ! 567: * water mark, or if the free count is less than the high ! 568: * water mark (but above the low water mark) and the inactive ! 569: * count is less than its target. ! 570: * ! 571: * We don't have the counts locked ... if they change a little, ! 572: * it doesn't really matter. ! 573: */ ! 574: ! 575: if ((vm_page_free_count < vm_page_free_min) || ! 576: ((vm_page_free_count < vm_page_free_target) && ! 577: (vm_page_inactive_count < vm_page_inactive_target))) ! 578: thread_wakeup(&vm_pages_needed); ! 579: return(mem); ! 580: } ! 581: ! 582: /* ! 583: * vm_page_free: ! 584: * ! 585: * Returns the given page to the free list, ! 586: * disassociating it with any VM object. ! 587: * ! 588: * Object and page must be locked prior to entry. ! 589: */ ! 590: void vm_page_free(mem) ! 591: register vm_page_t mem; ! 592: { ! 593: vm_page_remove(mem); ! 594: if (mem->active) { ! 595: queue_remove(&vm_page_queue_active, mem, vm_page_t, pageq); ! 596: mem->active = FALSE; ! 597: vm_page_active_count--; ! 598: } ! 599: ! 600: if (mem->inactive) { ! 601: queue_remove(&vm_page_queue_inactive, mem, vm_page_t, pageq); ! 602: mem->inactive = FALSE; ! 603: vm_page_inactive_count--; ! 604: } ! 605: ! 606: if (!mem->fictitious) { ! 607: int spl; ! 608: ! 609: spl = splimp(); ! 610: simple_lock(&vm_page_queue_free_lock); ! 611: queue_enter(&vm_page_queue_free, mem, vm_page_t, pageq); ! 612: ! 613: vm_page_free_count++; ! 614: simple_unlock(&vm_page_queue_free_lock); ! 615: splx(spl); ! 616: } ! 617: } ! 618: ! 619: /* ! 620: * vm_page_wire: ! 621: * ! 622: * Mark this page as wired down by yet ! 623: * another map, removing it from paging queues ! 624: * as necessary. ! 625: * ! 626: * The page queues must be locked. ! 627: */ ! 628: void vm_page_wire(mem) ! 629: register vm_page_t mem; ! 630: { ! 631: VM_PAGE_CHECK(mem); ! 632: ! 633: if (mem->wire_count == 0) { ! 634: if (mem->active) { ! 635: queue_remove(&vm_page_queue_active, mem, vm_page_t, ! 636: pageq); ! 637: vm_page_active_count--; ! 638: mem->active = FALSE; ! 639: } ! 640: if (mem->inactive) { ! 641: queue_remove(&vm_page_queue_inactive, mem, vm_page_t, ! 642: pageq); ! 643: vm_page_inactive_count--; ! 644: mem->inactive = FALSE; ! 645: } ! 646: vm_page_wire_count++; ! 647: } ! 648: mem->wire_count++; ! 649: } ! 650: ! 651: /* ! 652: * vm_page_unwire: ! 653: * ! 654: * Release one wiring of this page, potentially ! 655: * enabling it to be paged again. ! 656: * ! 657: * The page queues must be locked. ! 658: */ ! 659: void vm_page_unwire(mem) ! 660: register vm_page_t mem; ! 661: { ! 662: VM_PAGE_CHECK(mem); ! 663: ! 664: mem->wire_count--; ! 665: if (mem->wire_count == 0) { ! 666: queue_enter(&vm_page_queue_active, mem, vm_page_t, pageq); ! 667: vm_page_active_count++; ! 668: mem->active = TRUE; ! 669: vm_page_wire_count--; ! 670: } ! 671: } ! 672: ! 673: /* ! 674: * vm_page_deactivate: ! 675: * ! 676: * Returns the given page to the inactive list, ! 677: * indicating that no physical maps have access ! 678: * to this page. [Used by the physical mapping system.] ! 679: * ! 680: * The page queues must be locked. ! 681: */ ! 682: void vm_page_deactivate(m) ! 683: register vm_page_t m; ! 684: { ! 685: VM_PAGE_CHECK(m); ! 686: ! 687: /* ! 688: * Only move active pages -- ignore locked or already ! 689: * inactive ones. ! 690: */ ! 691: ! 692: if (m->active) { ! 693: pmap_clear_reference(VM_PAGE_TO_PHYS(m)); ! 694: queue_remove(&vm_page_queue_active, m, vm_page_t, pageq); ! 695: queue_enter(&vm_page_queue_inactive, m, vm_page_t, pageq); ! 696: m->active = FALSE; ! 697: m->inactive = TRUE; ! 698: vm_page_active_count--; ! 699: vm_page_inactive_count++; ! 700: if (pmap_is_modified(VM_PAGE_TO_PHYS(m))) ! 701: m->clean = FALSE; ! 702: m->laundry = !m->clean; ! 703: } ! 704: } ! 705: ! 706: /* ! 707: * vm_page_activate: ! 708: * ! 709: * Put the specified page on the active list (if appropriate). ! 710: * ! 711: * The page queues must be locked. ! 712: */ ! 713: ! 714: void vm_page_activate(m) ! 715: register vm_page_t m; ! 716: { ! 717: VM_PAGE_CHECK(m); ! 718: ! 719: if (m->inactive) { ! 720: queue_remove(&vm_page_queue_inactive, m, vm_page_t, ! 721: pageq); ! 722: vm_page_inactive_count--; ! 723: m->inactive = FALSE; ! 724: } ! 725: if (m->wire_count == 0) { ! 726: if (m->active) ! 727: panic("vm_page_activate: already active"); ! 728: ! 729: queue_enter(&vm_page_queue_active, m, vm_page_t, pageq); ! 730: m->active = TRUE; ! 731: vm_page_active_count++; ! 732: } ! 733: } ! 734: ! 735: /* ! 736: * vm_page_zero_fill: ! 737: * ! 738: * Zero-fill the specified page. ! 739: * Written as a standard pagein routine, to ! 740: * be used by the zero-fill object. ! 741: */ ! 742: ! 743: boolean_t vm_page_zero_fill(m) ! 744: vm_page_t m; ! 745: { ! 746: VM_PAGE_CHECK(m); ! 747: ! 748: pmap_zero_page(VM_PAGE_TO_PHYS(m)); ! 749: return(TRUE); ! 750: } ! 751: ! 752: /* ! 753: * vm_page_copy: ! 754: * ! 755: * Copy one page to another ! 756: */ ! 757: ! 758: void vm_page_copy(src_m, dest_m) ! 759: vm_page_t src_m; ! 760: vm_page_t dest_m; ! 761: { ! 762: VM_PAGE_CHECK(src_m); ! 763: VM_PAGE_CHECK(dest_m); ! 764: ! 765: pmap_copy_page(VM_PAGE_TO_PHYS(src_m), VM_PAGE_TO_PHYS(dest_m)); ! 766: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.