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