]> git.saurik.com Git - apple/xnu.git/blob - osfmk/vm/memory_object.c
xnu-344.2.tar.gz
[apple/xnu.git] / osfmk / vm / memory_object.c
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 * @OSF_COPYRIGHT@
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 Software.Distribution@CS.CMU.EDU
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 */
52 /*
53 * File: vm/memory_object.c
54 * Author: Michael Wayne Young
55 *
56 * External memory management interface control functions.
57 */
58
59 #include <advisory_pageout.h>
60
61 /*
62 * Interface dependencies:
63 */
64
65 #include <mach/std_types.h> /* For pointer_t */
66 #include <mach/mach_types.h>
67
68 #include <mach/mig.h>
69 #include <mach/kern_return.h>
70 #include <mach/memory_object.h>
71 #include <mach/memory_object_default.h>
72 #include <mach/memory_object_control_server.h>
73 #include <mach/host_priv_server.h>
74 #include <mach/boolean.h>
75 #include <mach/vm_prot.h>
76 #include <mach/message.h>
77
78 /*
79 * Implementation dependencies:
80 */
81 #include <string.h> /* For memcpy() */
82
83 #include <kern/xpr.h>
84 #include <kern/host.h>
85 #include <kern/thread.h> /* For current_thread() */
86 #include <kern/ipc_mig.h>
87 #include <kern/misc_protos.h>
88
89 #include <vm/vm_object.h>
90 #include <vm/vm_fault.h>
91 #include <vm/memory_object.h>
92 #include <vm/vm_page.h>
93 #include <vm/vm_pageout.h>
94 #include <vm/pmap.h> /* For pmap_clear_modify */
95 #include <vm/vm_kern.h> /* For kernel_map, vm_move */
96 #include <vm/vm_map.h> /* For vm_map_pageable */
97
98 #if MACH_PAGEMAP
99 #include <vm/vm_external.h>
100 #endif /* MACH_PAGEMAP */
101
102
103 memory_object_default_t memory_manager_default = MEMORY_OBJECT_DEFAULT_NULL;
104 vm_size_t memory_manager_default_cluster = 0;
105 decl_mutex_data(, memory_manager_default_lock)
106
107 /*
108 * Forward ref to file-local function:
109 */
110 boolean_t
111 vm_object_update(vm_object_t, vm_object_offset_t,
112 vm_size_t, memory_object_return_t, int, vm_prot_t);
113
114
115 /*
116 * Routine: memory_object_should_return_page
117 *
118 * Description:
119 * Determine whether the given page should be returned,
120 * based on the page's state and on the given return policy.
121 *
122 * We should return the page if one of the following is true:
123 *
124 * 1. Page is dirty and should_return is not RETURN_NONE.
125 * 2. Page is precious and should_return is RETURN_ALL.
126 * 3. Should_return is RETURN_ANYTHING.
127 *
128 * As a side effect, m->dirty will be made consistent
129 * with pmap_is_modified(m), if should_return is not
130 * MEMORY_OBJECT_RETURN_NONE.
131 */
132
133 #define memory_object_should_return_page(m, should_return) \
134 (should_return != MEMORY_OBJECT_RETURN_NONE && \
135 (((m)->dirty || ((m)->dirty = pmap_is_modified((m)->phys_addr))) || \
136 ((m)->precious && (should_return) == MEMORY_OBJECT_RETURN_ALL) || \
137 (should_return) == MEMORY_OBJECT_RETURN_ANYTHING))
138
139 typedef int memory_object_lock_result_t;
140
141 #define MEMORY_OBJECT_LOCK_RESULT_DONE 0
142 #define MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK 1
143 #define MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN 2
144 #define MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN 3
145
146 memory_object_lock_result_t memory_object_lock_page(
147 vm_page_t m,
148 memory_object_return_t should_return,
149 boolean_t should_flush,
150 vm_prot_t prot);
151
152 /*
153 * Routine: memory_object_lock_page
154 *
155 * Description:
156 * Perform the appropriate lock operations on the
157 * given page. See the description of
158 * "memory_object_lock_request" for the meanings
159 * of the arguments.
160 *
161 * Returns an indication that the operation
162 * completed, blocked, or that the page must
163 * be cleaned.
164 */
165 memory_object_lock_result_t
166 memory_object_lock_page(
167 vm_page_t m,
168 memory_object_return_t should_return,
169 boolean_t should_flush,
170 vm_prot_t prot)
171 {
172 XPR(XPR_MEMORY_OBJECT,
173 "m_o_lock_page, page 0x%X rtn %d flush %d prot %d\n",
174 (integer_t)m, should_return, should_flush, prot, 0);
175
176 /*
177 * If we cannot change access to the page,
178 * either because a mapping is in progress
179 * (busy page) or because a mapping has been
180 * wired, then give up.
181 */
182
183 if (m->busy || m->cleaning)
184 return(MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK);
185
186 /*
187 * Don't worry about pages for which the kernel
188 * does not have any data.
189 */
190
191 if (m->absent || m->error || m->restart) {
192 if(m->error && should_flush) {
193 /* dump the page, pager wants us to */
194 /* clean it up and there is no */
195 /* relevant data to return */
196 if(m->wire_count == 0) {
197 VM_PAGE_FREE(m);
198 return(MEMORY_OBJECT_LOCK_RESULT_DONE);
199 }
200 } else {
201 return(MEMORY_OBJECT_LOCK_RESULT_DONE);
202 }
203 }
204
205 assert(!m->fictitious);
206
207 if (m->wire_count != 0) {
208 /*
209 * If no change would take place
210 * anyway, return successfully.
211 *
212 * No change means:
213 * Not flushing AND
214 * No change to page lock [2 checks] AND
215 * Should not return page
216 *
217 * XXX This doesn't handle sending a copy of a wired
218 * XXX page to the pager, but that will require some
219 * XXX significant surgery.
220 */
221 if (!should_flush &&
222 (m->page_lock == prot || prot == VM_PROT_NO_CHANGE) &&
223 ! memory_object_should_return_page(m, should_return)) {
224
225 /*
226 * Restart page unlock requests,
227 * even though no change took place.
228 * [Memory managers may be expecting
229 * to see new requests.]
230 */
231 m->unlock_request = VM_PROT_NONE;
232 PAGE_WAKEUP(m);
233
234 return(MEMORY_OBJECT_LOCK_RESULT_DONE);
235 }
236
237 return(MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK);
238 }
239
240 /*
241 * If the page is to be flushed, allow
242 * that to be done as part of the protection.
243 */
244
245 if (should_flush)
246 prot = VM_PROT_ALL;
247
248 /*
249 * Set the page lock.
250 *
251 * If we are decreasing permission, do it now;
252 * let the fault handler take care of increases
253 * (pmap_page_protect may not increase protection).
254 */
255
256 if (prot != VM_PROT_NO_CHANGE) {
257 if ((m->page_lock ^ prot) & prot) {
258 pmap_page_protect(m->phys_addr, VM_PROT_ALL & ~prot);
259 }
260 #if 0
261 /* code associated with the vestigial
262 * memory_object_data_unlock
263 */
264 m->page_lock = prot;
265 m->lock_supplied = TRUE;
266 if (prot != VM_PROT_NONE)
267 m->unusual = TRUE;
268 else
269 m->unusual = FALSE;
270
271 /*
272 * Restart any past unlock requests, even if no
273 * change resulted. If the manager explicitly
274 * requested no protection change, then it is assumed
275 * to be remembering past requests.
276 */
277
278 m->unlock_request = VM_PROT_NONE;
279 #endif /* 0 */
280 PAGE_WAKEUP(m);
281 }
282
283 /*
284 * Handle page returning.
285 */
286
287 if (memory_object_should_return_page(m, should_return)) {
288
289 /*
290 * If we weren't planning
291 * to flush the page anyway,
292 * we may need to remove the
293 * page from the pageout
294 * system and from physical
295 * maps now.
296 */
297
298 vm_page_lock_queues();
299 VM_PAGE_QUEUES_REMOVE(m);
300 vm_page_unlock_queues();
301
302 if (!should_flush)
303 pmap_page_protect(m->phys_addr, VM_PROT_NONE);
304
305 if (m->dirty)
306 return(MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN);
307 else
308 return(MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN);
309 }
310
311 /*
312 * Handle flushing
313 */
314
315 if (should_flush) {
316 VM_PAGE_FREE(m);
317 } else {
318 extern boolean_t vm_page_deactivate_hint;
319
320 /*
321 * XXX Make clean but not flush a paging hint,
322 * and deactivate the pages. This is a hack
323 * because it overloads flush/clean with
324 * implementation-dependent meaning. This only
325 * happens to pages that are already clean.
326 */
327
328 if (vm_page_deactivate_hint &&
329 (should_return != MEMORY_OBJECT_RETURN_NONE)) {
330 vm_page_lock_queues();
331 vm_page_deactivate(m);
332 vm_page_unlock_queues();
333 }
334 }
335
336 return(MEMORY_OBJECT_LOCK_RESULT_DONE);
337 }
338
339 #define LIST_REQ_PAGEOUT_PAGES(object, data_cnt, action, po) \
340 MACRO_BEGIN \
341 \
342 register int i; \
343 register vm_page_t hp; \
344 \
345 vm_object_unlock(object); \
346 \
347 (void) memory_object_data_return(object->pager, \
348 po, \
349 data_cnt, \
350 (action == MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN), \
351 !should_flush); \
352 \
353 vm_object_lock(object); \
354 MACRO_END
355
356 /*
357 * Routine: memory_object_lock_request [user interface]
358 *
359 * Description:
360 * Control use of the data associated with the given
361 * memory object. For each page in the given range,
362 * perform the following operations, in order:
363 * 1) restrict access to the page (disallow
364 * forms specified by "prot");
365 * 2) return data to the manager (if "should_return"
366 * is RETURN_DIRTY and the page is dirty, or
367 * "should_return" is RETURN_ALL and the page
368 * is either dirty or precious); and,
369 * 3) flush the cached copy (if "should_flush"
370 * is asserted).
371 * The set of pages is defined by a starting offset
372 * ("offset") and size ("size"). Only pages with the
373 * same page alignment as the starting offset are
374 * considered.
375 *
376 * A single acknowledgement is sent (to the "reply_to"
377 * port) when these actions are complete. If successful,
378 * the naked send right for reply_to is consumed.
379 */
380
381 kern_return_t
382 memory_object_lock_request(
383 memory_object_control_t control,
384 memory_object_offset_t offset,
385 memory_object_size_t size,
386 memory_object_return_t should_return,
387 int flags,
388 vm_prot_t prot)
389 {
390 vm_object_t object;
391 vm_object_offset_t original_offset = offset;
392 boolean_t should_flush=flags & MEMORY_OBJECT_DATA_FLUSH;
393
394 XPR(XPR_MEMORY_OBJECT,
395 "m_o_lock_request, control 0x%X off 0x%X size 0x%X flags %X prot %X\n",
396 (integer_t)control, offset, size,
397 (((should_return&1)<<1)|should_flush), prot);
398
399 /*
400 * Check for bogus arguments.
401 */
402 object = memory_object_control_to_vm_object(control);
403 if (object == VM_OBJECT_NULL)
404 return (KERN_INVALID_ARGUMENT);
405
406 if ((prot & ~VM_PROT_ALL) != 0 && prot != VM_PROT_NO_CHANGE)
407 return (KERN_INVALID_ARGUMENT);
408
409 size = round_page(size);
410
411 /*
412 * Lock the object, and acquire a paging reference to
413 * prevent the memory_object reference from being released.
414 */
415 vm_object_lock(object);
416 vm_object_paging_begin(object);
417 offset -= object->paging_offset;
418
419 (void)vm_object_update(object,
420 offset, size, should_return, flags, prot);
421
422 vm_object_paging_end(object);
423 vm_object_unlock(object);
424
425 return (KERN_SUCCESS);
426 }
427
428 /*
429 * memory_object_release_name: [interface]
430 *
431 * Enforces name semantic on memory_object reference count decrement
432 * This routine should not be called unless the caller holds a name
433 * reference gained through the memory_object_named_create or the
434 * memory_object_rename call.
435 * If the TERMINATE_IDLE flag is set, the call will return if the
436 * reference count is not 1. i.e. idle with the only remaining reference
437 * being the name.
438 * If the decision is made to proceed the name field flag is set to
439 * false and the reference count is decremented. If the RESPECT_CACHE
440 * flag is set and the reference count has gone to zero, the
441 * memory_object is checked to see if it is cacheable otherwise when
442 * the reference count is zero, it is simply terminated.
443 */
444
445 kern_return_t
446 memory_object_release_name(
447 memory_object_control_t control,
448 int flags)
449 {
450 vm_object_t object;
451
452 object = memory_object_control_to_vm_object(control);
453 if (object == VM_OBJECT_NULL)
454 return (KERN_INVALID_ARGUMENT);
455
456 return vm_object_release_name(object, flags);
457 }
458
459
460
461 /*
462 * Routine: memory_object_destroy [user interface]
463 * Purpose:
464 * Shut down a memory object, despite the
465 * presence of address map (or other) references
466 * to the vm_object.
467 */
468 kern_return_t
469 memory_object_destroy(
470 memory_object_control_t control,
471 kern_return_t reason)
472 {
473 vm_object_t object;
474
475 object = memory_object_control_to_vm_object(control);
476 if (object == VM_OBJECT_NULL)
477 return (KERN_INVALID_ARGUMENT);
478
479 return (vm_object_destroy(object, reason));
480 }
481
482 /*
483 * Routine: vm_object_sync
484 *
485 * Kernel internal function to synch out pages in a given
486 * range within an object to its memory manager. Much the
487 * same as memory_object_lock_request but page protection
488 * is not changed.
489 *
490 * If the should_flush and should_return flags are true pages
491 * are flushed, that is dirty & precious pages are written to
492 * the memory manager and then discarded. If should_return
493 * is false, only precious pages are returned to the memory
494 * manager.
495 *
496 * If should flush is false and should_return true, the memory
497 * manager's copy of the pages is updated. If should_return
498 * is also false, only the precious pages are updated. This
499 * last option is of limited utility.
500 *
501 * Returns:
502 * FALSE if no pages were returned to the pager
503 * TRUE otherwise.
504 */
505
506 boolean_t
507 vm_object_sync(
508 vm_object_t object,
509 vm_object_offset_t offset,
510 vm_size_t size,
511 boolean_t should_flush,
512 boolean_t should_return)
513 {
514 boolean_t rv;
515
516 XPR(XPR_VM_OBJECT,
517 "vm_o_sync, object 0x%X, offset 0x%X size 0x%x flush %d rtn %d\n",
518 (integer_t)object, offset, size, should_flush, should_return);
519
520 /*
521 * Lock the object, and acquire a paging reference to
522 * prevent the memory_object and control ports from
523 * being destroyed.
524 */
525 vm_object_lock(object);
526 vm_object_paging_begin(object);
527
528 rv = vm_object_update(object, offset, size,
529 (should_return) ?
530 MEMORY_OBJECT_RETURN_ALL :
531 MEMORY_OBJECT_RETURN_NONE,
532 (should_flush) ?
533 MEMORY_OBJECT_DATA_FLUSH : 0,
534 VM_PROT_NO_CHANGE);
535
536
537 vm_object_paging_end(object);
538 vm_object_unlock(object);
539 return rv;
540 }
541
542 /*
543 * Routine: vm_object_update
544 * Description:
545 * Work function for m_o_lock_request(), vm_o_sync().
546 *
547 * Called with object locked and paging ref taken.
548 */
549 kern_return_t
550 vm_object_update(
551 register vm_object_t object,
552 register vm_object_offset_t offset,
553 register vm_size_t size,
554 memory_object_return_t should_return,
555 int flags,
556 vm_prot_t prot)
557 {
558 register vm_page_t m;
559 vm_page_t holding_page;
560 vm_size_t original_size = size;
561 vm_object_offset_t paging_offset = 0;
562 vm_object_t copy_object;
563 vm_size_t data_cnt = 0;
564 vm_object_offset_t last_offset = offset;
565 memory_object_lock_result_t page_lock_result;
566 memory_object_lock_result_t pageout_action;
567 boolean_t data_returned = FALSE;
568 boolean_t update_cow;
569 boolean_t should_flush = flags & MEMORY_OBJECT_DATA_FLUSH;
570 boolean_t pending_pageout = FALSE;
571
572 /*
573 * To avoid blocking while scanning for pages, save
574 * dirty pages to be cleaned all at once.
575 *
576 * XXXO A similar strategy could be used to limit the
577 * number of times that a scan must be restarted for
578 * other reasons. Those pages that would require blocking
579 * could be temporarily collected in another list, or
580 * their offsets could be recorded in a small array.
581 */
582
583 /*
584 * XXX NOTE: May want to consider converting this to a page list
585 * XXX vm_map_copy interface. Need to understand object
586 * XXX coalescing implications before doing so.
587 */
588
589 update_cow = ((flags & MEMORY_OBJECT_DATA_FLUSH)
590 && (!(flags & MEMORY_OBJECT_DATA_NO_CHANGE) &&
591 !(flags & MEMORY_OBJECT_DATA_PURGE)))
592 || (flags & MEMORY_OBJECT_COPY_SYNC);
593
594
595 if((((copy_object = object->copy) != NULL) && update_cow) ||
596 (flags & MEMORY_OBJECT_DATA_SYNC)) {
597 vm_size_t i;
598 vm_size_t copy_size;
599 vm_object_offset_t copy_offset;
600 vm_prot_t prot;
601 vm_page_t page;
602 vm_page_t top_page;
603 kern_return_t error = 0;
604
605 if(copy_object != NULL) {
606 /* translate offset with respect to shadow's offset */
607 copy_offset = (offset >= copy_object->shadow_offset)?
608 offset - copy_object->shadow_offset :
609 (vm_object_offset_t) 0;
610 if(copy_offset > copy_object->size)
611 copy_offset = copy_object->size;
612
613 /* clip size with respect to shadow offset */
614 copy_size = (offset >= copy_object->shadow_offset) ?
615 size : size - (copy_object->shadow_offset - offset);
616
617 if(copy_size <= 0) {
618 copy_size = 0;
619 } else {
620 copy_size = ((copy_offset + copy_size)
621 <= copy_object->size) ?
622 copy_size : copy_object->size - copy_offset;
623 }
624 /* check for a copy_offset which is beyond the end of */
625 /* the copy_object */
626 if(copy_size < 0)
627 copy_size = 0;
628
629 copy_size+=offset;
630
631 vm_object_unlock(object);
632 vm_object_lock(copy_object);
633 } else {
634 copy_object = object;
635
636 copy_size = offset + size;
637 copy_offset = offset;
638 }
639
640 vm_object_paging_begin(copy_object);
641 for (i=copy_offset; i<copy_size; i+=PAGE_SIZE) {
642 RETRY_COW_OF_LOCK_REQUEST:
643 prot = VM_PROT_WRITE|VM_PROT_READ;
644 switch (vm_fault_page(copy_object, i,
645 VM_PROT_WRITE|VM_PROT_READ,
646 FALSE,
647 THREAD_UNINT,
648 copy_offset,
649 copy_offset+copy_size,
650 VM_BEHAVIOR_SEQUENTIAL,
651 &prot,
652 &page,
653 &top_page,
654 (int *)0,
655 &error,
656 FALSE,
657 FALSE, NULL, 0)) {
658
659 case VM_FAULT_SUCCESS:
660 if(top_page) {
661 vm_fault_cleanup(
662 page->object, top_page);
663 PAGE_WAKEUP_DONE(page);
664 vm_page_lock_queues();
665 if (!page->active && !page->inactive)
666 vm_page_activate(page);
667 vm_page_unlock_queues();
668 vm_object_lock(copy_object);
669 vm_object_paging_begin(copy_object);
670 } else {
671 PAGE_WAKEUP_DONE(page);
672 vm_page_lock_queues();
673 if (!page->active && !page->inactive)
674 vm_page_activate(page);
675 vm_page_unlock_queues();
676 }
677 break;
678 case VM_FAULT_RETRY:
679 prot = VM_PROT_WRITE|VM_PROT_READ;
680 vm_object_lock(copy_object);
681 vm_object_paging_begin(copy_object);
682 goto RETRY_COW_OF_LOCK_REQUEST;
683 case VM_FAULT_INTERRUPTED:
684 prot = VM_PROT_WRITE|VM_PROT_READ;
685 vm_object_lock(copy_object);
686 vm_object_paging_begin(copy_object);
687 goto RETRY_COW_OF_LOCK_REQUEST;
688 case VM_FAULT_MEMORY_SHORTAGE:
689 VM_PAGE_WAIT();
690 prot = VM_PROT_WRITE|VM_PROT_READ;
691 vm_object_lock(copy_object);
692 vm_object_paging_begin(copy_object);
693 goto RETRY_COW_OF_LOCK_REQUEST;
694 case VM_FAULT_FICTITIOUS_SHORTAGE:
695 vm_page_more_fictitious();
696 prot = VM_PROT_WRITE|VM_PROT_READ;
697 vm_object_lock(copy_object);
698 vm_object_paging_begin(copy_object);
699 goto RETRY_COW_OF_LOCK_REQUEST;
700 case VM_FAULT_MEMORY_ERROR:
701 vm_object_lock(object);
702 goto BYPASS_COW_COPYIN;
703 }
704
705 }
706 vm_object_paging_end(copy_object);
707 if(copy_object != object) {
708 vm_object_unlock(copy_object);
709 vm_object_lock(object);
710 }
711 }
712 if((flags & (MEMORY_OBJECT_DATA_SYNC | MEMORY_OBJECT_COPY_SYNC))) {
713 return KERN_SUCCESS;
714 }
715 if(((copy_object = object->copy) != NULL) &&
716 (flags & MEMORY_OBJECT_DATA_PURGE)) {
717 copy_object->shadow_severed = TRUE;
718 copy_object->shadowed = FALSE;
719 copy_object->shadow = NULL;
720 /* delete the ref the COW was holding on the target object */
721 vm_object_deallocate(object);
722 }
723 BYPASS_COW_COPYIN:
724
725 for (;
726 size != 0;
727 size -= PAGE_SIZE, offset += PAGE_SIZE_64)
728 {
729 /*
730 * Limit the number of pages to be cleaned at once.
731 */
732 if (pending_pageout &&
733 data_cnt >= PAGE_SIZE * DATA_WRITE_MAX)
734 {
735 LIST_REQ_PAGEOUT_PAGES(object, data_cnt,
736 pageout_action, paging_offset);
737 data_cnt = 0;
738 pending_pageout = FALSE;
739 }
740
741 while ((m = vm_page_lookup(object, offset)) != VM_PAGE_NULL) {
742 page_lock_result = memory_object_lock_page(m, should_return,
743 should_flush, prot);
744
745 XPR(XPR_MEMORY_OBJECT,
746 "m_o_update: lock_page, obj 0x%X offset 0x%X result %d\n",
747 (integer_t)object, offset, page_lock_result, 0, 0);
748
749 switch (page_lock_result)
750 {
751 case MEMORY_OBJECT_LOCK_RESULT_DONE:
752 /*
753 * End of a cluster of dirty pages.
754 */
755 if(pending_pageout) {
756 LIST_REQ_PAGEOUT_PAGES(object,
757 data_cnt, pageout_action,
758 paging_offset);
759 data_cnt = 0;
760 pending_pageout = FALSE;
761 continue;
762 }
763 break;
764
765 case MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK:
766 /*
767 * Since it is necessary to block,
768 * clean any dirty pages now.
769 */
770 if(pending_pageout) {
771 LIST_REQ_PAGEOUT_PAGES(object,
772 data_cnt, pageout_action,
773 paging_offset);
774 pending_pageout = FALSE;
775 data_cnt = 0;
776 continue;
777 }
778
779 PAGE_SLEEP(object, m, THREAD_UNINT);
780 continue;
781
782 case MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN:
783 case MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN:
784 /*
785 * The clean and return cases are similar.
786 *
787 */
788
789 /*
790 * if this would form a discontiguous block,
791 * clean the old pages and start anew.
792 *
793 */
794
795 /*
796 * Mark the page busy since we unlock the
797 * object below.
798 */
799 m->busy = TRUE;
800 if (pending_pageout &&
801 (last_offset != offset ||
802 pageout_action != page_lock_result)) {
803 LIST_REQ_PAGEOUT_PAGES(object,
804 data_cnt, pageout_action,
805 paging_offset);
806 pending_pageout = FALSE;
807 data_cnt = 0;
808 }
809 m->busy = FALSE;
810 holding_page = VM_PAGE_NULL;
811 if(m->cleaning) {
812 PAGE_SLEEP(object, m, THREAD_UNINT);
813 continue;
814 }
815 if(!pending_pageout) {
816 pending_pageout = TRUE;
817 pageout_action = page_lock_result;
818 paging_offset = offset;
819 }
820 if (should_flush) {
821 vm_page_lock_queues();
822 m->list_req_pending = TRUE;
823 m->cleaning = TRUE;
824 m->busy = TRUE;
825 m->pageout = TRUE;
826 vm_page_wire(m);
827 vm_page_unlock_queues();
828 } else {
829 /*
830 * Clean but do not flush
831 */
832 vm_page_lock_queues();
833 m->list_req_pending = TRUE;
834 m->cleaning = TRUE;
835 vm_page_unlock_queues();
836
837 }
838 vm_object_unlock(object);
839
840
841 data_cnt += PAGE_SIZE;
842 last_offset = offset + PAGE_SIZE_64;
843 data_returned = TRUE;
844
845 vm_object_lock(object);
846 break;
847 }
848 break;
849 }
850 }
851
852 /*
853 * We have completed the scan for applicable pages.
854 * Clean any pages that have been saved.
855 */
856 if (pending_pageout) {
857 LIST_REQ_PAGEOUT_PAGES(object,
858 data_cnt, pageout_action, paging_offset);
859 }
860 return (data_returned);
861 }
862
863 /*
864 * Routine: memory_object_synchronize_completed [user interface]
865 *
866 * Tell kernel that previously synchronized data
867 * (memory_object_synchronize) has been queue or placed on the
868 * backing storage.
869 *
870 * Note: there may be multiple synchronize requests for a given
871 * memory object outstanding but they will not overlap.
872 */
873
874 kern_return_t
875 memory_object_synchronize_completed(
876 memory_object_control_t control,
877 memory_object_offset_t offset,
878 vm_offset_t length)
879 {
880 vm_object_t object;
881 msync_req_t msr;
882
883 XPR(XPR_MEMORY_OBJECT,
884 "m_o_sync_completed, object 0x%X, offset 0x%X length 0x%X\n",
885 (integer_t)object, offset, length, 0, 0);
886
887 /*
888 * Look for bogus arguments
889 */
890
891 object = memory_object_control_to_vm_object(control);
892 if (object == VM_OBJECT_NULL)
893 return (KERN_INVALID_ARGUMENT);
894
895 vm_object_lock(object);
896
897 /*
898 * search for sync request structure
899 */
900 queue_iterate(&object->msr_q, msr, msync_req_t, msr_q) {
901 if (msr->offset == offset && msr->length == length) {
902 queue_remove(&object->msr_q, msr, msync_req_t, msr_q);
903 break;
904 }
905 }/* queue_iterate */
906
907 if (queue_end(&object->msr_q, (queue_entry_t)msr)) {
908 vm_object_unlock(object);
909 return KERN_INVALID_ARGUMENT;
910 }
911
912 msr_lock(msr);
913 vm_object_unlock(object);
914 msr->flag = VM_MSYNC_DONE;
915 msr_unlock(msr);
916 thread_wakeup((event_t) msr);
917
918 return KERN_SUCCESS;
919 }/* memory_object_synchronize_completed */
920
921 static kern_return_t
922 vm_object_set_attributes_common(
923 vm_object_t object,
924 boolean_t may_cache,
925 memory_object_copy_strategy_t copy_strategy,
926 boolean_t temporary,
927 vm_size_t cluster_size,
928 boolean_t silent_overwrite,
929 boolean_t advisory_pageout)
930 {
931 boolean_t object_became_ready;
932
933 XPR(XPR_MEMORY_OBJECT,
934 "m_o_set_attr_com, object 0x%X flg %x strat %d\n",
935 (integer_t)object, (may_cache&1)|((temporary&1)<1), copy_strategy, 0, 0);
936
937 if (object == VM_OBJECT_NULL)
938 return(KERN_INVALID_ARGUMENT);
939
940 /*
941 * Verify the attributes of importance
942 */
943
944 switch(copy_strategy) {
945 case MEMORY_OBJECT_COPY_NONE:
946 case MEMORY_OBJECT_COPY_DELAY:
947 break;
948 default:
949 return(KERN_INVALID_ARGUMENT);
950 }
951
952 #if !ADVISORY_PAGEOUT
953 if (silent_overwrite || advisory_pageout)
954 return(KERN_INVALID_ARGUMENT);
955
956 #endif /* !ADVISORY_PAGEOUT */
957 if (may_cache)
958 may_cache = TRUE;
959 if (temporary)
960 temporary = TRUE;
961 if (cluster_size != 0) {
962 int pages_per_cluster;
963 pages_per_cluster = atop(cluster_size);
964 /*
965 * Cluster size must be integral multiple of page size,
966 * and be a power of 2 number of pages.
967 */
968 if ((cluster_size & (PAGE_SIZE-1)) ||
969 ((pages_per_cluster-1) & pages_per_cluster))
970 return KERN_INVALID_ARGUMENT;
971 }
972
973 vm_object_lock(object);
974
975 /*
976 * Copy the attributes
977 */
978 assert(!object->internal);
979 object_became_ready = !object->pager_ready;
980 object->copy_strategy = copy_strategy;
981 object->can_persist = may_cache;
982 object->temporary = temporary;
983 object->silent_overwrite = silent_overwrite;
984 object->advisory_pageout = advisory_pageout;
985 if (cluster_size == 0)
986 cluster_size = PAGE_SIZE;
987 object->cluster_size = cluster_size;
988
989 assert(cluster_size >= PAGE_SIZE &&
990 cluster_size % PAGE_SIZE == 0);
991
992 /*
993 * Wake up anyone waiting for the ready attribute
994 * to become asserted.
995 */
996
997 if (object_became_ready) {
998 object->pager_ready = TRUE;
999 vm_object_wakeup(object, VM_OBJECT_EVENT_PAGER_READY);
1000 }
1001
1002 vm_object_unlock(object);
1003
1004 return(KERN_SUCCESS);
1005 }
1006
1007 /*
1008 * Set the memory object attribute as provided.
1009 *
1010 * XXX This routine cannot be completed until the vm_msync, clean
1011 * in place, and cluster work is completed. See ifdef notyet
1012 * below and note that vm_object_set_attributes_common()
1013 * may have to be expanded.
1014 */
1015 kern_return_t
1016 memory_object_change_attributes(
1017 memory_object_control_t control,
1018 memory_object_flavor_t flavor,
1019 memory_object_info_t attributes,
1020 mach_msg_type_number_t count)
1021 {
1022 vm_object_t object;
1023 kern_return_t result = KERN_SUCCESS;
1024 boolean_t temporary;
1025 boolean_t may_cache;
1026 boolean_t invalidate;
1027 vm_size_t cluster_size;
1028 memory_object_copy_strategy_t copy_strategy;
1029 boolean_t silent_overwrite;
1030 boolean_t advisory_pageout;
1031
1032 object = memory_object_control_to_vm_object(control);
1033 if (object == VM_OBJECT_NULL)
1034 return (KERN_INVALID_ARGUMENT);
1035
1036 vm_object_lock(object);
1037
1038 temporary = object->temporary;
1039 may_cache = object->can_persist;
1040 copy_strategy = object->copy_strategy;
1041 silent_overwrite = object->silent_overwrite;
1042 advisory_pageout = object->advisory_pageout;
1043 #if notyet
1044 invalidate = object->invalidate;
1045 #endif
1046 cluster_size = object->cluster_size;
1047 vm_object_unlock(object);
1048
1049 switch (flavor) {
1050 case OLD_MEMORY_OBJECT_BEHAVIOR_INFO:
1051 {
1052 old_memory_object_behave_info_t behave;
1053
1054 if (count != OLD_MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
1055 result = KERN_INVALID_ARGUMENT;
1056 break;
1057 }
1058
1059 behave = (old_memory_object_behave_info_t) attributes;
1060
1061 temporary = behave->temporary;
1062 invalidate = behave->invalidate;
1063 copy_strategy = behave->copy_strategy;
1064
1065 break;
1066 }
1067
1068 case MEMORY_OBJECT_BEHAVIOR_INFO:
1069 {
1070 memory_object_behave_info_t behave;
1071
1072 if (count != MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
1073 result = KERN_INVALID_ARGUMENT;
1074 break;
1075 }
1076
1077 behave = (memory_object_behave_info_t) attributes;
1078
1079 temporary = behave->temporary;
1080 invalidate = behave->invalidate;
1081 copy_strategy = behave->copy_strategy;
1082 silent_overwrite = behave->silent_overwrite;
1083 advisory_pageout = behave->advisory_pageout;
1084 break;
1085 }
1086
1087 case MEMORY_OBJECT_PERFORMANCE_INFO:
1088 {
1089 memory_object_perf_info_t perf;
1090
1091 if (count != MEMORY_OBJECT_PERF_INFO_COUNT) {
1092 result = KERN_INVALID_ARGUMENT;
1093 break;
1094 }
1095
1096 perf = (memory_object_perf_info_t) attributes;
1097
1098 may_cache = perf->may_cache;
1099 cluster_size = round_page(perf->cluster_size);
1100
1101 break;
1102 }
1103
1104 case OLD_MEMORY_OBJECT_ATTRIBUTE_INFO:
1105 {
1106 old_memory_object_attr_info_t attr;
1107
1108 if (count != OLD_MEMORY_OBJECT_ATTR_INFO_COUNT) {
1109 result = KERN_INVALID_ARGUMENT;
1110 break;
1111 }
1112
1113 attr = (old_memory_object_attr_info_t) attributes;
1114
1115 may_cache = attr->may_cache;
1116 copy_strategy = attr->copy_strategy;
1117 cluster_size = page_size;
1118
1119 break;
1120 }
1121
1122 case MEMORY_OBJECT_ATTRIBUTE_INFO:
1123 {
1124 memory_object_attr_info_t attr;
1125
1126 if (count != MEMORY_OBJECT_ATTR_INFO_COUNT) {
1127 result = KERN_INVALID_ARGUMENT;
1128 break;
1129 }
1130
1131 attr = (memory_object_attr_info_t) attributes;
1132
1133 copy_strategy = attr->copy_strategy;
1134 may_cache = attr->may_cache_object;
1135 cluster_size = attr->cluster_size;
1136 temporary = attr->temporary;
1137
1138 break;
1139 }
1140
1141 default:
1142 result = KERN_INVALID_ARGUMENT;
1143 break;
1144 }
1145
1146 if (result != KERN_SUCCESS)
1147 return(result);
1148
1149 if (copy_strategy == MEMORY_OBJECT_COPY_TEMPORARY) {
1150 copy_strategy = MEMORY_OBJECT_COPY_DELAY;
1151 temporary = TRUE;
1152 } else {
1153 temporary = FALSE;
1154 }
1155
1156 /*
1157 * XXX may_cache may become a tri-valued variable to handle
1158 * XXX uncache if not in use.
1159 */
1160 return (vm_object_set_attributes_common(object,
1161 may_cache,
1162 copy_strategy,
1163 temporary,
1164 cluster_size,
1165 silent_overwrite,
1166 advisory_pageout));
1167 }
1168
1169 kern_return_t
1170 memory_object_get_attributes(
1171 memory_object_control_t control,
1172 memory_object_flavor_t flavor,
1173 memory_object_info_t attributes, /* pointer to OUT array */
1174 mach_msg_type_number_t *count) /* IN/OUT */
1175 {
1176 kern_return_t ret = KERN_SUCCESS;
1177 vm_object_t object;
1178
1179 object = memory_object_control_to_vm_object(control);
1180 if (object == VM_OBJECT_NULL)
1181 return (KERN_INVALID_ARGUMENT);
1182
1183 vm_object_lock(object);
1184
1185 switch (flavor) {
1186 case OLD_MEMORY_OBJECT_BEHAVIOR_INFO:
1187 {
1188 old_memory_object_behave_info_t behave;
1189
1190 if (*count < OLD_MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
1191 ret = KERN_INVALID_ARGUMENT;
1192 break;
1193 }
1194
1195 behave = (old_memory_object_behave_info_t) attributes;
1196 behave->copy_strategy = object->copy_strategy;
1197 behave->temporary = object->temporary;
1198 #if notyet /* remove when vm_msync complies and clean in place fini */
1199 behave->invalidate = object->invalidate;
1200 #else
1201 behave->invalidate = FALSE;
1202 #endif
1203
1204 *count = OLD_MEMORY_OBJECT_BEHAVE_INFO_COUNT;
1205 break;
1206 }
1207
1208 case MEMORY_OBJECT_BEHAVIOR_INFO:
1209 {
1210 memory_object_behave_info_t behave;
1211
1212 if (*count < MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
1213 ret = KERN_INVALID_ARGUMENT;
1214 break;
1215 }
1216
1217 behave = (memory_object_behave_info_t) attributes;
1218 behave->copy_strategy = object->copy_strategy;
1219 behave->temporary = object->temporary;
1220 #if notyet /* remove when vm_msync complies and clean in place fini */
1221 behave->invalidate = object->invalidate;
1222 #else
1223 behave->invalidate = FALSE;
1224 #endif
1225 behave->advisory_pageout = object->advisory_pageout;
1226 behave->silent_overwrite = object->silent_overwrite;
1227 *count = MEMORY_OBJECT_BEHAVE_INFO_COUNT;
1228 break;
1229 }
1230
1231 case MEMORY_OBJECT_PERFORMANCE_INFO:
1232 {
1233 memory_object_perf_info_t perf;
1234
1235 if (*count < MEMORY_OBJECT_PERF_INFO_COUNT) {
1236 ret = KERN_INVALID_ARGUMENT;
1237 break;
1238 }
1239
1240 perf = (memory_object_perf_info_t) attributes;
1241 perf->cluster_size = object->cluster_size;
1242 perf->may_cache = object->can_persist;
1243
1244 *count = MEMORY_OBJECT_PERF_INFO_COUNT;
1245 break;
1246 }
1247
1248 case OLD_MEMORY_OBJECT_ATTRIBUTE_INFO:
1249 {
1250 old_memory_object_attr_info_t attr;
1251
1252 if (*count < OLD_MEMORY_OBJECT_ATTR_INFO_COUNT) {
1253 ret = KERN_INVALID_ARGUMENT;
1254 break;
1255 }
1256
1257 attr = (old_memory_object_attr_info_t) attributes;
1258 attr->may_cache = object->can_persist;
1259 attr->copy_strategy = object->copy_strategy;
1260
1261 *count = OLD_MEMORY_OBJECT_ATTR_INFO_COUNT;
1262 break;
1263 }
1264
1265 case MEMORY_OBJECT_ATTRIBUTE_INFO:
1266 {
1267 memory_object_attr_info_t attr;
1268
1269 if (*count < MEMORY_OBJECT_ATTR_INFO_COUNT) {
1270 ret = KERN_INVALID_ARGUMENT;
1271 break;
1272 }
1273
1274 attr = (memory_object_attr_info_t) attributes;
1275 attr->copy_strategy = object->copy_strategy;
1276 attr->cluster_size = object->cluster_size;
1277 attr->may_cache_object = object->can_persist;
1278 attr->temporary = object->temporary;
1279
1280 *count = MEMORY_OBJECT_ATTR_INFO_COUNT;
1281 break;
1282 }
1283
1284 default:
1285 ret = KERN_INVALID_ARGUMENT;
1286 break;
1287 }
1288
1289 vm_object_unlock(object);
1290
1291 return(ret);
1292 }
1293
1294
1295 /*
1296 * Routine: memory_object_upl_request [interface]
1297 * Purpose:
1298 * Cause the population of a portion of a vm_object.
1299 * Depending on the nature of the request, the pages
1300 * returned may be contain valid data or be uninitialized.
1301 *
1302 */
1303
1304 kern_return_t
1305 memory_object_upl_request(
1306 memory_object_control_t control,
1307 memory_object_offset_t offset,
1308 vm_size_t size,
1309 upl_t *upl_ptr,
1310 upl_page_info_array_t user_page_list,
1311 unsigned int *page_list_count,
1312 int cntrl_flags)
1313 {
1314 vm_object_t object;
1315
1316 object = memory_object_control_to_vm_object(control);
1317 if (object == VM_OBJECT_NULL)
1318 return (KERN_INVALID_ARGUMENT);
1319
1320 return vm_object_upl_request(object,
1321 offset,
1322 size,
1323 upl_ptr,
1324 user_page_list,
1325 page_list_count,
1326 cntrl_flags);
1327 }
1328
1329 /*
1330 * Routine: memory_object_super_upl_request [interface]
1331 * Purpose:
1332 * Cause the population of a portion of a vm_object
1333 * in much the same way as memory_object_upl_request.
1334 * Depending on the nature of the request, the pages
1335 * returned may be contain valid data or be uninitialized.
1336 * However, the region may be expanded up to the super
1337 * cluster size provided.
1338 */
1339
1340 kern_return_t
1341 memory_object_super_upl_request(
1342 memory_object_control_t control,
1343 memory_object_offset_t offset,
1344 vm_size_t size,
1345 vm_size_t super_cluster,
1346 upl_t *upl,
1347 upl_page_info_t *user_page_list,
1348 unsigned int *page_list_count,
1349 int cntrl_flags)
1350 {
1351 vm_object_t object;
1352
1353 object = memory_object_control_to_vm_object(control);
1354 if (object == VM_OBJECT_NULL)
1355 return (KERN_INVALID_ARGUMENT);
1356
1357 return vm_object_super_upl_request(object,
1358 offset,
1359 size,
1360 super_cluster,
1361 upl,
1362 user_page_list,
1363 page_list_count,
1364 cntrl_flags);
1365 }
1366
1367 int vm_stat_discard_cleared_reply = 0;
1368 int vm_stat_discard_cleared_unset = 0;
1369 int vm_stat_discard_cleared_too_late = 0;
1370
1371
1372
1373 /*
1374 * Routine: host_default_memory_manager [interface]
1375 * Purpose:
1376 * set/get the default memory manager port and default cluster
1377 * size.
1378 *
1379 * If successful, consumes the supplied naked send right.
1380 */
1381 kern_return_t
1382 host_default_memory_manager(
1383 host_priv_t host_priv,
1384 memory_object_default_t *default_manager,
1385 vm_size_t cluster_size)
1386 {
1387 memory_object_default_t current_manager;
1388 memory_object_default_t new_manager;
1389 memory_object_default_t returned_manager;
1390
1391 if (host_priv == HOST_PRIV_NULL)
1392 return(KERN_INVALID_HOST);
1393
1394 assert(host_priv == &realhost);
1395
1396 new_manager = *default_manager;
1397 mutex_lock(&memory_manager_default_lock);
1398 current_manager = memory_manager_default;
1399
1400 if (new_manager == MEMORY_OBJECT_DEFAULT_NULL) {
1401 /*
1402 * Retrieve the current value.
1403 */
1404 memory_object_default_reference(current_manager);
1405 returned_manager = current_manager;
1406 } else {
1407 /*
1408 * Retrieve the current value,
1409 * and replace it with the supplied value.
1410 * We return the old reference to the caller
1411 * but we have to take a reference on the new
1412 * one.
1413 */
1414
1415 returned_manager = current_manager;
1416 memory_manager_default = new_manager;
1417 memory_object_default_reference(new_manager);
1418
1419 if (cluster_size % PAGE_SIZE != 0) {
1420 #if 0
1421 mutex_unlock(&memory_manager_default_lock);
1422 return KERN_INVALID_ARGUMENT;
1423 #else
1424 cluster_size = round_page(cluster_size);
1425 #endif
1426 }
1427 memory_manager_default_cluster = cluster_size;
1428
1429 /*
1430 * In case anyone's been waiting for a memory
1431 * manager to be established, wake them up.
1432 */
1433
1434 thread_wakeup((event_t) &memory_manager_default);
1435 }
1436
1437 mutex_unlock(&memory_manager_default_lock);
1438
1439 *default_manager = returned_manager;
1440 return(KERN_SUCCESS);
1441 }
1442
1443 /*
1444 * Routine: memory_manager_default_reference
1445 * Purpose:
1446 * Returns a naked send right for the default
1447 * memory manager. The returned right is always
1448 * valid (not IP_NULL or IP_DEAD).
1449 */
1450
1451 __private_extern__ memory_object_default_t
1452 memory_manager_default_reference(
1453 vm_size_t *cluster_size)
1454 {
1455 memory_object_default_t current_manager;
1456
1457 mutex_lock(&memory_manager_default_lock);
1458 current_manager = memory_manager_default;
1459 while (current_manager == MEMORY_OBJECT_DEFAULT_NULL) {
1460 wait_result_t res;
1461
1462 res = thread_sleep_mutex((event_t) &memory_manager_default,
1463 &memory_manager_default_lock,
1464 THREAD_UNINT);
1465 assert(res == THREAD_AWAKENED);
1466 current_manager = memory_manager_default;
1467 }
1468 memory_object_default_reference(current_manager);
1469 *cluster_size = memory_manager_default_cluster;
1470 mutex_unlock(&memory_manager_default_lock);
1471
1472 return current_manager;
1473 }
1474
1475 /*
1476 * Routine: memory_manager_default_check
1477 *
1478 * Purpose:
1479 * Check whether a default memory manager has been set
1480 * up yet, or not. Returns KERN_SUCCESS if dmm exists,
1481 * and KERN_FAILURE if dmm does not exist.
1482 *
1483 * If there is no default memory manager, log an error,
1484 * but only the first time.
1485 *
1486 */
1487 __private_extern__ kern_return_t
1488 memory_manager_default_check(void)
1489 {
1490 memory_object_default_t current;
1491
1492 mutex_lock(&memory_manager_default_lock);
1493 current = memory_manager_default;
1494 if (current == MEMORY_OBJECT_DEFAULT_NULL) {
1495 static boolean_t logged; /* initialized to 0 */
1496 boolean_t complain = !logged;
1497 logged = TRUE;
1498 mutex_unlock(&memory_manager_default_lock);
1499 if (complain)
1500 printf("Warning: No default memory manager\n");
1501 return(KERN_FAILURE);
1502 } else {
1503 mutex_unlock(&memory_manager_default_lock);
1504 return(KERN_SUCCESS);
1505 }
1506 }
1507
1508 __private_extern__ void
1509 memory_manager_default_init(void)
1510 {
1511 memory_manager_default = MEMORY_OBJECT_DEFAULT_NULL;
1512 mutex_init(&memory_manager_default_lock, ETAP_VM_MEMMAN);
1513 }
1514
1515
1516 void
1517 memory_object_deactivate_pages(
1518 vm_object_t object,
1519 vm_object_offset_t offset,
1520 vm_object_size_t size,
1521 boolean_t kill_page)
1522 {
1523 vm_object_t orig_object;
1524 int pages_moved = 0;
1525 int pages_found = 0;
1526
1527 /*
1528 * entered with object lock held, acquire a paging reference to
1529 * prevent the memory_object and control ports from
1530 * being destroyed.
1531 */
1532 orig_object = object;
1533
1534 for (;;) {
1535 register vm_page_t m;
1536 vm_object_offset_t toffset;
1537 vm_object_size_t tsize;
1538
1539 vm_object_paging_begin(object);
1540 vm_page_lock_queues();
1541
1542 for (tsize = size, toffset = offset; tsize; tsize -= PAGE_SIZE, toffset += PAGE_SIZE) {
1543
1544 if ((m = vm_page_lookup(object, toffset)) != VM_PAGE_NULL) {
1545
1546 pages_found++;
1547
1548 if ((m->wire_count == 0) && (!m->private) && (!m->gobbled) && (!m->busy)) {
1549
1550 m->reference = FALSE;
1551 pmap_clear_reference(m->phys_addr);
1552
1553 if ((kill_page) && (object->internal)) {
1554 m->precious = FALSE;
1555 m->dirty = FALSE;
1556 pmap_clear_modify(m->phys_addr);
1557 vm_external_state_clr(object->existence_map, offset);
1558 }
1559 VM_PAGE_QUEUES_REMOVE(m);
1560
1561 if(m->zero_fill) {
1562 queue_enter_first(
1563 &vm_page_queue_zf,
1564 m, vm_page_t, pageq);
1565 } else {
1566 queue_enter_first(
1567 &vm_page_queue_inactive,
1568 m, vm_page_t, pageq);
1569 }
1570
1571 m->inactive = TRUE;
1572 if (!m->fictitious)
1573 vm_page_inactive_count++;
1574
1575 pages_moved++;
1576 }
1577 }
1578 }
1579 vm_page_unlock_queues();
1580 vm_object_paging_end(object);
1581
1582 if (object->shadow) {
1583 vm_object_t tmp_object;
1584
1585 kill_page = 0;
1586
1587 offset += object->shadow_offset;
1588
1589 tmp_object = object->shadow;
1590 vm_object_lock(tmp_object);
1591
1592 if (object != orig_object)
1593 vm_object_unlock(object);
1594 object = tmp_object;
1595 } else
1596 break;
1597 }
1598 if (object != orig_object)
1599 vm_object_unlock(object);
1600 }
1601
1602 /* Allow manipulation of individual page state. This is actually part of */
1603 /* the UPL regimen but takes place on the object rather than on a UPL */
1604
1605 kern_return_t
1606 memory_object_page_op(
1607 memory_object_control_t control,
1608 memory_object_offset_t offset,
1609 int ops,
1610 vm_offset_t *phys_entry,
1611 int *flags)
1612 {
1613 vm_object_t object;
1614 vm_page_t dst_page;
1615
1616
1617 object = memory_object_control_to_vm_object(control);
1618 if (object == VM_OBJECT_NULL)
1619 return (KERN_INVALID_ARGUMENT);
1620
1621 vm_object_lock(object);
1622
1623 if(ops & UPL_POP_PHYSICAL) {
1624 if(object->phys_contiguous) {
1625 if (phys_entry) {
1626 *phys_entry = (vm_offset_t)
1627 object->shadow_offset;
1628 }
1629 vm_object_unlock(object);
1630 return KERN_SUCCESS;
1631 } else {
1632 vm_object_unlock(object);
1633 return KERN_INVALID_OBJECT;
1634 }
1635 }
1636
1637 while(TRUE) {
1638 if(object->phys_contiguous) {
1639 vm_object_unlock(object);
1640 return KERN_INVALID_OBJECT;
1641 }
1642
1643 if((dst_page = vm_page_lookup(object,offset)) == VM_PAGE_NULL) {
1644 vm_object_unlock(object);
1645 return KERN_FAILURE;
1646 }
1647
1648 /* Sync up on getting the busy bit */
1649 if((dst_page->busy || dst_page->cleaning) &&
1650 (((ops & UPL_POP_SET) &&
1651 (ops & UPL_POP_BUSY)) || (ops & UPL_POP_DUMP))) {
1652 /* someone else is playing with the page, we will */
1653 /* have to wait */
1654 PAGE_SLEEP(object, dst_page, THREAD_UNINT);
1655 continue;
1656 }
1657
1658 if (ops & UPL_POP_DUMP) {
1659 vm_page_lock_queues();
1660 vm_page_free(dst_page);
1661 vm_page_unlock_queues();
1662 break;
1663 }
1664
1665 if (flags) {
1666 *flags = 0;
1667
1668 /* Get the condition of flags before requested ops */
1669 /* are undertaken */
1670
1671 if(dst_page->dirty) *flags |= UPL_POP_DIRTY;
1672 if(dst_page->pageout) *flags |= UPL_POP_PAGEOUT;
1673 if(dst_page->precious) *flags |= UPL_POP_PRECIOUS;
1674 if(dst_page->absent) *flags |= UPL_POP_ABSENT;
1675 if(dst_page->busy) *flags |= UPL_POP_BUSY;
1676 }
1677 if (phys_entry)
1678 *phys_entry = dst_page->phys_addr;
1679
1680 /* The caller should have made a call either contingent with */
1681 /* or prior to this call to set UPL_POP_BUSY */
1682 if(ops & UPL_POP_SET) {
1683 /* The protection granted with this assert will */
1684 /* not be complete. If the caller violates the */
1685 /* convention and attempts to change page state */
1686 /* without first setting busy we may not see it */
1687 /* because the page may already be busy. However */
1688 /* if such violations occur we will assert sooner */
1689 /* or later. */
1690 assert(dst_page->busy || (ops & UPL_POP_BUSY));
1691 if (ops & UPL_POP_DIRTY) dst_page->dirty = TRUE;
1692 if (ops & UPL_POP_PAGEOUT) dst_page->pageout = TRUE;
1693 if (ops & UPL_POP_PRECIOUS) dst_page->precious = TRUE;
1694 if (ops & UPL_POP_ABSENT) dst_page->absent = TRUE;
1695 if (ops & UPL_POP_BUSY) dst_page->busy = TRUE;
1696 }
1697
1698 if(ops & UPL_POP_CLR) {
1699 assert(dst_page->busy);
1700 if (ops & UPL_POP_DIRTY) dst_page->dirty = FALSE;
1701 if (ops & UPL_POP_PAGEOUT) dst_page->pageout = FALSE;
1702 if (ops & UPL_POP_PRECIOUS) dst_page->precious = FALSE;
1703 if (ops & UPL_POP_ABSENT) dst_page->absent = FALSE;
1704 if (ops & UPL_POP_BUSY) {
1705 dst_page->busy = FALSE;
1706 PAGE_WAKEUP(dst_page);
1707 }
1708 }
1709 break;
1710 }
1711
1712 vm_object_unlock(object);
1713 return KERN_SUCCESS;
1714
1715 }
1716
1717 static zone_t mem_obj_control_zone;
1718
1719 __private_extern__ void
1720 memory_object_control_bootstrap(void)
1721 {
1722 int i;
1723
1724 i = (vm_size_t) sizeof (struct memory_object_control);
1725 mem_obj_control_zone = zinit (i, 8192*i, 4096, "mem_obj_control");
1726 return;
1727 }
1728
1729 __private_extern__ memory_object_control_t
1730 memory_object_control_allocate(
1731 vm_object_t object)
1732 {
1733 memory_object_control_t control;
1734
1735 control = (memory_object_control_t)zalloc(mem_obj_control_zone);
1736 if (control != MEMORY_OBJECT_CONTROL_NULL)
1737 control->object = object;
1738 return (control);
1739 }
1740
1741 __private_extern__ void
1742 memory_object_control_collapse(
1743 memory_object_control_t control,
1744 vm_object_t object)
1745 {
1746 assert((control->object != VM_OBJECT_NULL) &&
1747 (control->object != object));
1748 control->object = object;
1749 }
1750
1751 __private_extern__ vm_object_t
1752 memory_object_control_to_vm_object(
1753 memory_object_control_t control)
1754 {
1755 if (control == MEMORY_OBJECT_CONTROL_NULL)
1756 return VM_OBJECT_NULL;
1757
1758 return (control->object);
1759 }
1760
1761 memory_object_control_t
1762 convert_port_to_mo_control(
1763 mach_port_t port)
1764 {
1765 return MEMORY_OBJECT_CONTROL_NULL;
1766 }
1767
1768
1769 mach_port_t
1770 convert_mo_control_to_port(
1771 memory_object_control_t control)
1772 {
1773 return MACH_PORT_NULL;
1774 }
1775
1776 void
1777 memory_object_control_reference(
1778 memory_object_control_t control)
1779 {
1780 return;
1781 }
1782
1783 /*
1784 * We only every issue one of these references, so kill it
1785 * when that gets released (should switch the real reference
1786 * counting in true port-less EMMI).
1787 */
1788 void
1789 memory_object_control_deallocate(
1790 memory_object_control_t control)
1791 {
1792 zfree(mem_obj_control_zone, (vm_offset_t)control);
1793 }
1794
1795 void
1796 memory_object_control_disable(
1797 memory_object_control_t control)
1798 {
1799 assert(control->object != VM_OBJECT_NULL);
1800 control->object = VM_OBJECT_NULL;
1801 }
1802
1803 void
1804 memory_object_default_reference(
1805 memory_object_default_t dmm)
1806 {
1807 ipc_port_make_send(dmm);
1808 }
1809
1810 void
1811 memory_object_default_deallocate(
1812 memory_object_default_t dmm)
1813 {
1814 ipc_port_release_send(dmm);
1815 }
1816
1817 memory_object_t
1818 convert_port_to_memory_object(
1819 mach_port_t port)
1820 {
1821 return (MEMORY_OBJECT_NULL);
1822 }
1823
1824
1825 mach_port_t
1826 convert_memory_object_to_port(
1827 memory_object_t object)
1828 {
1829 return (MACH_PORT_NULL);
1830 }
1831
1832 #ifdef MACH_BSD
1833 /* remove after component interface available */
1834 extern int vnode_pager_workaround;
1835 extern int device_pager_workaround;
1836 #endif
1837
1838
1839 /* Routine memory_object_reference */
1840 void memory_object_reference(
1841 memory_object_t memory_object)
1842 {
1843 extern void dp_memory_object_reference(memory_object_t);
1844
1845 #ifdef MACH_BSD
1846 extern void vnode_pager_reference(memory_object_t);
1847 extern void device_pager_reference(memory_object_t);
1848
1849 if(memory_object->pager == &vnode_pager_workaround) {
1850 vnode_pager_reference(memory_object);
1851 } else if(memory_object->pager == &device_pager_workaround) {
1852 device_pager_reference(memory_object);
1853 } else
1854 #endif
1855 dp_memory_object_reference(memory_object);
1856 }
1857
1858 /* Routine memory_object_deallocate */
1859 void memory_object_deallocate(
1860 memory_object_t memory_object)
1861 {
1862 extern void dp_memory_object_deallocate(memory_object_t);
1863
1864 #ifdef MACH_BSD
1865 extern void vnode_pager_deallocate(memory_object_t);
1866 extern void device_pager_deallocate(memory_object_t);
1867
1868 if(memory_object->pager == &vnode_pager_workaround) {
1869 vnode_pager_deallocate(memory_object);
1870 } else if(memory_object->pager == &device_pager_workaround) {
1871 device_pager_deallocate(memory_object);
1872 } else
1873 #endif
1874 dp_memory_object_deallocate(memory_object);
1875 }
1876
1877
1878 /* Routine memory_object_init */
1879 kern_return_t memory_object_init
1880 (
1881 memory_object_t memory_object,
1882 memory_object_control_t memory_control,
1883 vm_size_t memory_object_page_size
1884 )
1885 {
1886 extern kern_return_t dp_memory_object_init(memory_object_t,
1887 memory_object_control_t,
1888 vm_size_t);
1889 #ifdef MACH_BSD
1890 extern kern_return_t vnode_pager_init(memory_object_t,
1891 memory_object_control_t,
1892 vm_size_t);
1893 extern kern_return_t device_pager_init(memory_object_t,
1894 memory_object_control_t,
1895 vm_size_t);
1896
1897 if(memory_object->pager == &vnode_pager_workaround) {
1898 return vnode_pager_init(memory_object,
1899 memory_control,
1900 memory_object_page_size);
1901 } else if(memory_object->pager == &device_pager_workaround) {
1902 return device_pager_init(memory_object,
1903 memory_control,
1904 memory_object_page_size);
1905 } else
1906 #endif
1907 return dp_memory_object_init(memory_object,
1908 memory_control,
1909 memory_object_page_size);
1910 }
1911
1912 /* Routine memory_object_terminate */
1913 kern_return_t memory_object_terminate
1914 (
1915 memory_object_t memory_object
1916 )
1917 {
1918 extern kern_return_t dp_memory_object_terminate(memory_object_t);
1919
1920 #ifdef MACH_BSD
1921 extern kern_return_t vnode_pager_terminate(memory_object_t);
1922 extern kern_return_t device_pager_terminate(memory_object_t);
1923
1924 if(memory_object->pager == &vnode_pager_workaround) {
1925 return vnode_pager_terminate(memory_object);
1926 } else if(memory_object->pager == &device_pager_workaround) {
1927 return device_pager_terminate(memory_object);
1928 } else
1929 #endif
1930 return dp_memory_object_terminate(memory_object);
1931 }
1932
1933 /* Routine memory_object_data_request */
1934 kern_return_t memory_object_data_request
1935 (
1936 memory_object_t memory_object,
1937 memory_object_offset_t offset,
1938 vm_size_t length,
1939 vm_prot_t desired_access
1940 )
1941 {
1942 extern kern_return_t dp_memory_object_data_request(memory_object_t,
1943 memory_object_offset_t, vm_size_t, vm_prot_t);
1944
1945 #ifdef MACH_BSD
1946 extern kern_return_t vnode_pager_data_request(memory_object_t,
1947 memory_object_offset_t, vm_size_t, vm_prot_t);
1948 extern kern_return_t device_pager_data_request(memory_object_t,
1949 memory_object_offset_t, vm_size_t, vm_prot_t);
1950
1951 if (memory_object->pager == &vnode_pager_workaround) {
1952 return vnode_pager_data_request(memory_object,
1953 offset,
1954 length,
1955 desired_access);
1956 } else if (memory_object->pager == &device_pager_workaround) {
1957 return device_pager_data_request(memory_object,
1958 offset,
1959 length,
1960 desired_access);
1961 } else
1962 #endif
1963 return dp_memory_object_data_request(memory_object,
1964 offset,
1965 length,
1966 desired_access);
1967 }
1968
1969 /* Routine memory_object_data_return */
1970 kern_return_t memory_object_data_return
1971 (
1972 memory_object_t memory_object,
1973 memory_object_offset_t offset,
1974 vm_size_t size,
1975 boolean_t dirty,
1976 boolean_t kernel_copy
1977 )
1978 {
1979 extern kern_return_t dp_memory_object_data_return(memory_object_t,
1980 memory_object_offset_t,
1981 vm_size_t,
1982 boolean_t,
1983 boolean_t);
1984 #ifdef MACH_BSD
1985 extern kern_return_t vnode_pager_data_return(memory_object_t,
1986 memory_object_offset_t,
1987 vm_size_t,
1988 boolean_t,
1989 boolean_t);
1990 extern kern_return_t device_pager_data_return(memory_object_t,
1991 memory_object_offset_t,
1992 vm_size_t,
1993 boolean_t,
1994 boolean_t);
1995
1996 if (memory_object->pager == &vnode_pager_workaround) {
1997 return vnode_pager_data_return(memory_object,
1998 offset,
1999 size,
2000 dirty,
2001 kernel_copy);
2002 } else if (memory_object->pager == &device_pager_workaround) {
2003 return device_pager_data_return(memory_object,
2004 offset,
2005 size,
2006 dirty,
2007 kernel_copy);
2008 } else
2009 #endif
2010 return dp_memory_object_data_return(memory_object,
2011 offset,
2012 size,
2013 dirty,
2014 kernel_copy);
2015 }
2016
2017 /* Routine memory_object_data_initialize */
2018 kern_return_t memory_object_data_initialize
2019 (
2020 memory_object_t memory_object,
2021 memory_object_offset_t offset,
2022 vm_size_t size
2023 )
2024 {
2025
2026 extern kern_return_t dp_memory_object_data_initialize(memory_object_t,
2027 memory_object_offset_t,
2028 vm_size_t);
2029 #ifdef MACH_BSD
2030 extern kern_return_t vnode_pager_data_initialize(memory_object_t,
2031 memory_object_offset_t,
2032 vm_size_t);
2033 extern kern_return_t device_pager_data_initialize(memory_object_t,
2034 memory_object_offset_t,
2035 vm_size_t);
2036
2037 if (memory_object->pager == &vnode_pager_workaround) {
2038 return vnode_pager_data_initialize(memory_object,
2039 offset,
2040 size);
2041 } else if (memory_object->pager == &device_pager_workaround) {
2042 return device_pager_data_initialize(memory_object,
2043 offset,
2044 size);
2045 } else
2046 #endif
2047 return dp_memory_object_data_initialize(memory_object,
2048 offset,
2049 size);
2050 }
2051
2052 /* Routine memory_object_data_unlock */
2053 kern_return_t memory_object_data_unlock
2054 (
2055 memory_object_t memory_object,
2056 memory_object_offset_t offset,
2057 vm_size_t size,
2058 vm_prot_t desired_access
2059 )
2060 {
2061 extern kern_return_t dp_memory_object_data_unlock(memory_object_t,
2062 memory_object_offset_t,
2063 vm_size_t,
2064 vm_prot_t);
2065 #ifdef MACH_BSD
2066 extern kern_return_t vnode_pager_data_unlock(memory_object_t,
2067 memory_object_offset_t,
2068 vm_size_t,
2069 vm_prot_t);
2070 extern kern_return_t device_pager_data_unlock(memory_object_t,
2071 memory_object_offset_t,
2072 vm_size_t,
2073 vm_prot_t);
2074
2075 if (memory_object->pager == &vnode_pager_workaround) {
2076 return vnode_pager_data_unlock(memory_object,
2077 offset,
2078 size,
2079 desired_access);
2080 } else if (memory_object->pager == &device_pager_workaround) {
2081 return device_pager_data_unlock(memory_object,
2082 offset,
2083 size,
2084 desired_access);
2085 } else
2086 #endif
2087 return dp_memory_object_data_unlock(memory_object,
2088 offset,
2089 size,
2090 desired_access);
2091
2092 }
2093
2094 /* Routine memory_object_synchronize */
2095 kern_return_t memory_object_synchronize
2096 (
2097 memory_object_t memory_object,
2098 memory_object_offset_t offset,
2099 vm_size_t size,
2100 vm_sync_t sync_flags
2101 )
2102 {
2103 extern kern_return_t dp_memory_object_data_synchronize(memory_object_t,
2104 memory_object_offset_t,
2105 vm_size_t,
2106 vm_sync_t);
2107 #ifdef MACH_BSD
2108 extern kern_return_t vnode_pager_data_synchronize(memory_object_t,
2109 memory_object_offset_t,
2110 vm_size_t,
2111 vm_sync_t);
2112 extern kern_return_t device_pager_data_synchronize(memory_object_t,
2113 memory_object_offset_t,
2114 vm_size_t,
2115 vm_sync_t);
2116
2117 if (memory_object->pager == &vnode_pager_workaround) {
2118 return vnode_pager_synchronize(
2119 memory_object,
2120 offset,
2121 size,
2122 sync_flags);
2123 } else if (memory_object->pager == &device_pager_workaround) {
2124 return device_pager_synchronize(
2125 memory_object,
2126 offset,
2127 size,
2128 sync_flags);
2129 } else
2130 #endif
2131 return dp_memory_object_synchronize(
2132 memory_object,
2133 offset,
2134 size,
2135 sync_flags);
2136 }
2137
2138 /* Routine memory_object_unmap */
2139 kern_return_t memory_object_unmap
2140 (
2141 memory_object_t memory_object
2142 )
2143 {
2144 extern kern_return_t dp_memory_object_unmap(memory_object_t);
2145 #ifdef MACH_BSD
2146 extern kern_return_t vnode_pager_unmap(memory_object_t);
2147 extern kern_return_t device_pager_unmap(memory_object_t);
2148
2149 if (memory_object->pager == &vnode_pager_workaround) {
2150 return vnode_pager_unmap(memory_object);
2151 } else if (memory_object->pager == &device_pager_workaround) {
2152 return device_pager_unmap(memory_object);
2153 } else
2154 #endif
2155 return dp_memory_object_unmap(memory_object);
2156 }
2157
2158 /* Routine memory_object_create */
2159 kern_return_t memory_object_create
2160 (
2161 memory_object_default_t default_memory_manager,
2162 vm_size_t new_memory_object_size,
2163 memory_object_t *new_memory_object
2164 )
2165 {
2166 extern kern_return_t default_pager_memory_object_create(memory_object_default_t,
2167 vm_size_t,
2168 memory_object_t *);
2169
2170 return default_pager_memory_object_create(default_memory_manager,
2171 new_memory_object_size,
2172 new_memory_object);
2173 }
2174