|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Mach Operating System
27: * Copyright (c) 1993-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 [email protected]
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: * File: vm/vm_object.c
52: * Author: Avadis Tevanian, Jr., Michael Wayne Young
53: *
54: * Virtual memory object module.
55: */
56:
57: #include <norma_vm.h>
58: #include <mach_pagemap.h>
59:
60: #if NORMA_VM
61: #include <norma/xmm_server_rename.h>
62: #endif /* NORMA_VM */
63:
64: #include <mach/memory_object.h>
65: #include <mach/memory_object_default.h>
66: #include <mach/memory_object_user.h>
67: #include <mach/vm_param.h>
68: #include <ipc/ipc_port.h>
69: #include <ipc/ipc_space.h>
70: #include <kern/assert.h>
71: #include <kern/lock.h>
72: #include <kern/queue.h>
73: #include <kern/xpr.h>
74: #include <kern/zalloc.h>
75: #include <vm/memory_object.h>
76: #include <vm/vm_fault.h>
77: #include <vm/vm_map.h>
78: #include <vm/vm_object.h>
79: #include <vm/vm_page.h>
80: #include <vm/vm_pageout.h>
81:
82: #include <mach/vm_policy.h>
83:
84:
85: void memory_object_release(
86: ipc_port_t pager,
87: pager_request_t pager_request,
88: ipc_port_t pager_name); /* forward */
89:
90: void vm_object_deactivate_pages(vm_object_t);
91:
92: /*
93: * Virtual memory objects maintain the actual data
94: * associated with allocated virtual memory. A given
95: * page of memory exists within exactly one object.
96: *
97: * An object is only deallocated when all "references"
98: * are given up. Only one "reference" to a given
99: * region of an object should be writeable.
100: *
101: * Associated with each object is a list of all resident
102: * memory pages belonging to that object; this list is
103: * maintained by the "vm_page" module, but locked by the object's
104: * lock.
105: *
106: * Each object also records a "pager" routine which is
107: * used to retrieve (and store) pages to the proper backing
108: * storage. In addition, objects may be backed by other
109: * objects from which they were virtual-copied.
110: *
111: * The only items within the object structure which are
112: * modified after time of creation are:
113: * reference count locked by object's lock
114: * pager routine locked by object's lock
115: *
116: */
117:
118: struct zone *vm_object_zone; /* vm backing store zone */
119:
120: struct vm_object kernel_object_store, vm_submap_object_store;
121: #define VM_OBJECT_HASH_COUNT 1024
122: #define VM_OBJECT_MEMORY_UNIT (1024 * 1024)
123: #define VM_OBJECTS_PER_MEMORY_UNIT 50
124: int vm_cache_max; /* set in vm_object_init */
125:
126: queue_head_t vm_object_hashtable[VM_OBJECT_HASH_COUNT];
127: struct zone *object_hash_zone;
128:
129: struct vm_object_hash_entry {
130: queue_chain_t hash_links; /* hash chain links */
131: vm_object_t object; /* object we represent */
132: };
133:
134: typedef struct vm_object_hash_entry *vm_object_hash_entry_t;
135:
136: queue_head_t vm_object_cached_list; /* list of objects persisting */
137: int vm_object_cached; /* size of cached list */
138: simple_lock_data_t vm_cache_lock; /* lock for object cache */
139:
140: queue_head_t vm_object_list; /* list of allocated objects */
141: long vm_object_count; /* count of all objects */
142: simple_lock_data_t vm_object_list_lock;
143: /* lock for object list and count */
144:
145: vm_object_t kernel_object; /* the single kernel object */
146:
147: #define vm_object_cache_lock() simple_lock(&vm_cache_lock)
148: #define vm_object_cache_unlock() simple_unlock(&vm_cache_lock)
149:
150: struct vm_object vm_object_template;
151:
152: long object_collapses = 0;
153: long object_bypasses = 0;
154:
155: /*
156: * vm_object_init:
157: *
158: * Initialize the VM objects module.
159: */
160: void vm_object_init()
161: {
162: register int i;
163:
164: vm_object_zone = zinit((vm_size_t) sizeof(struct vm_object),
165: round_page(512*1024),
166: 0, FALSE, "objects");
167:
168: object_hash_zone = zinit(
169: (vm_size_t)sizeof(struct vm_object_hash_entry),
170: 100*1024, 0, FALSE,
171: "object hash zone");
172:
173: queue_init(&vm_object_cached_list);
174: queue_init(&vm_object_list);
175: vm_object_count = 0;
176: simple_lock_init(&vm_cache_lock);
177: simple_lock_init(&vm_object_list_lock);
178:
179: for (i = 0; i < VM_OBJECT_HASH_COUNT; i++)
180: queue_init(&vm_object_hashtable[i]);
181:
182: /*
183: * Parameterize the size of the cache based on the amount of
184: * physical memory available.
185: */
186: vm_cache_max = mem_size / VM_OBJECT_MEMORY_UNIT;
187: vm_cache_max *= VM_OBJECTS_PER_MEMORY_UNIT;
188:
189: if (vm_cache_max > 2500)
190: vm_cache_max = 2500;
191:
192: /*
193: * Fill in a template object, for quick initialization
194: */
195:
196: vm_object_template.ref_count = 1;
197: vm_object_template.resident_page_count = 0;
198: vm_object_template.size = 0;
199: vm_object_template.can_persist = FALSE;
200: vm_object_template.paging_in_progress = 0;
201: vm_object_template.copy = VM_OBJECT_NULL;
202:
203: vm_object_template.pager = vm_pager_null;
204: vm_object_template.pager_request = PORT_NULL;
205: vm_object_template.pager_name = PORT_NULL;
206: vm_object_template.pager_ready = FALSE;
207: vm_object_template.pager_creating = FALSE;
208: vm_object_template.internal = TRUE;
209: vm_object_template.paging_offset = 0;
210: vm_object_template.shadow = VM_OBJECT_NULL;
211: vm_object_template.shadow_offset = (vm_offset_t) 0;
212: vm_object_template.last_alloc = (vm_offset_t) 0;
213: vm_object_template.policy = (vm_offset_t) VM_POLICY_SEQ_DEACTIVATE;
214:
215: /*
216: * Initialize the "kernel object"
217: */
218:
219: kernel_object = &kernel_object_store;
220: _vm_object_allocate(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS,
221: kernel_object);
222:
223: /*
224: * Initialize the "submap object". Make it as large as the
225: * kernel object so that no limit is imposed on submap sizes.
226: */
227:
228: vm_submap_object = &vm_submap_object_store;
229: _vm_object_allocate(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS,
230: vm_submap_object);
231: }
232:
233: /*
234: * vm_object_allocate:
235: *
236: * Returns a new object with the given size.
237: */
238:
239: vm_object_t vm_object_allocate(size)
240: vm_size_t size;
241: {
242: register vm_object_t result;
243:
244: result = (vm_object_t) zalloc(vm_object_zone);
245:
246: _vm_object_allocate(size, result);
247:
248: return(result);
249: }
250:
251: _vm_object_allocate(size, object)
252: vm_size_t size;
253: register vm_object_t object;
254: {
255: (*object) = vm_object_template;
256: queue_init(&object->memq);
257: vm_object_lock_init(object);
258: object->size = size;
259: simple_lock(&vm_object_list_lock);
260: queue_enter(&vm_object_list, object, vm_object_t, object_list);
261: vm_object_count++;
262: simple_unlock(&vm_object_list_lock);
263: }
264:
265: /*
266: * vm_object_reference:
267: *
268: * Gets another reference to the given object.
269: */
270: void vm_object_reference(object)
271: register vm_object_t object;
272: {
273: if (object == VM_OBJECT_NULL)
274: return;
275:
276: vm_object_lock(object);
277: object->ref_count++;
278: vm_object_unlock(object);
279: }
280:
281: /*
282: * vm_object_deallocate:
283: *
284: * Release a reference to the specified object,
285: * gained either through a vm_object_allocate
286: * or a vm_object_reference call. When all references
287: * are gone, storage associated with this object
288: * may be relinquished.
289: *
290: * No object may be locked.
291: */
292: void vm_object_deallocate(object)
293: register vm_object_t object;
294: {
295: vm_object_t temp;
296:
297: while (object != VM_OBJECT_NULL) {
298:
299: /*
300: * The cache holds a reference (uncounted) to
301: * the object; we must lock it before removing
302: * the object.
303: */
304:
305: vm_object_cache_lock();
306:
307: /*
308: * Lose the reference
309: */
310: vm_object_lock(object);
311: if (--(object->ref_count) != 0) {
312:
313: /*
314: * If there are still references, then
315: * we are done.
316: */
317: vm_object_unlock(object);
318: vm_object_cache_unlock();
319: return;
320: }
321:
322: /*
323: * See if this object can persist. If so, enter
324: * it in the cache, then deactivate all of its
325: * pages.
326: */
327:
328: if (object->can_persist) {
329:
330: if (object->resident_page_count > 0) {
331: queue_enter(&vm_object_cached_list, object,
332: vm_object_t, cached_list);
333: vm_object_cached++;
334: vm_object_cache_unlock();
335:
336: vm_object_deactivate_pages(object);
337: vm_object_unlock(object);
338:
339: vm_object_cache_trim();
340: return;
341: }
342: else {
343: object->can_persist = FALSE;
344: }
345: }
346:
347: /*
348: * Make sure no one can look us up now.
349: */
350: vm_object_remove(object->pager);
351: vm_object_cache_unlock();
352:
353: temp = object->shadow;
354: vm_object_terminate(object);
355: /* unlocks and deallocates object */
356: object = temp;
357: }
358: }
359:
360:
361: #define vm_object_pager_terminate(object) { \
362: if ((object)->pager != vm_pager_null) { \
363: port_release((object)->pager); \
364: (object)->pager = vm_pager_null; \
365: } \
366: if ((object)->pager_request != PORT_NULL) { \
367: port_deallocate(kernel_task, (object)->pager_request); \
368: (object)->pager_request = PORT_NULL; \
369: } \
370: if ((object)->pager_name != PORT_NULL) { \
371: port_deallocate(kernel_task, (object)->pager_name); \
372: (object)->pager_name = PORT_NULL; \
373: } \
374: }
375:
376: /*
377: * vm_object_terminate actually destroys the specified object, freeing
378: * up all previously used resources.
379: *
380: * The object must be locked.
381: */
382: void vm_object_terminate(object)
383: register vm_object_t object;
384: {
385: register vm_page_t p;
386: vm_page_t next_p;
387: vm_object_t shadow_object;
388:
389: /*
390: * Detach the object from its shadow if we are the shadow's
391: * copy.
392: */
393: if ((shadow_object = object->shadow) != VM_OBJECT_NULL) {
394: vm_object_lock(shadow_object);
395: if (shadow_object->copy == object)
396: shadow_object->copy = VM_OBJECT_NULL;
397: else if (shadow_object->copy != VM_OBJECT_NULL)
398: panic("vm_object_terminate: copy/shadow inconsistency");
399: vm_object_unlock(shadow_object);
400: }
401:
402: /*
403: * Wait until the pageout daemon is through
404: * with the object.
405: */
406:
407: while (object->paging_in_progress != 0) {
408: vm_object_sleep(object, object, FALSE);
409: vm_object_lock(object);
410: }
411:
412:
413: /*
414: * While the paging system is locked,
415: * pull the object's pages off the active
416: * and inactive queues. This keeps the
417: * pageout daemon from playing with them
418: * during vm_pager_deallocate.
419: *
420: * We can't free the pages yet, because the
421: * object's pager may have to write them out
422: * before deallocating the paging space.
423: */
424:
425: p = (vm_page_t) queue_first(&object->memq);
426: while (!queue_end(&object->memq, (queue_entry_t) p)) {
427: VM_PAGE_CHECK(p);
428:
429: vm_page_lock_queues();
430: if (p->active) {
431: queue_remove(&vm_page_queue_active, p, vm_page_t,
432: pageq);
433: p->active = FALSE;
434: vm_page_active_count--;
435: }
436:
437: if (p->inactive) {
438: queue_remove(&vm_page_queue_inactive, p, vm_page_t,
439: pageq);
440: p->inactive = FALSE;
441: vm_page_inactive_count--;
442: }
443: /*
444: * If we are on the free list just free ourselves now to make sure
445: * noone else finds out about this page.
446: */
447: next_p = (vm_page_t) queue_next(&p->listq);
448: if (p->free) {
449: vm_page_free(p);
450: }
451: vm_page_unlock_queues();
452: p = next_p;
453: }
454:
455: vm_object_unlock(object);
456:
457: /*
458: * Let the pager know object is dead.
459: */
460:
461: if (object->pager != vm_pager_null)
462: vm_pager_deallocate(object->pager);
463:
464: if (object->paging_in_progress != 0)
465: panic("vm_object_deallocate: pageout in progress");
466:
467: /*
468: * Free physical page resources. All references to the object
469: * are gone, so we don't need to lock it.
470: */
471:
472: while (!queue_empty(&object->memq)) {
473: p = (vm_page_t) queue_first(&object->memq);
474:
475: VM_PAGE_CHECK(p);
476:
477: vm_page_lock_queues();
478: vm_page_free(p);
479: vm_page_unlock_queues();
480: }
481:
482: simple_lock(&vm_object_list_lock);
483: queue_remove(&vm_object_list, object, vm_object_t, object_list);
484: vm_object_count--;
485: simple_unlock(&vm_object_list_lock);
486:
487: /*
488: * Free the space for the object.
489: */
490:
491: zfree(vm_object_zone, (vm_offset_t) object);
492: }
493:
494: void vm_object_destroy(pager)
495: port_t pager;
496: {
497: register
498: vm_object_t object = vm_object_lookup(pager);
499:
500: if (object == VM_OBJECT_NULL)
501: return;
502:
503: vm_object_deallocate(object);
504: }
505:
506: /*
507: * _vm_object_deactivate_pages
508: *
509: * Internal routine to deactivate pages in the specified object.
510: * (Keep its pages in memory even though it is no longer referenced.)
511: *
512: * The object must be locked.
513: */
514: static void _vm_object_deactivate_pages(object, age)
515: register vm_object_t object;
516: register boolean_t age;
517: {
518: register vm_page_t p, next;
519:
520: vm_page_lock_queues();
521: p = (vm_page_t) queue_first(&object->memq);
522: while (!queue_end(&object->memq, (queue_entry_t) p)) {
523: next = (vm_page_t) queue_next(&p->listq);
524: if (!p->inactive) {
525: if (age)
526: vm_page_deactivate_first(p);
527: else
528: vm_page_deactivate(p);
529: }
530: p = next;
531: }
532: vm_page_unlock_queues();
533: }
534:
535: /*
536: * vm_object_deactivate_pages
537: *
538: * Deactivate pages in the specified object.
539: * (Keep its pages in memory even though it is no longer referenced.)
540: *
541: * The object must be locked.
542: */
543: void vm_object_deactivate_pages(object)
544: register vm_object_t object;
545: {
546: _vm_object_deactivate_pages(object, FALSE);
547: }
548:
549: /*
550: * vm_object_deactivate_pages_first
551: *
552: * Deactivate pages in the specified object. Age them.
553: * (Keep its pages in memory even though it is no longer referenced.)
554: *
555: * The object must be locked.
556: */
557: void vm_object_deactivate_pages_first(object)
558: register vm_object_t object;
559: {
560: _vm_object_deactivate_pages(object, TRUE);
561: }
562:
563: /*
564: * Trim the object cache to size.
565: */
566: vm_object_cache_trim()
567: {
568: register vm_object_t object;
569:
570: vm_object_cache_lock();
571: while (vm_object_cached > vm_cache_max) {
572: object = (vm_object_t) queue_first(&vm_object_cached_list);
573: vm_object_cache_unlock();
574:
575: if (object != vm_object_lookup(object->pager))
576: panic("vm_object_cache_trim: I'm sooo confused.");
577: vm_object_cache_object(object, FALSE);
578:
579: vm_object_cache_lock();
580: }
581: vm_object_cache_unlock();
582: }
583:
584: /*
585: *
586: */
587: kern_return_t
588: adjust_vm_object_cache(vm_size_t oldval, vm_size_t newval)
589: {
590: vm_cache_max = newval;
591: vm_object_cache_trim();
592: return(KERN_SUCCESS);
593: }
594:
595: kern_return_t vm_object_cache_object(object, should_cache)
596: vm_object_t object;
597: boolean_t should_cache;
598: {
599: if (object == VM_OBJECT_NULL)
600: return(KERN_INVALID_ARGUMENT);
601:
602: vm_object_cache_lock();
603: vm_object_lock(object);
604: object->can_persist = should_cache;
605: vm_object_unlock(object);
606: vm_object_cache_unlock();
607:
608: vm_object_deallocate(object);
609:
610: return(KERN_SUCCESS);
611: }
612:
613:
614: /*
615: * vm_object_shutdown()
616: *
617: * Shut down the object system. Unfortunately, while we
618: * may be trying to do this, init is happily waiting for
619: * processes to exit, and therefore will be causing some objects
620: * to be deallocated. To handle this, we gain a fake reference
621: * to all objects we release paging areas for. This will prevent
622: * a duplicate deallocation. This routine is probably full of
623: * race conditions!
624: */
625:
626: void vm_object_shutdown()
627: {
628: /*
629: * Clean up the object cache *before* we screw up the reference
630: * counts on all of the objects.
631: */
632:
633: vm_object_cache_clear();
634: }
635:
636: /*
637: * vm_object_pmap_copy:
638: *
639: * Makes all physical pages in the specified
640: * object range copy-on-write. No writeable
641: * references to these pages should remain.
642: *
643: * The object must *not* be locked.
644: */
645: void vm_object_pmap_copy(object, start, end)
646: register vm_object_t object;
647: register vm_offset_t start;
648: register vm_offset_t end;
649: {
650: register vm_page_t p;
651:
652: if (object == VM_OBJECT_NULL)
653: return;
654:
655: vm_object_lock(object);
656: p = (vm_page_t) queue_first(&object->memq);
657: while (!queue_end(&object->memq, (queue_entry_t) p)) {
658: if ((start <= p->offset) && (p->offset < end)) {
659: if (!p->copy_on_write) {
660: pmap_copy_on_write(VM_PAGE_TO_PHYS(p));
661: p->copy_on_write = TRUE;
662: }
663: }
664: p = (vm_page_t) queue_next(&p->listq);
665: }
666: vm_object_unlock(object);
667: }
668:
669: /*
670: * vm_object_pmap_remove:
671: *
672: * Removes all physical pages in the specified
673: * object range from all physical maps.
674: *
675: * The object must *not* be locked.
676: */
677: void vm_object_pmap_remove(object, start, end)
678: register vm_object_t object;
679: register vm_offset_t start;
680: register vm_offset_t end;
681: {
682: register vm_page_t p;
683:
684: if (object == VM_OBJECT_NULL)
685: return;
686:
687: vm_object_lock(object);
688: p = (vm_page_t) queue_first(&object->memq);
689: while (!queue_end(&object->memq, (queue_entry_t) p)) {
690: if ((start <= p->offset) && (p->offset < end)) {
691: pmap_remove_all(VM_PAGE_TO_PHYS(p));
692: }
693: p = (vm_page_t) queue_next(&p->listq);
694: }
695: vm_object_unlock(object);
696: }
697:
698: /*
699: * vm_object_copy:
700: *
701: * Create a new object which is a copy of an existing
702: * object, and mark all of the pages in the existing
703: * object 'copy-on-write'. The new object has one reference.
704: * Returns the new object.
705: *
706: * May defer the copy until later if the object is not backed
707: * up by a non-default pager.
708: */
709: void vm_object_copy(src_object, src_offset, size,
710: dst_object, dst_offset, src_needs_copy)
711: register vm_object_t src_object;
712: vm_offset_t src_offset;
713: vm_size_t size;
714: vm_object_t *dst_object; /* OUT */
715: vm_offset_t *dst_offset; /* OUT */
716: boolean_t *src_needs_copy; /* OUT */
717: {
718: register vm_object_t new_copy;
719: register vm_object_t old_copy;
720: vm_offset_t new_start, new_end;
721:
722: register vm_page_t p;
723:
724: if (src_object == VM_OBJECT_NULL) {
725: /*
726: * Nothing to copy
727: */
728: *dst_object = VM_OBJECT_NULL;
729: *dst_offset = 0;
730: *src_needs_copy = FALSE;
731: return;
732: }
733:
734: /*
735: * If the object's pager is null_pager or the
736: * default pager, we don't have to make a copy
737: * of it. Instead, we set the needs copy flag and
738: * make a shadow later.
739: */
740:
741: vm_object_lock(src_object);
742: if (src_object->pager == vm_pager_null ||
743: src_object->internal) {
744:
745: /*
746: * Make another reference to the object
747: */
748: src_object->ref_count++;
749:
750: /*
751: * Mark all of the pages copy-on-write.
752: */
753: for (p = (vm_page_t) queue_first(&src_object->memq);
754: !queue_end(&src_object->memq, (queue_entry_t)p);
755: p = (vm_page_t) queue_next(&p->listq)) {
756: if (src_offset <= p->offset &&
757: p->offset < src_offset + size)
758: p->copy_on_write = TRUE;
759: }
760: vm_object_unlock(src_object);
761:
762: *dst_object = src_object;
763: *dst_offset = src_offset;
764:
765: /*
766: * Must make a shadow when write is desired
767: */
768: *src_needs_copy = TRUE;
769: return;
770: }
771:
772: /*
773: * Try to collapse the object before copying it.
774: */
775: vm_object_collapse(src_object);
776:
777: /*
778: * If the object has a pager, the pager wants to
779: * see all of the changes. We need a copy-object
780: * for the changed pages.
781: *
782: * If there is a copy-object, and it is empty,
783: * no changes have been made to the object since the
784: * copy-object was made. We can use the same copy-
785: * object.
786: */
787:
788: Retry1:
789: old_copy = src_object->copy;
790: if (old_copy != VM_OBJECT_NULL) {
791: /*
792: * Try to get the locks (out of order)
793: */
794: if (!vm_object_lock_try(old_copy)) {
795: vm_object_unlock(src_object);
796:
797: /* should spin a bit here... */
798: vm_object_lock(src_object);
799: goto Retry1;
800: }
801:
802: if (old_copy->resident_page_count == 0 &&
803: old_copy->pager == vm_pager_null) {
804: /*
805: * Return another reference to
806: * the existing copy-object.
807: */
808: old_copy->ref_count++;
809: vm_object_unlock(old_copy);
810: vm_object_unlock(src_object);
811: *dst_object = old_copy;
812: *dst_offset = src_offset;
813: *src_needs_copy = FALSE;
814: return;
815: }
816: vm_object_unlock(old_copy);
817: }
818: vm_object_unlock(src_object);
819:
820: /*
821: * If the object has a pager, the pager wants
822: * to see all of the changes. We must make
823: * a copy-object and put the changed pages there.
824: *
825: * The copy-object is always made large enough to
826: * completely shadow the original object, since
827: * it may have several users who want to shadow
828: * the original object at different points.
829: */
830:
831: new_copy = vm_object_allocate(src_object->size);
832:
833: Retry2:
834: vm_object_lock(src_object);
835: /*
836: * Copy object may have changed while we were unlocked
837: */
838: old_copy = src_object->copy;
839: if (old_copy != VM_OBJECT_NULL) {
840: /*
841: * Try to get the locks (out of order)
842: */
843: if (!vm_object_lock_try(old_copy)) {
844: vm_object_unlock(src_object);
845: goto Retry2;
846: }
847:
848: /*
849: * Consistency check
850: */
851: if (old_copy->shadow != src_object ||
852: old_copy->shadow_offset != (vm_offset_t) 0)
853: panic("vm_object_copy: copy/shadow inconsistency");
854:
855: /*
856: * Make the old copy-object shadow the new one.
857: * It will receive no more pages from the original
858: * object.
859: */
860:
861: src_object->ref_count--; /* remove ref. from old_copy */
862: old_copy->shadow = new_copy;
863: new_copy->ref_count++; /* locking not needed - we
864: have the only pointer */
865: vm_object_unlock(old_copy); /* done with old_copy */
866: }
867:
868: new_start = (vm_offset_t) 0; /* always shadow original at 0 */
869: new_end = (vm_offset_t) new_copy->size; /* for the whole object */
870:
871: /*
872: * Point the new copy at the existing object.
873: */
874:
875: new_copy->shadow = src_object;
876: new_copy->shadow_offset = new_start;
877: src_object->ref_count++;
878: src_object->copy = new_copy;
879:
880: /*
881: * Mark all the affected pages of the existing object
882: * copy-on-write.
883: */
884: p = (vm_page_t) queue_first(&src_object->memq);
885: while (!queue_end(&src_object->memq, (queue_entry_t) p)) {
886: if ((new_start <= p->offset) && (p->offset < new_end)) {
887: p->copy_on_write = TRUE;
888: }
889: p = (vm_page_t) queue_next(&p->listq);
890: }
891:
892: vm_object_unlock(src_object);
893:
894: *dst_object = new_copy;
895: *dst_offset = src_offset - new_start;
896: *src_needs_copy = FALSE;
897: }
898:
899: /*
900: * vm_object_shadow:
901: *
902: * Create a new object which is backed by the
903: * specified existing object range. The source
904: * object reference is deallocated.
905: *
906: * The new object and offset into that object
907: * are returned in the source parameters.
908: */
909:
910: void vm_object_shadow(object, offset, length)
911: vm_object_t *object; /* IN/OUT */
912: vm_offset_t *offset; /* IN/OUT */
913: vm_size_t length;
914: {
915: register vm_object_t source;
916: register vm_object_t result;
917:
918: source = *object;
919:
920: /*
921: * Allocate a new object with the given length
922: */
923:
924: if ((result = vm_object_allocate(length)) == VM_OBJECT_NULL)
925: panic("vm_object_shadow: no object for shadowing");
926:
927: /*
928: * The new object shadows the source object, adding
929: * a reference to it. Our caller changes his reference
930: * to point to the new object, removing a reference to
931: * the source object. Net result: no change of reference
932: * count.
933: */
934: result->shadow = source;
935:
936: /*
937: * Store the offset into the source object,
938: * and fix up the offset into the new object.
939: */
940:
941: result->shadow_offset = *offset;
942:
943: /*
944: * Return the new things
945: */
946:
947: *offset = 0;
948: *object = result;
949: }
950:
951: /*
952: * Set the specified object's pager to the specified pager.
953: */
954:
955: void vm_object_setpager(object, pager, paging_offset,
956: read_only)
957: vm_object_t object;
958: vm_pager_t pager;
959: vm_offset_t paging_offset;
960: boolean_t read_only;
961: {
962: #ifdef lint
963: read_only++; /* No longer used */
964: #endif lint
965:
966: vm_object_lock(object); /* XXX ? */
967: object->pager = pager;
968: object->paging_offset = paging_offset;
969: vm_object_unlock(object); /* XXX ? */
970: }
971:
972: /*
973: * vm_object_hash hashes the pager/id pair.
974: */
975: /* Shift for sizeof(struct vm_object_hash_entry) */
976: #define VM_OBJECT_HASH_SHIFT 8
977: #define vm_object_hash(pager) \
978: ((((unsigned)pager) >> VM_OBJECT_HASH_SHIFT) % VM_OBJECT_HASH_COUNT)
979:
980: /*
981: * vm_object_lookup looks in the object cache for an object with the
982: * specified pager and paging id.
983: */
984:
985: vm_object_t vm_object_lookup(pager)
986: vm_pager_t pager;
987: {
988: register queue_t bucket;
989: register vm_object_hash_entry_t entry;
990: vm_object_t object;
991:
992: bucket = &vm_object_hashtable[vm_object_hash(pager)];
993:
994: vm_object_cache_lock();
995:
996: entry = (vm_object_hash_entry_t) queue_first(bucket);
997: while (!queue_end(bucket, (queue_entry_t) entry)) {
998: object = entry->object;
999: if (object->pager == pager) {
1000: vm_object_lock(object);
1001: if (object->ref_count == 0) {
1002: queue_remove(&vm_object_cached_list, object,
1003: vm_object_t, cached_list);
1004: vm_object_cached--;
1005: }
1006: object->ref_count++;
1007: vm_object_unlock(object);
1008: vm_object_cache_unlock();
1009: return(object);
1010: }
1011: entry = (vm_object_hash_entry_t) queue_next(&entry->hash_links);
1012: }
1013:
1014: vm_object_cache_unlock();
1015: return(VM_OBJECT_NULL);
1016: }
1017:
1018: /*
1019: * vm_object_enter enters the specified object/pager/id into
1020: * the hash table.
1021: */
1022:
1023: void vm_object_enter(object, pager)
1024: vm_object_t object;
1025: vm_pager_t pager;
1026: {
1027: register queue_t bucket;
1028: register vm_object_hash_entry_t entry;
1029:
1030: /*
1031: * We don't cache null objects, and we can't cache
1032: * objects with the null pager.
1033: */
1034:
1035: if (object == VM_OBJECT_NULL)
1036: return;
1037: if (pager == vm_pager_null)
1038: return;
1039:
1040: bucket = &vm_object_hashtable[vm_object_hash(pager)];
1041: entry = (vm_object_hash_entry_t) zalloc(object_hash_zone);
1042: entry->object = object;
1043: object->can_persist = TRUE;
1044:
1045: vm_object_cache_lock();
1046: queue_enter(bucket, entry, vm_object_hash_entry_t, hash_links);
1047: vm_object_cache_unlock();
1048: }
1049:
1050: /*
1051: * vm_object_remove:
1052: *
1053: * Remove the pager from the hash table.
1054: * Note: This assumes that the object cache
1055: * is locked. XXX this should be fixed
1056: * by reorganizing vm_object_deallocate.
1057: */
1058: vm_object_remove(pager)
1059: register vm_pager_t pager;
1060: {
1061: register queue_t bucket;
1062: register vm_object_hash_entry_t entry;
1063: register vm_object_t object;
1064:
1065: bucket = &vm_object_hashtable[vm_object_hash(pager)];
1066:
1067: entry = (vm_object_hash_entry_t) queue_first(bucket);
1068: while (!queue_end(bucket, (queue_entry_t) entry)) {
1069: object = entry->object;
1070: if (object->pager == pager) {
1071: queue_remove(bucket, entry, vm_object_hash_entry_t,
1072: hash_links);
1073: zfree(object_hash_zone, (vm_offset_t) entry);
1074: break;
1075: }
1076: entry = (vm_object_hash_entry_t) queue_next(&entry->hash_links);
1077: }
1078: }
1079:
1080: /*
1081: * vm_object_cache_clear removes all objects from the cache.
1082: *
1083: */
1084:
1085: void vm_object_cache_clear()
1086: {
1087: register vm_object_t object;
1088:
1089: /*
1090: * Remove each object in the cache by scanning down the
1091: * list of cached objects.
1092: */
1093: vm_object_cache_lock();
1094: while (!queue_empty(&vm_object_cached_list)) {
1095: object = (vm_object_t) queue_first(&vm_object_cached_list);
1096: vm_object_cache_unlock();
1097:
1098: /*
1099: * Note: it is important that we use vm_object_lookup
1100: * to gain a reference, and not vm_object_reference, because
1101: * the logic for removing an object from the cache lies in
1102: * lookup.
1103: */
1104: if (object != vm_object_lookup(object->pager))
1105: panic("vm_object_cache_clear: I'm sooo confused.");
1106: vm_object_cache_object(object, FALSE);
1107:
1108: vm_object_cache_lock();
1109: }
1110: vm_object_cache_unlock();
1111: }
1112:
1113: /*
1114: * Remove some number of entries from the object cache.
1115: */
1116: int
1117: vm_object_cache_steal(num)
1118: register int num;
1119: {
1120: register vm_object_t object;
1121: register int num_removed = 0;
1122:
1123: vm_object_cache_lock();
1124: while (num_removed < num && !queue_empty(&vm_object_cached_list)) {
1125: object = (vm_object_t) queue_first(&vm_object_cached_list);
1126: vm_object_cache_unlock();
1127:
1128: if (object != vm_object_lookup(object->pager))
1129: panic("vm_object_cache_steal: I'm sooo confused.");
1130: vm_object_cache_object(object, FALSE);
1131: num_removed++;
1132:
1133: vm_object_cache_lock();
1134: }
1135: vm_object_cache_unlock();
1136:
1137: return(num_removed);
1138: }
1139:
1140: boolean_t vm_object_collapse_allowed = TRUE;
1141: /*
1142: * vm_object_collapse:
1143: *
1144: * Collapse an object with the object backing it.
1145: * Pages in the backing object are moved into the
1146: * parent, and the backing object is deallocated.
1147: *
1148: * Requires that the object be locked and the page
1149: * queues be unlocked.
1150: *
1151: */
1152: void vm_object_collapse(object)
1153: register vm_object_t object;
1154:
1155: {
1156: register vm_object_t backing_object;
1157: register vm_offset_t backing_offset;
1158: register vm_size_t size;
1159: register vm_offset_t new_offset;
1160: register vm_page_t p, pp;
1161:
1162: if (!vm_object_collapse_allowed)
1163: return;
1164:
1165: while (TRUE) {
1166: /*
1167: * Verify that the conditions are right for collapse:
1168: *
1169: * The object exists and no pages in it are currently
1170: * being paged out (or have ever been paged out).
1171: */
1172: if (object == VM_OBJECT_NULL ||
1173: object->paging_in_progress != 0 ||
1174: object->pager != vm_pager_null)
1175: return;
1176:
1177: /*
1178: * There is a backing object, and
1179: */
1180:
1181: if ((backing_object = object->shadow) == VM_OBJECT_NULL)
1182: return;
1183:
1184: vm_object_lock(backing_object);
1185: /*
1186: * ...
1187: * The backing object is not read_only,
1188: * and no pages in the backing object are
1189: * currently being paged out.
1190: * The backing object is internal.
1191: */
1192:
1193: if (!backing_object->internal ||
1194: backing_object->paging_in_progress != 0) {
1195: vm_object_unlock(backing_object);
1196: return;
1197: }
1198:
1199: /*
1200: * The backing object can't be a copy-object:
1201: * the shadow_offset for the copy-object must stay
1202: * as 0. Furthermore (for the 'we have all the
1203: * pages' case), if we bypass backing_object and
1204: * just shadow the next object in the chain, old
1205: * pages from that object would then have to be copied
1206: * BOTH into the (former) backing_object and into the
1207: * parent object.
1208: */
1209: if (backing_object->shadow != VM_OBJECT_NULL &&
1210: backing_object->shadow->copy != VM_OBJECT_NULL) {
1211: vm_object_unlock(backing_object);
1212: return;
1213: }
1214:
1215: /*
1216: * We know that we can either collapse the backing
1217: * object (if the parent is the only reference to
1218: * it) or (perhaps) remove the parent's reference
1219: * to it.
1220: */
1221:
1222: backing_offset = object->shadow_offset;
1223: size = object->size;
1224:
1225: /*
1226: * If there is exactly one reference to the backing
1227: * object, we can collapse it into the parent.
1228: */
1229:
1230: if (backing_object->ref_count == 1) {
1231:
1232: /*
1233: * We can collapse the backing object.
1234: *
1235: * Move all in-memory pages from backing_object
1236: * to the parent. Pages that have been paged out
1237: * will be overwritten by any of the parent's
1238: * pages that shadow them.
1239: */
1240:
1241: while (!queue_empty(&backing_object->memq)) {
1242:
1243: p = (vm_page_t)
1244: queue_first(&backing_object->memq);
1245:
1246: new_offset = (p->offset - backing_offset);
1247:
1248: /*
1249: * If the parent has a page here, or if
1250: * this page falls outside the parent,
1251: * dispose of it.
1252: *
1253: * Otherwise, move it as planned.
1254: */
1255:
1256: if (p->offset < backing_offset ||
1257: new_offset >= size) {
1258: vm_page_lock_queues();
1259: vm_page_free(p);
1260: vm_page_unlock_queues();
1261: } else {
1262: pp = vm_page_lookup(object, new_offset);
1263: if (pp != VM_PAGE_NULL) {
1264: vm_page_lock_queues();
1265: vm_page_free(p);
1266: vm_page_unlock_queues();
1267: }
1268: else {
1269: vm_page_rename(p, object, new_offset);
1270: }
1271: }
1272: }
1273:
1274: /*
1275: * Move the pager from backing_object to object.
1276: *
1277: * XXX We're only using part of the paging space
1278: * for keeps now... we ought to discard the
1279: * unused portion.
1280: */
1281:
1282: object->pager = backing_object->pager;
1283: object->paging_offset =
1284: backing_object->paging_offset + backing_offset;
1285:
1286: backing_object->pager = vm_pager_null;
1287: backing_object->pager_request = PORT_NULL;
1288: backing_object->pager_name = PORT_NULL;
1289:
1290: /*
1291: * Object now shadows whatever backing_object did.
1292: * Note that the reference to backing_object->shadow
1293: * moves from within backing_object to within object.
1294: */
1295:
1296: object->shadow = backing_object->shadow;
1297: object->shadow_offset += backing_object->shadow_offset;
1298: if (object->shadow != VM_OBJECT_NULL &&
1299: object->shadow->copy != VM_OBJECT_NULL) {
1300: panic("vm_object_collapse: we collapsed a copy-object!");
1301: }
1302: /*
1303: * Discard backing_object.
1304: *
1305: * Since the backing object has no pages, no
1306: * pager left, and no object references within it,
1307: * all that is necessary is to dispose of it.
1308: */
1309:
1310: vm_object_unlock(backing_object);
1311:
1312: simple_lock(&vm_object_list_lock);
1313: queue_remove(&vm_object_list, backing_object,
1314: vm_object_t, object_list);
1315: vm_object_count--;
1316: simple_unlock(&vm_object_list_lock);
1317:
1318: zfree(vm_object_zone, (vm_offset_t) backing_object);
1319:
1320: object_collapses++;
1321: }
1322: else {
1323: /*
1324: * If all of the pages in the backing object are
1325: * shadowed by the parent object, the parent
1326: * object no longer has to shadow the backing
1327: * object; it can shadow the next one in the
1328: * chain.
1329: *
1330: * The backing object must not be paged out - we'd
1331: * have to check all of the paged-out pages, as
1332: * well.
1333: */
1334:
1335: if (backing_object->pager != vm_pager_null) {
1336: vm_object_unlock(backing_object);
1337: return;
1338: }
1339:
1340: /*
1341: * Should have a check for a 'small' number
1342: * of pages here.
1343: */
1344:
1345: p = (vm_page_t) queue_first(&backing_object->memq);
1346: while (!queue_end(&backing_object->memq,
1347: (queue_entry_t) p)) {
1348:
1349: new_offset = (p->offset - backing_offset);
1350:
1351: /*
1352: * If the parent has a page here, or if
1353: * this page falls outside the parent,
1354: * keep going.
1355: *
1356: * Otherwise, the backing_object must be
1357: * left in the chain.
1358: */
1359:
1360: if (p->offset >= backing_offset &&
1361: new_offset <= size &&
1362: (pp = vm_page_lookup(object, new_offset))
1363: == VM_PAGE_NULL) {
1364: /*
1365: * Page still needed.
1366: * Can't go any further.
1367: */
1368: vm_object_unlock(backing_object);
1369: return;
1370: }
1371: p = (vm_page_t) queue_next(&p->listq);
1372: }
1373:
1374: /*
1375: * Make the parent shadow the next object
1376: * in the chain. Deallocating backing_object
1377: * will not remove it, since its reference
1378: * count is at least 2.
1379: */
1380:
1381: vm_object_reference(object->shadow = backing_object->shadow);
1382: object->shadow_offset += backing_object->shadow_offset;
1383:
1384: /* Drop the reference count on backing_object.
1385: * Since its ref_count was at least 2, it
1386: * will not vanish; so we don't need to call
1387: * vm_object_deallocate.
1388: */
1389: backing_object->ref_count--;
1390: vm_object_unlock(backing_object);
1391:
1392: object_bypasses ++;
1393:
1394: }
1395:
1396: /*
1397: * Try again with this object's new backing object.
1398: */
1399: }
1400: }
1401:
1402: /*
1403: * vm_object_page_remove: [internal]
1404: *
1405: * Removes all physical pages in the specified
1406: * object range from the object's list of pages.
1407: *
1408: * The object must be locked.
1409: */
1410: void vm_object_page_remove(object, start, end)
1411: register vm_object_t object;
1412: register vm_offset_t start;
1413: register vm_offset_t end;
1414: {
1415: register vm_page_t p, next;
1416:
1417: if (object == VM_OBJECT_NULL)
1418: return;
1419:
1420: p = (vm_page_t) queue_first(&object->memq);
1421: while (!queue_end(&object->memq, (queue_entry_t) p)) {
1422: next = (vm_page_t) queue_next(&p->listq);
1423: if ((start <= p->offset) && (p->offset < end)) {
1424: pmap_remove_all(VM_PAGE_TO_PHYS(p));
1425: vm_page_lock_queues();
1426: vm_page_free(p);
1427: vm_page_unlock_queues();
1428: }
1429: p = next;
1430: }
1431: }
1432:
1433: /*
1434: * Routine: vm_object_coalesce
1435: * Function: Coalesces two objects backing up adjoining
1436: * regions of memory into a single object.
1437: *
1438: * returns TRUE if objects were combined.
1439: *
1440: * NOTE: Only works at the moment if the second object is NULL -
1441: * if it's not, which object do we lock first?
1442: *
1443: * Parameters:
1444: * prev_object First object to coalesce
1445: * prev_offset Offset into prev_object
1446: * next_object Second object into coalesce
1447: * next_offset Offset into next_object
1448: *
1449: * prev_size Size of reference to prev_object
1450: * next_size Size of reference to next_object
1451: *
1452: * Conditions:
1453: * The object must *not* be locked.
1454: */
1455: boolean_t vm_object_coalesce(prev_object, next_object,
1456: prev_offset, next_offset,
1457: prev_size, next_size)
1458:
1459: register vm_object_t prev_object;
1460: vm_object_t next_object;
1461: vm_offset_t prev_offset, next_offset;
1462: vm_size_t prev_size, next_size;
1463: {
1464: vm_size_t newsize;
1465:
1466: #ifdef lint
1467: next_offset++;
1468: #endif lint
1469:
1470: if (next_object != VM_OBJECT_NULL) {
1471: return(FALSE);
1472: }
1473:
1474: if (prev_object == VM_OBJECT_NULL) {
1475: return(TRUE);
1476: }
1477:
1478: vm_object_lock(prev_object);
1479:
1480: /*
1481: * Try to collapse the object first
1482: */
1483: vm_object_collapse(prev_object);
1484:
1485: /*
1486: * Can't coalesce if:
1487: * . more than one reference
1488: * . paged out
1489: * . shadows another object
1490: * . has a copy elsewhere
1491: * (any of which mean that the pages not mapped to
1492: * prev_entry may be in use anyway)
1493: */
1494:
1495: if (prev_object->ref_count > 1 ||
1496: prev_object->pager != vm_pager_null ||
1497: prev_object->shadow != VM_OBJECT_NULL ||
1498: prev_object->copy != VM_OBJECT_NULL) {
1499: vm_object_unlock(prev_object);
1500: return(FALSE);
1501: }
1502:
1503: /*
1504: * Remove any pages that may still be in the object from
1505: * a previous deallocation.
1506: */
1507:
1508: vm_object_page_remove(prev_object,
1509: prev_offset + prev_size,
1510: prev_offset + prev_size + next_size);
1511:
1512: /*
1513: * Extend the object if necessary.
1514: */
1515: newsize = prev_offset + prev_size + next_size;
1516: if (newsize > prev_object->size)
1517: prev_object->size = newsize;
1518:
1519: vm_object_unlock(prev_object);
1520: return(TRUE);
1521: }
1522:
1523: vm_object_t vm_object_request_object(p)
1524: port_t p;
1525: {
1526: #ifdef lint
1527: p++;
1528: #endif lint
1529: printf("vm_object_request_object: called\n");
1530: return(VM_OBJECT_NULL);
1531: }
1532:
1533: /*
1534: * Routine: vm_object_name
1535: * Purpose:
1536: * Returns a reference to the "name" port associated
1537: * with this object.
1538: */
1539: port_t vm_object_name(object)
1540: vm_object_t object;
1541: {
1542: return ((port_t)object);
1543: }
1544:
1545: #if DEBUG
1546: /*
1547: * vm_object_print: [ debug ]
1548: */
1549: void vm_object_print(object)
1550: vm_object_t object;
1551: {
1552: register vm_page_t p;
1553: extern indent;
1554:
1555: register int count;
1556:
1557: if (object == VM_OBJECT_NULL)
1558: return;
1559:
1560: iprintf("Object 0x%x: size=0x%x, ref=%d, pager=0x%x+0x%x, shadow=(0x%x)+0x%x\n",
1561: (int) object, (int) object->size, object->ref_count, (int) object->pager,
1562: (int) object->paging_offset,
1563: (int) object->shadow, (int) object->shadow_offset);
1564:
1565: indent += 2;
1566:
1567: count = 0;
1568: p = (vm_page_t) queue_first(&object->memq);
1569: while (!queue_end(&object->memq, (queue_entry_t) p)) {
1570: if (count == 0) iprintf("memory:=");
1571: else if (count == 6) {printf("\n"); iprintf(" ..."); count = 0;}
1572: else printf(",");
1573: count++;
1574:
1575: printf("(off=0x%x,page=0x%x)", p->offset, VM_PAGE_TO_PHYS(p));
1576: p = (vm_page_t) queue_next(&p->listq);
1577: }
1578: if (count != 0)
1579: printf("\n");
1580: indent -= 2;
1581: }
1582: #endif DEBUG
1583:
1584:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.