1/* 2 * Copyright (c) 2000-2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29#if CONFIG_FREEZE 30 31#ifndef CONFIG_MEMORYSTATUS 32#error "CONFIG_FREEZE defined without matching CONFIG_MEMORYSTATUS" 33#endif 34 35#include <vm/default_freezer.h> 36 37/* 38 * Indicates that a page has been faulted back in. 39 */ 40#define FREEZER_OFFSET_ABSENT ((vm_object_offset_t)(-1)) 41 42lck_grp_attr_t default_freezer_handle_lck_grp_attr; 43lck_grp_t default_freezer_handle_lck_grp; 44 45void 46default_freezer_init(void) 47{ 48 lck_grp_attr_setdefault(&default_freezer_handle_lck_grp_attr); 49 lck_grp_init(&default_freezer_handle_lck_grp, "default_freezer_handle", 50 &default_freezer_handle_lck_grp_attr); 51 52} 53 54 55/* 56 * Create the mapping table that will 57 * tell us the object/offset pair that 58 * corresponds to the page being sent 59 * out or being brought back in. 60 */ 61 62default_freezer_mapping_table_t 63default_freezer_mapping_create(vm_object_t object, vm_offset_t offset) 64{ 65 default_freezer_mapping_table_t table; 66 67 table = kalloc(sizeof(struct default_freezer_mapping_table)); 68 if (table) { 69 memset(table, 0, sizeof(*table)); 70 } else { 71 panic("Could not allocate mapping table\n"); 72 } 73 74 table->object = object; 75 table->offset = offset; 76 77 return table; 78} 79 80/* 81 * Table modifications/lookup are done behind 82 * the compact_object lock. 83 */ 84 85void 86default_freezer_mapping_free(default_freezer_mapping_table_t *table_p, boolean_t all) 87{ 88 default_freezer_mapping_table_t freezer_table = *table_p; 89 assert(freezer_table); 90 91 if (all) { 92 do { 93 default_freezer_mapping_table_t next = freezer_table->next; 94 kfree(freezer_table, sizeof(*freezer_table)); 95 freezer_table = next; 96 } while (freezer_table); 97 } else { 98 kfree(freezer_table, sizeof(*freezer_table)); 99 } 100} 101 102kern_return_t 103default_freezer_mapping_store( 104 default_freezer_mapping_table_t table, 105 memory_object_offset_t table_offset, 106 memory_object_t memory_object, 107 memory_object_offset_t offset) 108{ 109 default_freezer_mapping_table_entry_t entry; 110 uint32_t index; 111 112 assert(table); 113 114 while (table->next) { 115 table = table->next; 116 } 117 118 if (table->index >= MAX_FREEZE_TABLE_ENTRIES) { 119 vm_object_t compact_object = table->object; 120 default_freezer_mapping_table_t next; 121 122 next = default_freezer_mapping_create(compact_object, table_offset); 123 if (!next) { 124 return KERN_FAILURE; 125 } 126 table->next = next; 127 } 128 129 index = (table)->index++; 130 entry = &(table)->entry[index]; 131 132 entry->memory_object = memory_object; 133 entry->offset = offset; 134 135 return KERN_SUCCESS; 136} 137 138kern_return_t 139default_freezer_mapping_update( 140 default_freezer_mapping_table_t table, 141 memory_object_t memory_object, 142 memory_object_offset_t offset, 143 memory_object_offset_t *table_offset, /*OUT: contains the offset into the compact object*/ 144 boolean_t remove_entry) 145{ 146 147 kern_return_t kr = KERN_SUCCESS; 148 vm_object_offset_t compact_offset; 149 default_freezer_mapping_table_entry_t entry; 150 uint32_t index = 0; 151 152 if (table == NULL){ 153 return KERN_FAILURE; 154 } 155 156 compact_offset = table->offset; 157 158 while (1) { 159 if (index >= table->index) { 160 if (table->next) { 161 table = table->next; 162 index = 0; 163 } else { 164 /* End of tables and we didn't find our candidate entry */ 165 kr = KERN_FAILURE; 166 break; 167 } 168 } 169 170 entry = &table->entry[index]; 171 172 if (memory_object == entry->memory_object && offset == entry->offset) { 173 if (remove_entry == TRUE) { 174 /* 175 * Mark the page absent whilst retaining the object 176 * for cleanup during thaw. 177 */ 178 entry->offset = FREEZER_OFFSET_ABSENT; 179 } 180 if (table_offset != NULL) { 181 *table_offset = compact_offset; 182 } 183 break; 184 } 185 186 index++; 187 compact_offset += PAGE_SIZE; 188 } 189 return kr; 190} 191 192 193 194/* 195 * Create a freezer memory object for this 196 * vm object. This will be one of the vm 197 * objects that will pack the compact object. 198 */ 199void 200default_freezer_memory_object_create( 201 vm_object_t object, 202 default_freezer_handle_t df_handle) 203{ 204 205 default_freezer_memory_object_t fo = NULL; 206 207 fo = kalloc(sizeof(struct default_freezer_memory_object)); 208 209 if (fo) { 210 memory_object_control_t control = NULL; 211 212 memset(fo, 0, sizeof(*fo)); 213 214 control = memory_object_control_allocate(object); 215 assert (control != MEMORY_OBJECT_CONTROL_NULL); 216 217 df_memory_object_init((memory_object_t)fo, control, 0); 218 fo->fo_df_handle = df_handle; 219 220 default_freezer_handle_reference_locked(fo->fo_df_handle); 221 222 object->pager = (memory_object_t)fo; 223 object->pager_created = TRUE; 224 object->pager_initialized = TRUE; 225 object->pager_ready = TRUE; 226 object->pager_trusted = TRUE; 227 object->pager_control = control; 228 } else { 229 panic(" Could not allocate freezer object\n"); 230 } 231} 232 233kern_return_t 234default_freezer_pack( 235 unsigned int *purgeable_count, 236 unsigned int *wired_count, 237 unsigned int *clean_count, 238 unsigned int *dirty_count, 239 unsigned int dirty_budget, 240 boolean_t *shared, 241 vm_object_t src_object, 242 default_freezer_handle_t df_handle) 243{ 244 kern_return_t kr = KERN_SUCCESS; 245 246 if (df_handle) { 247 default_freezer_handle_lock(df_handle); 248 } 249 250 kr = vm_object_pack(purgeable_count, wired_count, clean_count, dirty_count, dirty_budget, shared, src_object, df_handle); 251 252 if (df_handle) { 253 default_freezer_handle_unlock(df_handle); 254 } 255 256 return kr; 257} 258 259/* 260 * Called with freezer_handle locked. 261 * default_freezer_pack locks the handle, calls 262 * vm_object_pack which, in turn, will call 263 * default_freezer_pack_page(). 264 */ 265void 266default_freezer_pack_page( 267 vm_page_t p, 268 default_freezer_handle_t df_handle) 269{ 270 271 default_freezer_mapping_table_t freeze_table = NULL; 272 memory_object_t memory_object = NULL; 273 vm_object_t compact_object = VM_OBJECT_NULL; 274 275 assert(df_handle); 276 277 compact_object = df_handle->dfh_compact_object; 278 279 assert(compact_object); 280 281 freeze_table = df_handle->dfh_table; 282 memory_object = p->object->pager; 283 284 if (memory_object == NULL) { 285 default_freezer_memory_object_create(p->object, df_handle); 286 memory_object = p->object->pager; 287 } else { 288 assert(df_handle == ((default_freezer_memory_object_t)memory_object)->fo_df_handle); 289 } 290 291 vm_object_lock(compact_object); 292 default_freezer_mapping_store(freeze_table, df_handle->dfh_compact_offset, memory_object, p->offset + p->object->paging_offset); 293 vm_page_rename(p, compact_object, df_handle->dfh_compact_offset, FALSE); 294 vm_object_unlock(compact_object); 295 296 df_handle->dfh_compact_offset += PAGE_SIZE; 297} 298 299void 300default_freezer_unpack( 301 default_freezer_handle_t df_handle) 302{ 303 304 vm_page_t compact_page = VM_PAGE_NULL, src_page = VM_PAGE_NULL; 305 uint32_t index = 0; 306 vm_object_t src_object = VM_OBJECT_NULL; 307 vm_object_t compact_object = VM_OBJECT_NULL; 308 memory_object_t src_mem_object = MEMORY_OBJECT_NULL; 309 memory_object_offset_t src_offset = 0; 310 vm_object_offset_t compact_offset = 0; 311 default_freezer_memory_object_t fo = NULL; 312 default_freezer_mapping_table_t freeze_table = NULL; 313 boolean_t should_unlock_handle = FALSE; 314 315 assert(df_handle); 316 317 default_freezer_handle_lock(df_handle); 318 should_unlock_handle = TRUE; 319 320 freeze_table = df_handle->dfh_table; 321 compact_object = df_handle->dfh_compact_object; 322 323 assert(compact_object); 324 assert(compact_object->alive); 325 assert(!compact_object->terminating); 326 assert(compact_object->pager_ready); 327 328 /* Bring the pages back in */ 329 if (vm_object_pagein(compact_object) != KERN_SUCCESS) { 330 if (should_unlock_handle) { 331 default_freezer_handle_unlock(df_handle); 332 } 333 return; 334 } 335 336 vm_object_lock(compact_object); 337 338 for (index = 0, compact_offset = 0; ; index++, compact_offset += PAGE_SIZE){ 339 if (index >= freeze_table->index) { 340 default_freezer_mapping_table_t table_next; 341 342 table_next = freeze_table->next; 343 344 /* Free the tables as we go along */ 345 default_freezer_mapping_free(&freeze_table, FALSE); 346 347 if (table_next == NULL){ 348 break; 349 } 350 351 freeze_table = table_next; 352 index = 0; 353 } 354 355 /* 356 * Skip slots that represent deallocated memory objects. 357 */ 358 src_mem_object = freeze_table->entry[index].memory_object; 359 if (src_mem_object == MEMORY_OBJECT_NULL) 360 continue; 361 362 /* 363 * Skip slots that represent faulted pages. 364 */ 365 src_offset = freeze_table->entry[index].offset; 366 if (src_offset != FREEZER_OFFSET_ABSENT) { 367 368 compact_page = vm_page_lookup(compact_object, compact_offset); 369 assert(compact_page); 370 371 fo = (default_freezer_memory_object_t)src_mem_object; 372 373 src_object = memory_object_control_to_vm_object(fo->fo_pager_control); 374 375 /* Move back over from the freeze object to the original */ 376 vm_object_lock(src_object); 377 src_page = vm_page_lookup(src_object, src_offset - src_object->paging_offset); 378 if (src_page != VM_PAGE_NULL){ 379 /* 380 * We might be racing with a VM fault. 381 * So handle that gracefully. 382 */ 383 assert(src_page->absent == TRUE); 384 VM_PAGE_FREE(src_page); 385 } 386 vm_page_rename(compact_page, src_object, src_offset - src_object->paging_offset, FALSE); 387 vm_object_unlock(src_object); 388 } 389 390 } 391 392 vm_object_unlock(compact_object); 393 394 vm_object_deallocate(compact_object); 395 396 if (should_unlock_handle) { 397 df_handle->dfh_table = NULL; 398 df_handle->dfh_compact_object = VM_OBJECT_NULL; 399 df_handle->dfh_compact_offset = 0; 400 default_freezer_handle_unlock(df_handle); 401 } 402} 403 404void 405df_memory_object_reference(__unused memory_object_t mem_obj) 406{ 407 408 /* No-op */ 409} 410 411void 412df_memory_object_deallocate(memory_object_t mem_obj) 413{ 414 415 default_freezer_memory_object_t fo = (default_freezer_memory_object_t)mem_obj; 416 417 assert(fo); 418 419 if (fo->fo_df_handle != NULL) { 420 421 default_freezer_mapping_table_t table = NULL; 422 default_freezer_mapping_table_entry_t entry; 423 boolean_t found = FALSE; 424 uint32_t index = 0; 425 vm_object_t compact_object = VM_OBJECT_NULL; 426 427 default_freezer_handle_lock(fo->fo_df_handle); 428 429 compact_object = fo->fo_df_handle->dfh_compact_object; 430 table = fo->fo_df_handle->dfh_table; 431 432 if (compact_object == VM_OBJECT_NULL || table == NULL) { 433 /*Nothing to do. A thaw must have cleared it all out.*/ 434 } else { 435 vm_object_lock(compact_object); 436 437 /* Remove from table */ 438 while (1) { 439 if (index >= table->index) { 440 if (table->next) { 441 table = table->next; 442 index = 0; 443 } else { 444 /* End of tables */ 445 break; 446 } 447 } 448 449 entry = &table->entry[index]; 450 if (mem_obj == entry->memory_object) { 451 /* It matches, so clear the entry */ 452 if (!found) { 453 found = TRUE; 454 } 455 entry->memory_object = MEMORY_OBJECT_NULL; 456 entry->offset = 0; 457 } else if (MEMORY_OBJECT_NULL != entry->memory_object) { 458 /* We have a different valid object; we're done */ 459 if (found) { 460 break; 461 } 462 } 463 464 index++; 465 } 466 467 vm_object_unlock(compact_object); 468 } 469 470 if (default_freezer_handle_deallocate_locked(fo->fo_df_handle)) { 471 default_freezer_handle_unlock(fo->fo_df_handle); 472 } 473 } 474 475 kfree(fo, sizeof(*fo)); 476} 477 478kern_return_t 479df_memory_object_init( 480 memory_object_t mem_obj, 481 memory_object_control_t control, 482 __unused memory_object_cluster_size_t pager_page_size) 483{ 484 485 default_freezer_memory_object_t fo = (default_freezer_memory_object_t)mem_obj; 486 assert(fo); 487 488 fo->fo_pager_ops = &default_freezer_ops; 489 fo->fo_pager_header.io_bits = IKOT_MEMORY_OBJECT; 490 fo->fo_pager_control = control; 491 492 return KERN_SUCCESS; 493} 494 495kern_return_t 496df_memory_object_terminate(memory_object_t mem_obj) 497{ 498 499 default_freezer_memory_object_t fo = (default_freezer_memory_object_t)mem_obj; 500 assert(fo); 501 memory_object_control_deallocate(fo->fo_pager_control); 502 return KERN_SUCCESS; 503} 504 505 506kern_return_t 507df_memory_object_data_request( 508 memory_object_t mem_obj, 509 memory_object_offset_t offset, 510 memory_object_cluster_size_t length, 511 vm_prot_t protection_required, 512 memory_object_fault_info_t fault_info) 513{ 514 515 vm_object_t src_object = VM_OBJECT_NULL, compact_object = VM_OBJECT_NULL; 516 memory_object_offset_t compact_offset = 0; 517 memory_object_t pager = NULL; 518 kern_return_t kr = KERN_SUCCESS; 519 boolean_t drop_object_ref = FALSE; 520 521 default_freezer_memory_object_t fo = (default_freezer_memory_object_t)mem_obj; 522 default_freezer_handle_t df_handle = NULL; 523 524 df_handle = fo->fo_df_handle; 525 526 if (df_handle == NULL) { 527 kr = KERN_FAILURE; 528 } else { 529 default_freezer_handle_lock(df_handle); 530 531 src_object = memory_object_control_to_vm_object(fo->fo_pager_control); 532 compact_object = fo->fo_df_handle->dfh_compact_object; 533 534 if (compact_object == NULL) { 535 kr = KERN_FAILURE; 536 } else { 537 vm_object_lock(compact_object); 538 vm_object_reference_locked(compact_object); 539 drop_object_ref = TRUE; 540 541 kr = default_freezer_mapping_update(fo->fo_df_handle->dfh_table, 542 mem_obj, 543 offset, 544 &compact_offset, 545 FALSE); 546 vm_object_unlock(compact_object); 547 } 548 default_freezer_handle_unlock(df_handle); 549 } 550 551 552 if (length == 0){ 553 /*Caller is just querying to see if we have the page*/ 554 if (drop_object_ref) { 555 vm_object_deallocate(compact_object); 556 } 557 return kr; 558 } 559 560 if (kr != KERN_SUCCESS){ 561 562 unsigned int request_flags; 563 upl_t upl; 564 unsigned int page_list_count = 0; 565 566 request_flags = UPL_NO_SYNC | UPL_RET_ONLY_ABSENT | UPL_SET_LITE; 567 /* 568 * Should we decide to activate USE_PRECIOUS (from default_pager_internal.h) 569 * here, then the request_flags will need to add these to the ones above: 570 * 571 * request_flags |= UPL_PRECIOUS | UPL_CLEAN_IN_PLACE 572 */ 573 request_flags |= UPL_REQUEST_SET_DIRTY; 574 575 memory_object_super_upl_request(fo->fo_pager_control, 576 (memory_object_offset_t)offset, 577 PAGE_SIZE, PAGE_SIZE, 578 &upl, NULL, &page_list_count, 579 request_flags); 580 upl_range_needed(upl, 0, 1); 581 582 upl_abort(upl, UPL_ABORT_UNAVAILABLE); 583 upl_deallocate(upl); 584 585 if (drop_object_ref) { 586 vm_object_deallocate(compact_object); 587 } 588 589 return KERN_SUCCESS; 590 } 591 592 assert(compact_object->alive); 593 assert(!compact_object->terminating); 594 assert(compact_object->pager_ready); 595 596 vm_object_lock(compact_object); 597 598 vm_object_paging_wait(compact_object, THREAD_UNINT); 599 vm_object_paging_begin(compact_object); 600 601 compact_object->blocked_access = TRUE; 602 pager = (memory_object_t)compact_object->pager; 603 604 vm_object_unlock(compact_object); 605 606 ((vm_object_fault_info_t) fault_info)->io_sync = TRUE; 607 608 /* 609 * We have a reference on both the default_freezer 610 * memory object handle and the compact object. 611 */ 612 kr = dp_memory_object_data_request(pager, 613 compact_offset, 614 length, 615 protection_required, 616 fault_info); 617 if (kr == KERN_SUCCESS){ 618 619 vm_page_t compact_page = VM_PAGE_NULL, dst_page = VM_PAGE_NULL; 620 621 vm_object_lock(compact_object); 622 623 compact_object->blocked_access = FALSE; 624 vm_object_paging_end(compact_object); 625 626 vm_object_lock(src_object); 627 628 if ((compact_page = vm_page_lookup(compact_object, compact_offset)) != VM_PAGE_NULL){ 629 630 dst_page = vm_page_lookup(src_object, offset - src_object->paging_offset); 631 632 if (!dst_page->absent){ 633 /* 634 * Someone raced us here and unpacked 635 * the object behind us. 636 * So cleanup before we return. 637 */ 638 VM_PAGE_FREE(compact_page); 639 } else { 640 VM_PAGE_FREE(dst_page); 641 vm_page_rename(compact_page, src_object, offset - src_object->paging_offset, FALSE); 642 643 if (default_freezer_mapping_update(fo->fo_df_handle->dfh_table, 644 mem_obj, 645 offset, 646 NULL, 647 TRUE) != KERN_SUCCESS) { 648 printf("Page for object: 0x%lx at offset: 0x%lx not found in table\n", (uintptr_t)src_object, (uintptr_t)offset); 649 } 650 651 PAGE_WAKEUP_DONE(compact_page); 652 } 653 } else { 654 printf("%d: default_freezer: compact_object doesn't have the page for object 0x%lx at offset 0x%lx \n", kr, (uintptr_t)compact_object, (uintptr_t)compact_offset); 655 kr = KERN_SUCCESS; 656 } 657 vm_object_unlock(src_object); 658 vm_object_unlock(compact_object); 659 vm_object_deallocate(compact_object); 660 } else { 661 panic("%d: default_freezer TOC pointed us to default_pager incorrectly\n", kr); 662 } 663 664 return kr; 665} 666 667kern_return_t 668df_memory_object_data_return( 669 __unused memory_object_t mem_obj, 670 __unused memory_object_offset_t offset, 671 __unused memory_object_cluster_size_t size, 672 __unused memory_object_offset_t *resid_offset, 673 __unused int *io_error, 674 __unused boolean_t dirty, 675 __unused boolean_t kernel_copy, 676 __unused int upl_flags) 677{ 678 679 panic(" default_freezer: df_memory_object_data_return should not be called\n"); 680 return KERN_SUCCESS; 681} 682 683kern_return_t 684df_memory_object_data_initialize( 685 __unused memory_object_t mem_obj, 686 __unused memory_object_offset_t offset, 687 __unused memory_object_cluster_size_t size) 688{ 689 690 panic(" default_freezer: df_memory_object_data_initialize should not be called\n"); 691 return KERN_SUCCESS; 692} 693 694kern_return_t 695df_memory_object_data_unlock( 696 __unused memory_object_t mem_obj, 697 __unused memory_object_offset_t offset, 698 __unused memory_object_size_t length, 699 __unused vm_prot_t prot) 700{ 701 702 panic(" default_freezer: df_memory_object_data_unlock should not be called\n"); 703 return KERN_FAILURE; 704} 705 706kern_return_t 707df_memory_object_synchronize( 708 __unused memory_object_t mem_obj, 709 __unused memory_object_offset_t offset, 710 __unused memory_object_size_t length, 711 __unused vm_sync_t flags) 712{ 713 714 panic(" default_freezer: df_memory_object_synchronize should not be called\n"); 715 return KERN_FAILURE; 716} 717 718kern_return_t 719df_memory_object_map( 720 __unused memory_object_t mem_obj, 721 __unused vm_prot_t prot) 722{ 723 724 panic(" default_freezer: df_memory_object_map should not be called\n"); 725 return KERN_FAILURE; 726} 727 728kern_return_t 729df_memory_object_last_unmap(__unused memory_object_t mem_obj) 730{ 731 732 panic(" default_freezer: df_memory_object_last_unmap should not be called\n"); 733 return KERN_FAILURE; 734} 735 736 737kern_return_t 738df_memory_object_data_reclaim( 739 __unused memory_object_t mem_obj, 740 __unused boolean_t reclaim_backing_store) 741{ 742 743 panic("df_memory_object_data_reclaim\n"); 744 return KERN_SUCCESS; 745} 746 747 748/* 749 * The freezer handle is used to make sure that 750 * we don't race against the lookup and termination 751 * of the compact object. 752 */ 753 754void 755default_freezer_handle_lock(default_freezer_handle_t df_handle) { 756 lck_rw_lock_exclusive(&df_handle->dfh_lck); 757} 758 759void 760default_freezer_handle_unlock(default_freezer_handle_t df_handle) { 761 lck_rw_done(&df_handle->dfh_lck); 762} 763 764default_freezer_handle_t 765default_freezer_handle_allocate(void) 766{ 767 768 default_freezer_handle_t df_handle = NULL; 769 df_handle = kalloc(sizeof(struct default_freezer_handle)); 770 771 if (df_handle) { 772 memset(df_handle, 0, sizeof(struct default_freezer_handle)); 773 lck_rw_init(&df_handle->dfh_lck, &default_freezer_handle_lck_grp, NULL); 774 /* No one knows of this handle yet so no need to lock it. */ 775 default_freezer_handle_reference_locked(df_handle); 776 } else { 777 panic("Failed to allocated default_freezer_handle structure\n"); 778 } 779 return df_handle; 780} 781 782kern_return_t 783default_freezer_handle_init( 784 default_freezer_handle_t df_handle) 785{ 786 kern_return_t kr = KERN_SUCCESS; 787 vm_object_t compact_object = VM_OBJECT_NULL; 788 789 if (df_handle == NULL || df_handle->dfh_table != NULL) { 790 kr = KERN_FAILURE; 791 } else { 792 /* Create our compact object */ 793 compact_object = vm_object_allocate((vm_map_offset_t)(VM_MAX_ADDRESS) - (vm_map_offset_t)(VM_MIN_ADDRESS)); 794 if (!compact_object) { 795 kr = KERN_FAILURE; 796 } else { 797 df_handle->dfh_compact_object = compact_object; 798 df_handle->dfh_compact_offset = 0; 799 df_handle->dfh_table = default_freezer_mapping_create(df_handle->dfh_compact_object, df_handle->dfh_compact_offset); 800 if (!df_handle->dfh_table) { 801 kr = KERN_FAILURE; 802 } 803 } 804 } 805 806 return kr; 807} 808 809void 810default_freezer_handle_reference_locked( 811 default_freezer_handle_t df_handle) 812{ 813 assert(df_handle); 814 df_handle->dfh_ref_count++; 815} 816 817void 818default_freezer_handle_deallocate( 819 default_freezer_handle_t df_handle) 820{ 821 assert(df_handle); 822 default_freezer_handle_lock(df_handle); 823 if (default_freezer_handle_deallocate_locked(df_handle)) { 824 default_freezer_handle_unlock(df_handle); 825 } 826} 827 828boolean_t 829default_freezer_handle_deallocate_locked( 830 default_freezer_handle_t df_handle) 831{ 832 boolean_t should_unlock = TRUE; 833 834 assert(df_handle); 835 df_handle->dfh_ref_count--; 836 if (df_handle->dfh_ref_count == 0) { 837 lck_rw_destroy(&df_handle->dfh_lck, &default_freezer_handle_lck_grp); 838 kfree(df_handle, sizeof(struct default_freezer_handle)); 839 should_unlock = FALSE; 840 } 841 return should_unlock; 842} 843 844void 845default_freezer_pageout( 846 default_freezer_handle_t df_handle) 847{ 848 assert(df_handle); 849 850 vm_object_pageout(df_handle->dfh_compact_object); 851} 852 853#endif /* CONFIG_FREEZE */ 854