]> git.saurik.com Git - apple/xnu.git/blob - osfmk/vm/default_freezer.c
xnu-2050.22.13.tar.gz
[apple/xnu.git] / osfmk / vm / default_freezer.c
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
42 lck_grp_attr_t default_freezer_handle_lck_grp_attr;
43 lck_grp_t default_freezer_handle_lck_grp;
44
45 void
46 default_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
62 default_freezer_mapping_table_t
63 default_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
85 void
86 default_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
102 kern_return_t
103 default_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
138 kern_return_t
139 default_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 */
199 void
200 default_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
233 kern_return_t
234 default_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 */
265 void
266 default_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
299 void
300 default_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
404 void
405 df_memory_object_reference(__unused memory_object_t mem_obj)
406 {
407
408 /* No-op */
409 }
410
411 void
412 df_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
478 kern_return_t
479 df_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
495 kern_return_t
496 df_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
506 kern_return_t
507 df_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
667 kern_return_t
668 df_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
683 kern_return_t
684 df_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
694 kern_return_t
695 df_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
706 kern_return_t
707 df_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
718 kern_return_t
719 df_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
728 kern_return_t
729 df_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
737 kern_return_t
738 df_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
754 void
755 default_freezer_handle_lock(default_freezer_handle_t df_handle) {
756 lck_rw_lock_exclusive(&df_handle->dfh_lck);
757 }
758
759 void
760 default_freezer_handle_unlock(default_freezer_handle_t df_handle) {
761 lck_rw_done(&df_handle->dfh_lck);
762 }
763
764 default_freezer_handle_t
765 default_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
782 kern_return_t
783 default_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
809 void
810 default_freezer_handle_reference_locked(
811 default_freezer_handle_t df_handle)
812 {
813 assert(df_handle);
814 df_handle->dfh_ref_count++;
815 }
816
817 void
818 default_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
828 boolean_t
829 default_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
844 void
845 default_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 */