|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 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: * File: vm/vm_kern.c ! 52: * Author: Avadis Tevanian, Jr., Michael Wayne Young ! 53: * Date: 1985 ! 54: * ! 55: * Kernel memory management. ! 56: */ ! 57: ! 58: #include <mach/kern_return.h> ! 59: #include <mach/vm_param.h> ! 60: #include <kern/assert.h> ! 61: #include <kern/lock.h> ! 62: #include <kern/thread.h> ! 63: #include <vm/vm_fault.h> ! 64: #include <vm/vm_kern.h> ! 65: #include <vm/vm_map.h> ! 66: #include <vm/vm_object.h> ! 67: #include <vm/vm_page.h> ! 68: #include <vm/vm_pageout.h> ! 69: ! 70: vm_map_t kernel_map; ! 71: ! 72: static boolean_t kmem_alloc_pages( ! 73: vm_object_t object, ! 74: vm_offset_t offset, ! 75: vm_offset_t start, ! 76: vm_offset_t end, ! 77: boolean_t canblock); ! 78: void kmem_remap_pages( ! 79: vm_object_t object, ! 80: vm_offset_t offset, ! 81: vm_offset_t start, ! 82: vm_offset_t end); ! 83: ! 84: /* ! 85: * Allocate wired-down memory in the kernel's address map ! 86: * or a submap. ! 87: */ ! 88: static ! 89: kern_return_t ! 90: kmem_alloc_prim( ! 91: vm_map_t map, ! 92: vm_offset_t *addrp, ! 93: vm_size_t size, ! 94: vm_object_t object, ! 95: boolean_t canblock ! 96: ) ! 97: { ! 98: kern_return_t result; ! 99: vm_offset_t addr, offset = 0; ! 100: vm_map_entry_t entry; ! 101: ! 102: size = round_page(size); ! 103: vm_map_lock(map); ! 104: if (result = vm_map_find_entry(map, &addr, size, (vm_offset_t) 0, ! 105: (object != kernel_object)? ! 106: VM_OBJECT_NULL : object, &entry) ! 107: != KERN_SUCCESS) { ! 108: vm_map_unlock(map); ! 109: if (object != kernel_object) ! 110: vm_object_deallocate(object); ! 111: return (result); ! 112: } ! 113: ! 114: if (object == kernel_object) ! 115: offset = addr - VM_MIN_KERNEL_ADDRESS; ! 116: ! 117: if (entry->object.vm_object == VM_OBJECT_NULL) { ! 118: if (object == kernel_object) ! 119: vm_object_reference(kernel_object); ! 120: ! 121: entry->object.vm_object = object; ! 122: entry->offset = offset; ! 123: } ! 124: ! 125: /* ! 126: * Since we have not given out this address yet, ! 127: * it is safe to unlock the map. ! 128: */ ! 129: vm_map_unlock(map); ! 130: ! 131: if (!kmem_alloc_pages(object, offset, addr, addr + size, canblock)) { ! 132: vm_map_remove(map, addr, addr + size); ! 133: ! 134: return (KERN_RESOURCE_SHORTAGE); ! 135: } ! 136: ! 137: *addrp = addr; ! 138: ! 139: return (KERN_SUCCESS); ! 140: } ! 141: ! 142: kern_return_t ! 143: kmem_alloc( ! 144: vm_map_t map, ! 145: vm_offset_t *addrp, ! 146: vm_size_t size) ! 147: { ! 148: vm_object_t object = vm_object_allocate(size); ! 149: ! 150: return kmem_alloc_prim(map, addrp, size, object, TRUE); ! 151: } ! 152: ! 153: /* ! 154: * kmem_realloc: ! 155: * ! 156: * Reallocate wired-down memory in the kernel's address map ! 157: * or a submap. ! 158: * This can only be used on regions allocated with kmem_alloc. ! 159: * ! 160: * If successful, the pages in the old region are mapped twice. ! 161: * The old region is unchanged. Use kmem_free to get rid of it. ! 162: */ ! 163: kern_return_t kmem_realloc( ! 164: vm_map_t map, ! 165: vm_offset_t oldaddr, ! 166: vm_size_t oldsize, ! 167: vm_offset_t *newaddrp, ! 168: vm_size_t newsize) ! 169: { ! 170: vm_offset_t oldmin, oldmax; ! 171: vm_offset_t newaddr; ! 172: vm_object_t object; ! 173: vm_map_entry_t oldentry, newentry; ! 174: kern_return_t kr; ! 175: ! 176: oldmin = trunc_page(oldaddr); ! 177: oldmax = round_page(oldaddr + oldsize); ! 178: oldsize = oldmax - oldmin; ! 179: newsize = round_page(newsize); ! 180: ! 181: /* ! 182: * Find space for the new region. ! 183: */ ! 184: ! 185: vm_map_lock(map); ! 186: kr = vm_map_find_entry(map, &newaddr, newsize, (vm_offset_t) 0, ! 187: VM_OBJECT_NULL, &newentry); ! 188: if (kr != KERN_SUCCESS) { ! 189: vm_map_unlock(map); ! 190: return kr; ! 191: } ! 192: ! 193: /* ! 194: * Find the VM object backing the old region. ! 195: */ ! 196: ! 197: if (!vm_map_lookup_entry(map, oldmin, &oldentry)) ! 198: panic("kmem_realloc"); ! 199: object = oldentry->object.vm_object; ! 200: ! 201: /* ! 202: * Increase the size of the object and ! 203: * fill in the new region. ! 204: */ ! 205: ! 206: vm_object_reference(object); ! 207: vm_object_lock(object); ! 208: if (object->size != oldsize) ! 209: panic("kmem_realloc"); ! 210: object->size = newsize; ! 211: vm_object_unlock(object); ! 212: ! 213: newentry->object.vm_object = object; ! 214: newentry->offset = 0; ! 215: ! 216: /* ! 217: * Since we have not given out this address yet, ! 218: * it is safe to unlock the map. We are trusting ! 219: * that nobody will play with either region. ! 220: */ ! 221: ! 222: vm_map_unlock(map); ! 223: ! 224: /* ! 225: * Remap the pages in the old region and ! 226: * allocate more pages for the new region. ! 227: */ ! 228: ! 229: kmem_remap_pages(object, 0, ! 230: newaddr, newaddr + oldsize); ! 231: (void) kmem_alloc_pages(object, oldsize, ! 232: newaddr + oldsize, newaddr + newsize, TRUE); ! 233: ! 234: *newaddrp = newaddr; ! 235: return KERN_SUCCESS; ! 236: } ! 237: ! 238: kern_return_t ! 239: kmem_alloc_wired( ! 240: vm_map_t map, ! 241: vm_offset_t *addrp, ! 242: vm_size_t size) ! 243: { ! 244: return kmem_alloc_prim(map, addrp, size, kernel_object, TRUE); ! 245: } ! 246: ! 247: ! 248: /* ! 249: * kmem_alloc_pageable: ! 250: * ! 251: * Allocate pageable memory to the kernel's address map. ! 252: * map must be "kernel_map" below. ! 253: */ ! 254: ! 255: kern_return_t ! 256: kmem_alloc_pageable( ! 257: vm_map_t map, ! 258: vm_offset_t *addrp, ! 259: vm_size_t size) ! 260: { ! 261: vm_offset_t addr; ! 262: kern_return_t kr; ! 263: ! 264: addr = vm_map_min(map); ! 265: kr = vm_map_find(map, VM_OBJECT_NULL, (vm_offset_t) 0, ! 266: &addr, round_page(size), TRUE); ! 267: if (kr != KERN_SUCCESS) ! 268: return kr; ! 269: ! 270: *addrp = addr; ! 271: return KERN_SUCCESS; ! 272: } ! 273: ! 274: /* ! 275: * kmem_free: ! 276: * ! 277: * Release a region of kernel virtual memory allocated ! 278: * with kmem_alloc, and return the physical pages ! 279: * associated with that region. ! 280: */ ! 281: void ! 282: kmem_free( ! 283: vm_map_t map, ! 284: vm_offset_t addr, ! 285: vm_size_t size) ! 286: { ! 287: (void) vm_map_remove(map, trunc_page(addr), round_page(addr + size)); ! 288: } ! 289: ! 290: /* ! 291: * Allocate new wired pages in an object. ! 292: * The object is assumed to be mapped into the kernel map or ! 293: * a submap. ! 294: */ ! 295: static ! 296: boolean_t ! 297: kmem_alloc_pages( ! 298: vm_object_t object, ! 299: vm_offset_t offset, ! 300: vm_offset_t start, ! 301: vm_offset_t end, ! 302: boolean_t canblock) ! 303: { ! 304: /* ! 305: * Mark the pmap region as not pageable. ! 306: */ ! 307: pmap_pageable(kernel_pmap, start, end, FALSE); ! 308: ! 309: while (start < end) { ! 310: register vm_page_t mem; ! 311: ! 312: vm_object_lock(object); ! 313: ! 314: /* ! 315: * Allocate a page ! 316: */ ! 317: while ((mem = vm_page_alloc(object, offset)) == VM_PAGE_NULL) { ! 318: vm_object_unlock(object); ! 319: if (!canblock) ! 320: return FALSE; ! 321: VM_WAIT; ! 322: vm_object_lock(object); ! 323: } ! 324: ! 325: /* ! 326: * Wire it down ! 327: */ ! 328: vm_page_lock_queues(); ! 329: vm_page_wire(mem); ! 330: vm_page_unlock_queues(); ! 331: vm_object_unlock(object); ! 332: ! 333: vm_page_zero_fill(mem); ! 334: ! 335: /* ! 336: * Enter it in the kernel pmap ! 337: */ ! 338: PMAP_ENTER(kernel_pmap, start, mem, ! 339: VM_PROT_DEFAULT, TRUE); ! 340: ! 341: vm_object_lock(object); ! 342: PAGE_WAKEUP(mem); ! 343: vm_object_unlock(object); ! 344: ! 345: start += PAGE_SIZE; ! 346: offset += PAGE_SIZE; ! 347: } ! 348: ! 349: return TRUE; ! 350: } ! 351: ! 352: /* ! 353: * Remap wired pages in an object into a new region. ! 354: * The object is assumed to be mapped into the kernel map or ! 355: * a submap. ! 356: */ ! 357: void ! 358: kmem_remap_pages( ! 359: vm_object_t object, ! 360: vm_offset_t offset, ! 361: vm_offset_t start, ! 362: vm_offset_t end) ! 363: { ! 364: /* ! 365: * Mark the pmap region as not pageable. ! 366: */ ! 367: pmap_pageable(kernel_pmap, start, end, FALSE); ! 368: ! 369: while (start < end) { ! 370: register vm_page_t mem; ! 371: ! 372: vm_object_lock(object); ! 373: ! 374: /* ! 375: * Find a page ! 376: */ ! 377: if ((mem = vm_page_lookup(object, offset)) == VM_PAGE_NULL) ! 378: panic("kmem_remap_pages"); ! 379: ! 380: /* ! 381: * Wire it down (again) ! 382: */ ! 383: vm_page_lock_queues(); ! 384: vm_page_wire(mem); ! 385: vm_page_unlock_queues(); ! 386: vm_object_unlock(object); ! 387: ! 388: /* ! 389: * Enter it in the kernel pmap. The page isn't busy, ! 390: * but this shouldn't be a problem because it is wired. ! 391: */ ! 392: PMAP_ENTER(kernel_pmap, start, mem, ! 393: VM_PROT_DEFAULT, TRUE); ! 394: ! 395: start += PAGE_SIZE; ! 396: offset += PAGE_SIZE; ! 397: } ! 398: } ! 399: ! 400: /* ! 401: * kmem_suballoc: ! 402: * ! 403: * Allocates a map to manage a subrange ! 404: * of the kernel virtual address space. ! 405: * ! 406: * Arguments are as follows: ! 407: * ! 408: * parent Map to take range from ! 409: * size Size of range to find ! 410: * min, max Returned endpoints of map ! 411: * pageable Can the region be paged ! 412: */ ! 413: vm_map_t ! 414: kmem_suballoc( ! 415: vm_map_t parent, ! 416: vm_offset_t *min, ! 417: vm_offset_t *max, ! 418: vm_size_t size, ! 419: boolean_t pageable) ! 420: { ! 421: vm_map_t map; ! 422: vm_offset_t addr; ! 423: kern_return_t kr; ! 424: ! 425: size = round_page(size); ! 426: ! 427: /* ! 428: * Need reference on submap object because it is internal ! 429: * to the vm_system. vm_object_enter will never be called ! 430: * on it (usual source of reference for vm_map_enter). ! 431: */ ! 432: vm_object_reference(vm_submap_object); ! 433: ! 434: addr = (vm_offset_t) vm_map_min(parent); ! 435: kr = vm_map_find(parent, vm_submap_object, (vm_offset_t) 0, ! 436: &addr, size, TRUE); ! 437: if (kr != KERN_SUCCESS) ! 438: panic("kmem_suballoc 1"); ! 439: ! 440: pmap_reference(vm_map_pmap(parent)); ! 441: map = vm_map_create(vm_map_pmap(parent), addr, addr + size, pageable); ! 442: if (map == VM_MAP_NULL) ! 443: panic("kmem_suballoc 2"); ! 444: ! 445: kr = vm_map_submap(parent, addr, addr + size, map); ! 446: if (kr != KERN_SUCCESS) ! 447: panic("kmem_suballoc 3"); ! 448: ! 449: *min = addr; ! 450: *max = addr + size; ! 451: return map; ! 452: } ! 453: ! 454: /* ! 455: * kmem_init: ! 456: * ! 457: * Initialize the kernel's virtual memory map, taking ! 458: * into account all memory allocated up to this time. ! 459: */ ! 460: void kmem_init( ! 461: vm_offset_t start, ! 462: vm_offset_t end) ! 463: { ! 464: kernel_map = vm_map_create(pmap_kernel(), ! 465: VM_MIN_KERNEL_ADDRESS, end, ! 466: FALSE); ! 467: ! 468: /* ! 469: * Reserve virtual memory allocated up to this time. ! 470: */ ! 471: ! 472: if (start != VM_MIN_KERNEL_ADDRESS) { ! 473: vm_offset_t addr = VM_MIN_KERNEL_ADDRESS; ! 474: (void) vm_map_find(kernel_map, VM_OBJECT_NULL, (vm_offset_t) 0, ! 475: &addr, (start - VM_MIN_KERNEL_ADDRESS), ! 476: FALSE); ! 477: } ! 478: } ! 479: ! 480: /* ! 481: * Routine: copyinmap ! 482: * Purpose: ! 483: * Like copyin, except that fromaddr is an address ! 484: * in the specified VM map. This implementation ! 485: * is incomplete; it handles the current user map ! 486: * and the kernel map/submaps. ! 487: */ ! 488: ! 489: int copyinmap(map, fromaddr, toaddr, length) ! 490: vm_map_t map; ! 491: char *fromaddr, *toaddr; ! 492: int length; ! 493: { ! 494: if (vm_map_pmap(map) == kernel_pmap) { ! 495: /* assume a correct copy */ ! 496: bcopy(fromaddr, toaddr, length); ! 497: return 0; ! 498: } ! 499: ! 500: if (current_map() == map) ! 501: return copyin( fromaddr, toaddr, length); ! 502: ! 503: return 1; ! 504: } ! 505: ! 506: /* ! 507: * Routine: copyoutmap ! 508: * Purpose: ! 509: * Like copyout, except that toaddr is an address ! 510: * in the specified VM map. This implementation ! 511: * is incomplete; it handles the current user map ! 512: * and the kernel map/submaps. ! 513: */ ! 514: ! 515: int copyoutmap(map, fromaddr, toaddr, length) ! 516: vm_map_t map; ! 517: char *fromaddr, *toaddr; ! 518: int length; ! 519: { ! 520: if (vm_map_pmap(map) == kernel_pmap) { ! 521: /* assume a correct copy */ ! 522: bcopy(fromaddr, toaddr, length); ! 523: return 0; ! 524: } ! 525: ! 526: if (current_map() == map) ! 527: return copyout(fromaddr, toaddr, length); ! 528: ! 529: return 1; ! 530: } ! 531: ! 532: /* ! 533: * Allocate wired-down memory in the kernel's address map ! 534: * or a submap. ! 535: */ ! 536: kern_return_t ! 537: kmem_alloc_zone(map, addrp, size, canblock) ! 538: vm_map_t map; ! 539: vm_offset_t *addrp; ! 540: register vm_size_t size; ! 541: boolean_t canblock; ! 542: { ! 543: return kmem_alloc_prim(map, addrp, size, kernel_object, canblock); ! 544: } ! 545: ! 546: /* ! 547: * Special hack for allocation in mb_map. Can never wait for pages ! 548: * (or anything else) in mb_map. ! 549: */ ! 550: vm_offset_t kmem_mb_alloc(map, size) ! 551: register vm_map_t map; ! 552: vm_size_t size; ! 553: { ! 554: vm_object_t object; ! 555: register vm_map_entry_t entry; ! 556: vm_offset_t addr; ! 557: register int npgs; ! 558: register vm_page_t m; ! 559: register vm_offset_t vaddr, offset, cur_off; ! 560: ! 561: /* ! 562: * Only do this on the mb_map. ! 563: */ ! 564: if (map != mb_map) ! 565: panic("You fool!"); ! 566: ! 567: size = round_page(size); ! 568: ! 569: vm_map_lock(map); ! 570: entry = vm_map_first_entry(map); ! 571: if (entry == vm_map_to_entry(map)) { ! 572: /* ! 573: * Map is empty. Do things normally the first time... ! 574: * this will allocate the entry and the object to use. ! 575: */ ! 576: vm_map_unlock(map); ! 577: addr = vm_map_min(map); ! 578: if (vm_map_find(map, VM_OBJECT_NULL, (vm_offset_t) 0, ! 579: &addr, size, TRUE) != KERN_SUCCESS) ! 580: return (0); ! 581: (void) vm_map_pageable(map, addr, addr + size, FALSE); ! 582: ! 583: return(addr); ! 584: } ! 585: /* ! 586: * Map already has an entry. We must be extending it. ! 587: */ ! 588: if (!(entry == vm_map_last_entry(map) && ! 589: entry->is_a_map == FALSE && ! 590: entry->vme_start == vm_map_min(map) && ! 591: entry->max_protection == VM_PROT_ALL && ! 592: entry->protection == VM_PROT_DEFAULT && ! 593: entry->inheritance == VM_INHERIT_DEFAULT && ! 594: entry->wired_count != 0)) { ! 595: /* ! 596: * Someone's not playing by the rules... ! 597: */ ! 598: panic("mb_map abused even more than usual"); ! 599: } ! 600: ! 601: /* ! 602: * Make sure there's enough room in map to extend entry. ! 603: */ ! 604: ! 605: if (vm_map_max(map) - size < entry->vme_end) { ! 606: vm_map_unlock(map); ! 607: return(0); ! 608: } ! 609: ! 610: /* ! 611: * extend the entry ! 612: */ ! 613: object = entry->object.vm_object; ! 614: offset = (entry->vme_end - entry->vme_start) + entry->offset; ! 615: addr = entry->vme_end; ! 616: entry->vme_end += size; ! 617: ! 618: /* ! 619: * Since we may not have enough memory, and we may not ! 620: * block, we first allocate all the memory up front, pulling ! 621: * it off the active queue to prevent pageout. We then can ! 622: * either enter the pages, or free whatever we tried to get. ! 623: */ ! 624: ! 625: vm_object_lock(object); ! 626: cur_off = offset; ! 627: npgs = atop(size); ! 628: while (npgs) { ! 629: m = vm_page_alloc_sequential(object, cur_off, FALSE); ! 630: if (m == VM_PAGE_NULL) { ! 631: /* ! 632: * Not enough pages, and we can't ! 633: * wait, so free everything up. ! 634: */ ! 635: while (cur_off > offset) { ! 636: cur_off -= PAGE_SIZE; ! 637: m = vm_page_lookup(object, cur_off); ! 638: /* ! 639: * Don't have to lock the queues here ! 640: * because we know that the pages are ! 641: * not on any queues. ! 642: */ ! 643: vm_page_free(m); ! 644: } ! 645: vm_object_unlock(object); ! 646: ! 647: /* ! 648: * Shrink the map entry back to its old size. ! 649: */ ! 650: entry->vme_end -= size; ! 651: vm_map_unlock(map); ! 652: return(0); ! 653: } ! 654: ! 655: /* ! 656: * We want zero-filled memory ! 657: */ ! 658: ! 659: vm_page_zero_fill(m); ! 660: ! 661: /* ! 662: * Since no other process can see these pages, we don't ! 663: * have to bother with the busy bit. ! 664: */ ! 665: ! 666: m->busy = FALSE; ! 667: ! 668: npgs--; ! 669: cur_off += PAGE_SIZE; ! 670: } ! 671: ! 672: vm_object_unlock(object); ! 673: ! 674: /* ! 675: * Map entry is already marked non-pageable. ! 676: * Loop thru pages, entering them in the pmap. ! 677: * (We can't add them to the wired count without ! 678: * wrapping the vm_page_queue_lock in splimp...) ! 679: */ ! 680: vaddr = addr; ! 681: cur_off = offset; ! 682: while (vaddr < entry->vme_end) { ! 683: vm_object_lock(object); ! 684: m = vm_page_lookup(object, cur_off); ! 685: vm_page_wire(m); ! 686: vm_object_unlock(object); ! 687: pmap_enter(map->pmap, vaddr, VM_PAGE_TO_PHYS(m), ! 688: entry->protection, TRUE); ! 689: vaddr += PAGE_SIZE; ! 690: cur_off += PAGE_SIZE; ! 691: } ! 692: vm_map_unlock(map); ! 693: ! 694: return(addr); ! 695: } ! 696: ! 697: /* ! 698: * kmem_alloc_wait ! 699: * ! 700: * Allocates pageable memory from a sub-map of the kernel. If the submap ! 701: * has no room, the caller sleeps waiting for more memory in the submap. ! 702: * ! 703: */ ! 704: vm_offset_t kmem_alloc_wait(map, size) ! 705: vm_map_t map; ! 706: vm_size_t size; ! 707: { ! 708: vm_offset_t addr; ! 709: kern_return_t result; ! 710: ! 711: size = round_page(size); ! 712: ! 713: do { ! 714: /* ! 715: * To make this work for more than one map, ! 716: * use the map's lock to lock out sleepers/wakers. ! 717: * Unfortunately, vm_map_find also grabs the map lock. ! 718: */ ! 719: vm_map_lock(map); ! 720: lock_set_recursive(&map->lock); ! 721: ! 722: addr = vm_map_min(map); ! 723: result = vm_map_find(map, VM_OBJECT_NULL, (vm_offset_t) 0, ! 724: &addr, size, TRUE); ! 725: ! 726: lock_clear_recursive(&map->lock); ! 727: if (result != KERN_SUCCESS) { ! 728: ! 729: if ( (vm_map_max(map) - vm_map_min(map)) < size ) { ! 730: vm_map_unlock(map); ! 731: return(0); ! 732: } ! 733: ! 734: assert_wait(map, TRUE); ! 735: vm_map_unlock(map); ! 736: thread_block(); ! 737: } ! 738: else { ! 739: vm_map_unlock(map); ! 740: } ! 741: ! 742: } while (result != KERN_SUCCESS); ! 743: ! 744: return(addr); ! 745: } ! 746: ! 747: /* ! 748: * kmem_free_wakeup ! 749: * ! 750: * Returns memory to a submap of the kernel, and wakes up any threads ! 751: * waiting for memory in that map. ! 752: */ ! 753: void kmem_free_wakeup(map, addr, size) ! 754: vm_map_t map; ! 755: vm_offset_t addr; ! 756: vm_size_t size; ! 757: { ! 758: vm_map_lock(map); ! 759: (void) vm_map_delete(map, trunc_page(addr), round_page(addr + size)); ! 760: thread_wakeup(map); ! 761: vm_map_unlock(map); ! 762: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.