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