|
|
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: #include <sys/errno.h> ! 24: #include <kern/host.h> ! 25: #include <mach/mach_types.h> ! 26: #include <vm/vm_map.h> ! 27: #include <vm/vm_kern.h> ! 28: #include <vm/vm_pageout.h> ! 29: #include <mach/kern_return.h> ! 30: #include <mach/memory_object_types.h> ! 31: #include <mach/port.h> ! 32: #include <mach/policy.h> ! 33: #include <ipc/ipc_port.h> ! 34: #include <ipc/ipc_space.h> ! 35: #include <kern/thread.h> ! 36: #include <vm/vm_pageout.h> ! 37: ! 38: ! 39: /* BSD VM COMPONENT INTERFACES */ ! 40: int ! 41: get_map_nentries( ! 42: vm_map_t); ! 43: ! 44: vm_offset_t ! 45: get_map_start( ! 46: vm_map_t); ! 47: ! 48: vm_offset_t ! 49: get_map_end( ! 50: vm_map_t); ! 51: ! 52: void ! 53: map_ref_fixup( ! 54: vm_map_t, ! 55: vm_map_t); ! 56: ! 57: /* ! 58: * ! 59: */ ! 60: int ! 61: get_map_nentries( ! 62: vm_map_t map) ! 63: { ! 64: return(map->hdr.nentries); ! 65: } ! 66: ! 67: /* ! 68: * ! 69: */ ! 70: vm_offset_t ! 71: get_map_start( ! 72: vm_map_t map) ! 73: { ! 74: return(vm_map_first_entry(map)->vme_start); ! 75: } ! 76: ! 77: /* ! 78: * ! 79: */ ! 80: vm_offset_t ! 81: get_map_end( ! 82: vm_map_t map) ! 83: { ! 84: return(vm_map_last_entry(map)->vme_end); ! 85: } ! 86: ! 87: /* ! 88: * TODO: TO BE REMOVED ! 89: */ ! 90: void ! 91: map_ref_fixup( ! 92: vm_map_t old_map, ! 93: vm_map_t new_map) ! 94: { ! 95: if (old_map->ref_count >1) ! 96: old_map->ref_count = 1; ! 97: new_map->ref_count =2; ! 98: } ! 99: ! 100: /* ! 101: * BSD VNODE PAGER ! 102: */ ! 103: ! 104: /* until component support available */ ! 105: int vnode_pager_workaround; ! 106: ! 107: typedef int vnode_port_t; ! 108: ! 109: typedef struct vnode_pager { ! 110: ipc_port_t pager; /* pager */ ! 111: ipc_port_t pager_handle; /* pager handle */ ! 112: ipc_port_t vm_obj_handle; /* memory object's control handle */ ! 113: vnode_port_t vnode_handle; /* vnode handle */ ! 114: } *vnode_pager_t; ! 115: ! 116: typedef struct vnode_port_entry { ! 117: queue_chain_t links; /* queue links */ ! 118: ipc_port_t name; /* port name */ ! 119: vnode_pager_t pager_rec; /* pager record */ ! 120: } *vnode_port_entry_t; ! 121: ! 122: ! 123: #define VNODE_PORT_HASH_COUNT 127 ! 124: #define vnode_port_hash(name_port) \ ! 125: (((int)(name_port) & 0xffffff) % VNODE_PORT_HASH_COUNT) ! 126: ! 127: queue_head_t vnode_port_hashtable[VNODE_PORT_HASH_COUNT]; ! 128: zone_t vnode_port_hash_zone; ! 129: decl_simple_lock_data(,vnode_port_hash_lock) ! 130: ! 131: ! 132: ipc_port_t ! 133: trigger_name_to_port( ! 134: mach_port_t); ! 135: ! 136: void ! 137: vnode_pager_bootstrap( ! 138: void); ! 139: ! 140: void ! 141: vnode_pager_alloc_map( ! 142: void); ! 143: ! 144: ipc_port_t ! 145: vnode_pager_setup( ! 146: vnode_port_t, ! 147: ipc_port_t); ! 148: ! 149: ipc_port_t ! 150: vnode_pager_lookup( ! 151: vnode_port_t, ! 152: ipc_port_t); ! 153: ! 154: kern_return_t ! 155: vnode_pager_init( ! 156: ipc_port_t, ! 157: ipc_port_t, ! 158: vm_size_t); ! 159: ! 160: kern_return_t ! 161: vnode_pager_data_request( ! 162: ipc_port_t, ! 163: ipc_port_t, ! 164: vm_offset_t, ! 165: vm_size_t, ! 166: vm_prot_t); ! 167: ! 168: kern_return_t ! 169: vnode_pager_data_return( ! 170: ipc_port_t, ! 171: ipc_port_t, ! 172: vm_offset_t, ! 173: pointer_t, ! 174: vm_size_t, ! 175: boolean_t, ! 176: boolean_t); ! 177: ! 178: void ! 179: vnode_pager_no_senders( ! 180: ipc_port_t, ! 181: mach_port_mscount_t); ! 182: ! 183: kern_return_t ! 184: vnode_pager_terminate( ! 185: ipc_port_t, ! 186: ipc_port_t); ! 187: ! 188: kern_return_t ! 189: vnode_pager_cluster_read( ! 190: vnode_pager_t, ! 191: vm_offset_t, ! 192: vm_size_t, ! 193: vm_object_t); ! 194: ! 195: void ! 196: vnode_pager_cluster_write( ! 197: vnode_pager_t, ! 198: vm_offset_t, ! 199: vm_size_t, ! 200: vm_object_t); ! 201: ! 202: kern_return_t ! 203: memory_object_change_attributes( ! 204: vm_object_t, ! 205: memory_object_flavor_t, ! 206: memory_object_info_t, ! 207: mach_msg_type_number_t, ! 208: ipc_port_t, ! 209: mach_msg_type_name_t); ! 210: ! 211: vnode_pager_t ! 212: vnode_object_create( ! 213: vnode_port_t vp); ! 214: ! 215: void ! 216: vnode_port_hash_init(void); ! 217: ! 218: void ! 219: vnode_port_hash_insert( ! 220: ipc_port_t, ! 221: vnode_pager_t); ! 222: ! 223: vnode_pager_t ! 224: vnode_port_hash_lookup( ! 225: ipc_port_t); ! 226: ! 227: void ! 228: vnode_port_hash_delete( ! 229: ipc_port_t); ! 230: ! 231: void ! 232: vnode_pager_release_from_cache( ! 233: int *cnt); ! 234: ! 235: void ! 236: vnode_pager_create( ! 237: vnode_port_t, ! 238: ipc_port_t); ! 239: ! 240: int ! 241: vnode_pageout( ! 242: vnode_port_t, ! 243: vm_offset_t, ! 244: vm_offset_t, ! 245: int, ! 246: int *); ! 247: ! 248: int ! 249: vnode_pagein( ! 250: vnode_port_t, ! 251: vm_offset_t, ! 252: vm_offset_t, ! 253: int, ! 254: int *); ! 255: ! 256: zone_t vnode_pager_zone; ! 257: ! 258: ! 259: #define VNODE_PAGER_NULL ((vnode_pager_t) 0) ! 260: ! 261: /* TODO: Should be set dynamically by vnode_pager_init() */ ! 262: #define CLUSTER_SHIFT 1 ! 263: ! 264: /* TODO: Should be set dynamically by vnode_pager_bootstrap() */ ! 265: #define MAX_VNODE 10000 ! 266: ! 267: ! 268: #if DEBUG ! 269: int pagerdebug=0; ! 270: ! 271: #define PAGER_ALL 0xffffffff ! 272: #define PAGER_INIT 0x00000001 ! 273: #define PAGER_PAGEIN 0x00000002 ! 274: ! 275: #define PAGER_DEBUG(LEVEL, A) {if ((pagerdebug & LEVEL)==LEVEL){printf A;}} ! 276: #else ! 277: #define PAGER_DEBUG(LEVEL, A) ! 278: #endif ! 279: ! 280: /* ! 281: * Routine: macx_triggers ! 282: * Function: ! 283: * Syscall interface to set the call backs for low and ! 284: * high water marks. ! 285: */ ! 286: int ! 287: macx_triggers( ! 288: int hi_water, ! 289: int low_water, ! 290: int flags, ! 291: mach_port_t trigger_name) ! 292: { ! 293: kern_return_t kr; ! 294: ipc_port_t default_pager_port = MACH_PORT_NULL; ! 295: ipc_port_t trigger_port; ! 296: ! 297: kr = host_default_memory_manager(realhost.host_priv_self, ! 298: &default_pager_port, 0); ! 299: if(kr != KERN_SUCCESS) { ! 300: return EINVAL; ! 301: } ! 302: trigger_port = trigger_name_to_port(trigger_name); ! 303: if(trigger_port == NULL) { ! 304: return EINVAL; ! 305: } ! 306: /* trigger_port is locked and active */ ! 307: ip_unlock(trigger_port); ! 308: default_pager_triggers(default_pager_port, ! 309: hi_water, low_water, flags, trigger_port); ! 310: ipc_port_make_send(trigger_port); ! 311: ! 312: /* ! 313: * Set thread scheduling priority and policy for the current thread ! 314: * it is assumed for the time being that the thread setting the alert ! 315: * is the same one which will be servicing it. ! 316: */ ! 317: { ! 318: struct policy_timeshare_base fifo_base; ! 319: struct policy_timeshare_limit fifo_limit; ! 320: policy_base_t base; ! 321: processor_set_t pset; ! 322: policy_limit_t limit; ! 323: ! 324: pset = (current_thread())->processor_set; ! 325: base = (policy_base_t) &fifo_base; ! 326: limit = (policy_limit_t) &fifo_limit; ! 327: fifo_base.base_priority = BASEPRI_KERNEL; ! 328: fifo_limit.max_priority = BASEPRI_KERNEL; ! 329: thread_set_policy((current_thread())->top_act, pset, POLICY_FIFO, base, POLICY_TIMESHARE_BASE_COUNT, limit, POLICY_TIMESHARE_LIMIT_COUNT); ! 330: } ! 331: ! 332: current_thread()->vm_privilege = TRUE; ! 333: } ! 334: ! 335: /* ! 336: * ! 337: */ ! 338: ipc_port_t ! 339: trigger_name_to_port( ! 340: mach_port_t trigger_name) ! 341: { ! 342: ipc_port_t trigger_port; ! 343: ipc_space_t space; ! 344: ! 345: if (trigger_name == 0) ! 346: return (NULL); ! 347: ! 348: space = current_space(); ! 349: if(ipc_port_translate_receive(space, (mach_port_name_t)trigger_name, ! 350: &trigger_port) != KERN_SUCCESS) ! 351: return (NULL); ! 352: return trigger_port; ! 353: } ! 354: ! 355: /* ! 356: * ! 357: */ ! 358: void ! 359: vnode_pager_bootstrap(void) ! 360: { ! 361: register vm_size_t size; ! 362: ! 363: size = (vm_size_t) sizeof(struct vnode_pager); ! 364: vnode_pager_zone = zinit(size, (vm_size_t) MAX_VNODE*size, ! 365: PAGE_SIZE, "vnode pager structures"); ! 366: vnode_port_hash_init(); ! 367: ! 368: return; ! 369: } ! 370: ! 371: /* ! 372: * ! 373: */ ! 374: ipc_port_t ! 375: vnode_pager_setup( ! 376: vnode_port_t vp, ! 377: ipc_port_t pager) ! 378: { ! 379: vnode_pager_t vnode_object; ! 380: kern_return_t kr; ! 381: ipc_port_t previous; ! 382: ! 383: if (pager && ! 384: (vnode_object = vnode_port_hash_lookup(pager))) { ! 385: if (vnode_object->vnode_handle == vp) ! 386: return(pager); ! 387: } ! 388: ! 389: vnode_object = vnode_object_create(vp); ! 390: if (vnode_object == VNODE_PAGER_NULL) ! 391: panic("vnode_pager_setup: vnode_object_create() failed"); ! 392: ! 393: vnode_object->pager = ipc_port_alloc_kernel(); ! 394: assert (vnode_object->pager != IP_NULL); ! 395: pager_mux_hash_insert(vnode_object->pager, ! 396: (rpc_subsystem_t)&vnode_pager_workaround); ! 397: ! 398: vnode_object->pager_handle = ipc_port_make_send(vnode_object->pager); ! 399: ! 400: vnode_port_hash_insert(vnode_object->pager_handle, vnode_object); ! 401: ! 402: ipc_port_make_sonce(vnode_object->pager); ! 403: ip_lock(vnode_object->pager); /* unlocked in nsrequest below */ ! 404: ipc_port_nsrequest(vnode_object->pager, 1, vnode_object->pager, &previous); ! 405: ! 406: PAGER_DEBUG(PAGER_INIT, ("vnode_pager_setup: vp %x pager %x vnode_pager %x\n", vp, vnode_object->pager_handle, vnode_object)); ! 407: ! 408: vnode_pager_create( vp, vnode_object->pager_handle); ! 409: return(vnode_object->pager_handle); ! 410: } ! 411: ! 412: /* ! 413: * ! 414: */ ! 415: ipc_port_t ! 416: vnode_pager_lookup( ! 417: vnode_port_t vp, ! 418: ipc_port_t pager) ! 419: { ! 420: vnode_pager_t vnode_object; ! 421: kern_return_t kr; ! 422: ! 423: if (pager && ! 424: (vnode_object = vnode_port_hash_lookup(pager))) { ! 425: if (vnode_object->vnode_handle == vp) ! 426: return(vnode_object->vm_obj_handle); ! 427: else ! 428: return NULL; ! 429: } ! 430: else ! 431: return NULL; ! 432: } ! 433: ! 434: /* ! 435: * ! 436: */ ! 437: kern_return_t ! 438: vnode_pager_init(ipc_port_t pager, ! 439: ipc_port_t pager_request, ! 440: vm_size_t pg_size) ! 441: { ! 442: vnode_pager_t vnode_object; ! 443: kern_return_t kr; ! 444: memory_object_attr_info_data_t attributes; ! 445: vm_object_t vm_object; ! 446: ! 447: ! 448: PAGER_DEBUG(PAGER_ALL, ("vnode_pager_init: %x, %x, %x\n", pager, pager_request, pg_size)); ! 449: ! 450: vnode_object = vnode_port_hash_lookup(pager); ! 451: if (vnode_object == VNODE_PAGER_NULL) ! 452: panic("vnode_pager_init: lookup failed"); ! 453: ! 454: vnode_object->vm_obj_handle = pager_request; ! 455: ! 456: vm_object = vm_object_lookup(pager_request); ! 457: ! 458: if (vm_object == VM_OBJECT_NULL) ! 459: panic("vnode_pager_init: vm_object_lookup() failed"); ! 460: ! 461: attributes.copy_strategy = MEMORY_OBJECT_COPY_DELAY; ! 462: attributes.cluster_size = (1 << (CLUSTER_SHIFT + PAGE_SHIFT)); ! 463: attributes.may_cache_object = TRUE; ! 464: attributes.temporary = TRUE; ! 465: ! 466: kr = memory_object_change_attributes( ! 467: vm_object, ! 468: MEMORY_OBJECT_ATTRIBUTE_INFO, ! 469: (memory_object_info_t) &attributes, ! 470: MEMORY_OBJECT_ATTR_INFO_COUNT, ! 471: MACH_PORT_NULL, 0); ! 472: if (kr != KERN_SUCCESS) ! 473: panic("vnode_pager_init: memory_object_change_attributes() failed"); ! 474: ! 475: return(KERN_SUCCESS); ! 476: } ! 477: ! 478: /* ! 479: * ! 480: */ ! 481: kern_return_t ! 482: vnode_pager_data_return( ! 483: ipc_port_t mem_obj, ! 484: ipc_port_t control_port, ! 485: vm_offset_t offset, ! 486: pointer_t addr, ! 487: vm_size_t data_cnt, ! 488: boolean_t dirty, ! 489: boolean_t kernel_copy) ! 490: { ! 491: register vnode_pager_t vnode_object; ! 492: ! 493: vnode_object = vnode_port_hash_lookup(mem_obj); ! 494: if (vnode_object == VNODE_PAGER_NULL) ! 495: panic("vnode_pager_data_return: lookup failed"); ! 496: ! 497: vnode_pager_cluster_write(vnode_object, offset, data_cnt, (vm_object_t)control_port->ip_kobject); ! 498: ! 499: return KERN_SUCCESS; ! 500: } ! 501: ! 502: /* ! 503: * ! 504: */ ! 505: kern_return_t ! 506: vnode_pager_data_request( ! 507: ipc_port_t mem_obj, ! 508: ipc_port_t mem_obj_control, ! 509: vm_offset_t offset, ! 510: vm_size_t length, ! 511: vm_prot_t protection_required) ! 512: { ! 513: register vnode_pager_t vnode_object; ! 514: ! 515: PAGER_DEBUG(PAGER_ALL, ("vnode_pager_data_request: %x, %x, %x, %x, %x\n", mem_obj, mem_obj_control, offset, length, protection_required)); ! 516: ! 517: vnode_object = vnode_port_hash_lookup(mem_obj); ! 518: ! 519: PAGER_DEBUG(PAGER_PAGEIN, ("vnode_pager_data_request: %x, %x, %x, %x, %x, vnode_object %x\n", mem_obj, mem_obj_control, offset, length, protection_required, vnode_object)); ! 520: ! 521: if (vnode_object == VNODE_PAGER_NULL) ! 522: panic("vnode_pager_data_request: lookup failed"); ! 523: ! 524: vnode_pager_cluster_read(vnode_object, offset, length, (vm_object_t)mem_obj_control->ip_kobject); ! 525: ! 526: return KERN_SUCCESS; ! 527: } ! 528: ! 529: /* ! 530: * ! 531: */ ! 532: void ! 533: vnode_pager_no_senders( ! 534: ipc_port_t mem_obj, ! 535: mach_port_mscount_t mscount) ! 536: { ! 537: register vnode_pager_t vnode_object; ! 538: boolean_t funnel_state; ! 539: ! 540: PAGER_DEBUG(PAGER_ALL, ("vnode_pager_nosenders: %x, %x\n", mem_obj, mscount)); ! 541: ! 542: vnode_object = vnode_port_hash_lookup(mem_obj); ! 543: if (vnode_object == VNODE_PAGER_NULL) ! 544: panic("vnode_pager_no_senders: lookup failed"); ! 545: ! 546: assert(vnode_object->pager_handle == mem_obj); ! 547: ! 548: pager_mux_hash_delete((ipc_port_t) vnode_object->pager_handle); ! 549: ipc_port_dealloc_kernel(vnode_object->pager); ! 550: vnode_port_hash_delete(vnode_object->pager_handle); ! 551: if (vnode_object->vnode_handle != (vnode_port_t) NULL) { ! 552: funnel_state = thread_set_funneled(TRUE); ! 553: vrele(vnode_object->vnode_handle); ! 554: (void) thread_set_funneled(funnel_state); ! 555: } ! 556: zfree(vnode_pager_zone, (vm_offset_t) vnode_object); ! 557: ! 558: return; ! 559: } ! 560: ! 561: /* ! 562: * ! 563: */ ! 564: kern_return_t ! 565: vnode_pager_terminate( ! 566: ipc_port_t mem_obj, ! 567: ipc_port_t mem_obj_control) ! 568: { ! 569: register vnode_pager_t vnode_object; ! 570: ! 571: PAGER_DEBUG(PAGER_ALL, ("vnode_pager_terminate: %x, %x\n", mem_obj, mem_obj_control)); ! 572: ! 573: vnode_object = vnode_port_hash_lookup(mem_obj); ! 574: if (vnode_object == VNODE_PAGER_NULL) ! 575: panic("vnode_pager_terminate: lookup failed"); ! 576: ! 577: assert(vnode_object->pager_handle == mem_obj); ! 578: ! 579: /* release extra send right created by the fact that the caller */ ! 580: /* of vnode_pager_setup does not establish a mapping between a */ ! 581: /* cache object and the mem_obj (AMO). When a subsequent vm_map */ ! 582: /* is done, vm_map will bump the send right count */ ! 583: ipc_port_release_send(mem_obj); ! 584: ! 585: /* release a send right because terminate is called directly and */ ! 586: /* not through IPC, the right won't disappear quietly */ ! 587: ipc_port_release_send(mem_obj); ! 588: ! 589: ipc_port_dealloc_kernel(mem_obj_control); ! 590: ! 591: return(KERN_SUCCESS); ! 592: } ! 593: ! 594: /* ! 595: * ! 596: */ ! 597: kern_return_t ! 598: vnode_pager_synchronize( ! 599: ipc_port_t pager, ! 600: ipc_port_t pager_request, ! 601: vm_offset_t offset, ! 602: vm_offset_t length, ! 603: vm_sync_t sync_flags) ! 604: { ! 605: memory_object_synchronize_completed(vm_object_lookup(pager_request), offset, length); ! 606: ! 607: return (KERN_SUCCESS); ! 608: } ! 609: ! 610: /* ! 611: * ! 612: */ ! 613: void ! 614: vnode_pager_cluster_write( ! 615: vnode_pager_t vnode_object, ! 616: vm_offset_t offset, ! 617: vm_size_t cnt, ! 618: vm_object_t object) ! 619: { ! 620: vm_offset_t data; ! 621: upl_t page_list; ! 622: int error = 0; ! 623: int size; ! 624: ! 625: upl_system_list_request(object, offset, ! 626: cnt, cnt, &page_list, NULL, 0, ! 627: (UPL_CLEAN_IN_PLACE | UPL_NO_SYNC | UPL_COPYOUT_FROM)); ! 628: upl_map(kernel_map, page_list, &data); ! 629: ! 630: error = vnode_pageout( ! 631: vnode_object->vnode_handle, data, offset, cnt, NULL); ! 632: ! 633: upl_un_map(kernel_map, page_list); ! 634: if (error == 0) { ! 635: upl_commit(page_list, NULL); ! 636: } else { ! 637: upl_abort(page_list, 0); ! 638: } ! 639: ! 640: return; ! 641: } ! 642: ! 643: ! 644: /* ! 645: * ! 646: */ ! 647: kern_return_t ! 648: vnode_pager_cluster_read( ! 649: vnode_pager_t vnode_object, ! 650: vm_offset_t offset, ! 651: vm_size_t cnt, ! 652: vm_object_t object) ! 653: { ! 654: vm_offset_t buffer; ! 655: int error = 0; ! 656: int local_error = 0; ! 657: int kret; ! 658: int size; ! 659: upl_t page_list; ! 660: vm_offset_t base, orig_offset; ! 661: kern_return_t kr; ! 662: ! 663: size = PAGE_SIZE; ! 664: orig_offset = offset; ! 665: base = offset; ! 666: ! 667: kr = upl_system_list_request(object, offset, ! 668: cnt, cnt, &page_list, NULL, 0, ! 669: UPL_CLEAN_IN_PLACE | UPL_NO_SYNC); ! 670: if(kr != KERN_SUCCESS) { ! 671: panic("VNODE_PAGER_CLUSTER_READ: upl_system_list_request failed"); ! 672: } ! 673: kr = upl_map(kernel_map, page_list, &buffer); ! 674: if(kr != KERN_SUCCESS) { ! 675: upl_abort(page_list, UPL_ABORT_RESTART); ! 676: return KERN_SUCCESS; ! 677: } ! 678: ! 679: while (cnt) { ! 680: ! 681: kret = vnode_pagein(vnode_object->vnode_handle, buffer, offset, size, &local_error); ! 682: ! 683: PAGER_DEBUG(PAGER_PAGEIN, ("vnode_pagein ret: vp %x, buf %x buf[0] %x\n", vnode_object->vnode_handle, buffer, *((int *)buffer))); ! 684: ! 685: if (local_error != 0) { ! 686: error = local_error; ! 687: local_error = 0; ! 688: if(offset > base) { ! 689: upl_un_map(kernel_map, page_list); ! 690: upl_commit_range(page_list, base - orig_offset, ! 691: offset - base, FALSE, NULL); ! 692: upl_map(kernel_map, page_list, &buffer); ! 693: } ! 694: base = offset+size; ! 695: } ! 696: ! 697: cnt -= size; ! 698: offset += size; ! 699: } ! 700: ! 701: if(error != 0) { ! 702: upl_un_map(kernel_map, page_list); ! 703: if(offset > base) { ! 704: upl_commit_range(page_list, base - orig_offset, ! 705: offset - base, FALSE, NULL); ! 706: } ! 707: upl_abort(page_list, UPL_ABORT_ERROR); ! 708: return(KERN_FAILURE); ! 709: } ! 710: upl_un_map(kernel_map, page_list); ! 711: upl_commit(page_list, NULL); ! 712: ! 713: return(KERN_SUCCESS); ! 714: } ! 715: ! 716: ! 717: /* ! 718: * ! 719: */ ! 720: void ! 721: vnode_pager_release_from_cache( ! 722: int *cnt) ! 723: { ! 724: memory_object_free_from_cache( ! 725: &realhost, (int)&vnode_pager_workaround, cnt); ! 726: } ! 727: ! 728: /* ! 729: * ! 730: */ ! 731: vnode_pager_t ! 732: vnode_object_create( ! 733: vnode_port_t vp) ! 734: { ! 735: register vnode_pager_t vnode_object; ! 736: ! 737: vnode_object = (struct vnode_pager *) zalloc(vnode_pager_zone); ! 738: if (vnode_object == VNODE_PAGER_NULL) ! 739: return(VNODE_PAGER_NULL); ! 740: vnode_object->pager_handle = IP_NULL; ! 741: vnode_object->vm_obj_handle = IP_NULL; ! 742: vnode_object->vnode_handle = vp; ! 743: ! 744: return(vnode_object); ! 745: } ! 746: ! 747: /* ! 748: * ! 749: */ ! 750: void ! 751: vnode_port_hash_init(void) ! 752: { ! 753: register vm_size_t size; ! 754: register int i; ! 755: ! 756: ! 757: size = (vm_size_t) sizeof(struct vnode_port_entry); ! 758: ! 759: vnode_port_hash_zone = zinit(size, ! 760: (vm_size_t) MAX_VNODE * size, ! 761: PAGE_SIZE, "vnode_pager port hash"); ! 762: ! 763: for (i = 0; i < VNODE_PORT_HASH_COUNT; i++) ! 764: queue_init(&vnode_port_hashtable[i]); ! 765: ! 766: simple_lock_init(&vnode_port_hash_lock,ETAP_NO_TRACE); ! 767: } ! 768: ! 769: /* ! 770: * ! 771: */ ! 772: void ! 773: vnode_port_hash_insert( ! 774: ipc_port_t name_port, ! 775: vnode_pager_t rec) ! 776: { ! 777: register vnode_port_entry_t new_entry; ! 778: ! 779: new_entry = (vnode_port_entry_t) zalloc(vnode_port_hash_zone); ! 780: /* ! 781: * TODO: Delete the following check once MAX_VNODE is removed ! 782: */ ! 783: if (!new_entry) ! 784: panic("vnode_port_hash_insert: no space"); ! 785: new_entry->name = name_port; ! 786: new_entry->pager_rec = rec; ! 787: ! 788: simple_lock(&vnode_port_hash_lock); ! 789: queue_enter(&vnode_port_hashtable[vnode_port_hash(name_port)], ! 790: new_entry, vnode_port_entry_t, links); ! 791: simple_unlock(&vnode_port_hash_lock); ! 792: } ! 793: ! 794: /* ! 795: * ! 796: */ ! 797: vnode_pager_t ! 798: vnode_port_hash_lookup( ! 799: ipc_port_t name_port) ! 800: { ! 801: register queue_t bucket; ! 802: register vnode_port_entry_t entry; ! 803: vnode_pager_t rec; ! 804: ! 805: bucket = (queue_t) &vnode_port_hashtable[vnode_port_hash(name_port)]; ! 806: ! 807: simple_lock(&vnode_port_hash_lock); ! 808: entry = (vnode_port_entry_t) queue_first(bucket); ! 809: while (!queue_end(bucket,&entry->links)) { ! 810: if (entry->name == name_port) { ! 811: rec = entry->pager_rec; ! 812: simple_unlock(&vnode_port_hash_lock); ! 813: return(rec); ! 814: } ! 815: entry = (vnode_port_entry_t)queue_next(&entry->links); ! 816: } ! 817: simple_unlock(&vnode_port_hash_lock); ! 818: return(VNODE_PAGER_NULL); ! 819: } ! 820: ! 821: /* ! 822: * ! 823: */ ! 824: void ! 825: vnode_port_hash_delete( ! 826: ipc_port_t name_port) ! 827: { ! 828: register queue_t bucket; ! 829: register vnode_port_entry_t entry; ! 830: ! 831: bucket = (queue_t) &vnode_port_hashtable[vnode_port_hash(name_port)]; ! 832: ! 833: simple_lock(&vnode_port_hash_lock); ! 834: entry = (vnode_port_entry_t) queue_first(bucket); ! 835: while (!queue_end(bucket,&entry->links)) { ! 836: if (entry->name == name_port) { ! 837: queue_remove(bucket, entry, vnode_port_entry_t,links); ! 838: simple_unlock(&vnode_port_hash_lock); ! 839: zfree(vnode_port_hash_zone, (vm_offset_t) entry); ! 840: return; ! 841: } ! 842: entry = (vnode_port_entry_t)queue_next(&entry->links); ! 843: } ! 844: simple_unlock(&vnode_port_hash_lock); ! 845: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.