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