|
|
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();
457: vm_page_deactivate(p);
458: vm_page_unlock_queues();
459: p = next;
460: }
461: }
462:
463: /*
464: * Trim the object cache to size.
465: */
466: vm_object_cache_trim()
467: {
468: register vm_object_t object;
469:
470: vm_object_cache_lock();
471: while (vm_object_cached > vm_cache_max) {
472: object = (vm_object_t) queue_first(&vm_object_cached_list);
473: vm_object_cache_unlock();
474:
475: if (object != vm_object_lookup(object->pager))
476: panic("vm_object_deactivate: I'm sooo confused.");
477:
478: pager_cache(object, FALSE);
479:
480: vm_object_cache_lock();
481: }
482: vm_object_cache_unlock();
483: }
484:
485:
486: /*
487: * vm_object_shutdown()
488: *
489: * Shut down the object system. Unfortunately, while we
490: * may be trying to do this, init is happily waiting for
491: * processes to exit, and therefore will be causing some objects
492: * to be deallocated. To handle this, we gain a fake reference
493: * to all objects we release paging areas for. This will prevent
494: * a duplicate deallocation. This routine is probably full of
495: * race conditions!
496: */
497:
498: void vm_object_shutdown()
499: {
500: register vm_object_t object;
501:
502: /*
503: * Clean up the object cache *before* we screw up the reference
504: * counts on all of the objects.
505: */
506:
507: vm_object_cache_clear();
508:
509: printf("free paging spaces: ");
510:
511: /*
512: * First we gain a reference to each object so that
513: * no one else will deallocate them.
514: */
515:
516: simple_lock(&vm_object_list_lock);
517: object = (vm_object_t) queue_first(&vm_object_list);
518: while (!queue_end(&vm_object_list, (queue_entry_t) object)) {
519: vm_object_reference(object);
520: object = (vm_object_t) queue_next(&object->object_list);
521: }
522: simple_unlock(&vm_object_list_lock);
523:
524: /*
525: * Now we deallocate all the paging areas. We don't need
526: * to lock anything because we've reduced to a single
527: * processor while shutting down. This also assumes that
528: * no new objects are being created.
529: */
530:
531: object = (vm_object_t) queue_first(&vm_object_list);
532: while (!queue_end(&vm_object_list, (queue_entry_t) object)) {
533: if (object->pager != NULL)
534: vm_pager_deallocate(object->pager);
535: object = (vm_object_t) queue_next(&object->object_list);
536: printf(".");
537: }
538: printf("done.\n");
539: }
540:
541: /*
542: * vm_object_pmap_copy:
543: *
544: * Makes all physical pages in the specified
545: * object range copy-on-write. No writeable
546: * references to these pages should remain.
547: *
548: * The object must *not* be locked.
549: */
550: void vm_object_pmap_copy(object, start, end)
551: register vm_object_t object;
552: register vm_offset_t start;
553: register vm_offset_t end;
554: {
555: register vm_page_t p;
556:
557: if (object == NULL)
558: return;
559:
560: vm_object_lock(object);
561: p = (vm_page_t) queue_first(&object->memq);
562: while (!queue_end(&object->memq, (queue_entry_t) p)) {
563: if ((start <= p->offset) && (p->offset < end)) {
564: pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_READ);
565: p->copy_on_write = TRUE;
566: }
567: p = (vm_page_t) queue_next(&p->listq);
568: }
569: vm_object_unlock(object);
570: }
571:
572: /*
573: * vm_object_pmap_remove:
574: *
575: * Removes all physical pages in the specified
576: * object range from all physical maps.
577: *
578: * The object must *not* be locked.
579: */
580: void vm_object_pmap_remove(object, start, end)
581: register vm_object_t object;
582: register vm_offset_t start;
583: register vm_offset_t end;
584: {
585: register vm_page_t p;
586:
587: if (object == NULL)
588: return;
589:
590: vm_object_lock(object);
591: p = (vm_page_t) queue_first(&object->memq);
592: while (!queue_end(&object->memq, (queue_entry_t) p)) {
593: if ((start <= p->offset) && (p->offset < end))
594: pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_NONE);
595: p = (vm_page_t) queue_next(&p->listq);
596: }
597: vm_object_unlock(object);
598: }
599:
600: /*
601: * vm_object_copy:
602: *
603: * Create a new object which is a copy of an existing
604: * object, and mark all of the pages in the existing
605: * object 'copy-on-write'. The new object has one reference.
606: * Returns the new object.
607: *
608: * May defer the copy until later if the object is not backed
609: * up by a non-default pager.
610: */
611: void vm_object_copy(src_object, src_offset, size,
612: dst_object, dst_offset, src_needs_copy)
613: register vm_object_t src_object;
614: vm_offset_t src_offset;
615: vm_size_t size;
616: vm_object_t *dst_object; /* OUT */
617: vm_offset_t *dst_offset; /* OUT */
618: boolean_t *src_needs_copy; /* OUT */
619: {
620: register vm_object_t new_copy;
621: register vm_object_t old_copy;
622: vm_offset_t new_start, new_end;
623:
624: register vm_page_t p;
625:
626: if (src_object == NULL) {
627: /*
628: * Nothing to copy
629: */
630: *dst_object = NULL;
631: *dst_offset = 0;
632: *src_needs_copy = FALSE;
633: return;
634: }
635:
636: /*
637: * If the object's pager is null_pager or the
638: * default pager, we don't have to make a copy
639: * of it. Instead, we set the needs copy flag and
640: * make a shadow later.
641: */
642:
643: vm_object_lock(src_object);
644: if (src_object->pager == NULL ||
645: src_object->internal) {
646:
647: /*
648: * Make another reference to the object
649: */
650: src_object->ref_count++;
651:
652: /*
653: * Mark all of the pages copy-on-write.
654: */
655: for (p = (vm_page_t) queue_first(&src_object->memq);
656: !queue_end(&src_object->memq, (queue_entry_t)p);
657: p = (vm_page_t) queue_next(&p->listq)) {
658: if (src_offset <= p->offset &&
659: p->offset < src_offset + size)
660: p->copy_on_write = TRUE;
661: }
662: vm_object_unlock(src_object);
663:
664: *dst_object = src_object;
665: *dst_offset = src_offset;
666:
667: /*
668: * Must make a shadow when write is desired
669: */
670: *src_needs_copy = TRUE;
671: return;
672: }
673:
674: /*
675: * Try to collapse the object before copying it.
676: */
677: vm_object_collapse(src_object);
678:
679: /*
680: * If the object has a pager, the pager wants to
681: * see all of the changes. We need a copy-object
682: * for the changed pages.
683: *
684: * If there is a copy-object, and it is empty,
685: * no changes have been made to the object since the
686: * copy-object was made. We can use the same copy-
687: * object.
688: */
689:
690: Retry1:
691: old_copy = src_object->copy;
692: if (old_copy != NULL) {
693: /*
694: * Try to get the locks (out of order)
695: */
696: if (!vm_object_lock_try(old_copy)) {
697: vm_object_unlock(src_object);
698:
699: /* should spin a bit here... */
700: vm_object_lock(src_object);
701: goto Retry1;
702: }
703:
704: if (old_copy->resident_page_count == 0 &&
705: old_copy->pager == NULL) {
706: /*
707: * Return another reference to
708: * the existing copy-object.
709: */
710: old_copy->ref_count++;
711: vm_object_unlock(old_copy);
712: vm_object_unlock(src_object);
713: *dst_object = old_copy;
714: *dst_offset = src_offset;
715: *src_needs_copy = FALSE;
716: return;
717: }
718: vm_object_unlock(old_copy);
719: }
720: vm_object_unlock(src_object);
721:
722: /*
723: * If the object has a pager, the pager wants
724: * to see all of the changes. We must make
725: * a copy-object and put the changed pages there.
726: *
727: * The copy-object is always made large enough to
728: * completely shadow the original object, since
729: * it may have several users who want to shadow
730: * the original object at different points.
731: */
732:
733: new_copy = vm_object_allocate(src_object->size);
734:
735: Retry2:
736: vm_object_lock(src_object);
737: /*
738: * Copy object may have changed while we were unlocked
739: */
740: old_copy = src_object->copy;
741: if (old_copy != NULL) {
742: /*
743: * Try to get the locks (out of order)
744: */
745: if (!vm_object_lock_try(old_copy)) {
746: vm_object_unlock(src_object);
747: goto Retry2;
748: }
749:
750: /*
751: * Consistency check
752: */
753: if (old_copy->shadow != src_object ||
754: old_copy->shadow_offset != (vm_offset_t) 0)
755: panic("vm_object_copy: copy/shadow inconsistency");
756:
757: /*
758: * Make the old copy-object shadow the new one.
759: * It will receive no more pages from the original
760: * object.
761: */
762:
763: src_object->ref_count--; /* remove ref. from old_copy */
764: old_copy->shadow = new_copy;
765: new_copy->ref_count++; /* locking not needed - we
766: have the only pointer */
767: vm_object_unlock(old_copy); /* done with old_copy */
768: }
769:
770: new_start = (vm_offset_t) 0; /* always shadow original at 0 */
771: new_end = (vm_offset_t) new_copy->size; /* for the whole object */
772:
773: /*
774: * Point the new copy at the existing object.
775: */
776:
777: new_copy->shadow = src_object;
778: new_copy->shadow_offset = new_start;
779: src_object->ref_count++;
780: src_object->copy = new_copy;
781:
782: /*
783: * Mark all the affected pages of the existing object
784: * copy-on-write.
785: */
786: p = (vm_page_t) queue_first(&src_object->memq);
787: while (!queue_end(&src_object->memq, (queue_entry_t) p)) {
788: if ((new_start <= p->offset) && (p->offset < new_end))
789: p->copy_on_write = TRUE;
790: p = (vm_page_t) queue_next(&p->listq);
791: }
792:
793: vm_object_unlock(src_object);
794:
795: *dst_object = new_copy;
796: *dst_offset = src_offset - new_start;
797: *src_needs_copy = FALSE;
798: }
799:
800: /*
801: * vm_object_shadow:
802: *
803: * Create a new object which is backed by the
804: * specified existing object range. The source
805: * object reference is deallocated.
806: *
807: * The new object and offset into that object
808: * are returned in the source parameters.
809: */
810:
811: void vm_object_shadow(object, offset, length)
812: vm_object_t *object; /* IN/OUT */
813: vm_offset_t *offset; /* IN/OUT */
814: vm_size_t length;
815: {
816: register vm_object_t source;
817: register vm_object_t result;
818:
819: source = *object;
820:
821: /*
822: * Allocate a new object with the given length
823: */
824:
825: if ((result = vm_object_allocate(length)) == NULL)
826: panic("vm_object_shadow: no object for shadowing");
827:
828: /*
829: * The new object shadows the source object, adding
830: * a reference to it. Our caller changes his reference
831: * to point to the new object, removing a reference to
832: * the source object. Net result: no change of reference
833: * count.
834: */
835: result->shadow = source;
836:
837: /*
838: * Store the offset into the source object,
839: * and fix up the offset into the new object.
840: */
841:
842: result->shadow_offset = *offset;
843:
844: /*
845: * Return the new things
846: */
847:
848: *offset = 0;
849: *object = result;
850: }
851:
852: /*
853: * Set the specified object's pager to the specified pager.
854: */
855:
856: void vm_object_setpager(object, pager, paging_offset,
857: read_only)
858: vm_object_t object;
859: vm_pager_t pager;
860: vm_offset_t paging_offset;
861: boolean_t read_only;
862: {
863: #ifdef lint
864: read_only++; /* No longer used */
865: #endif lint
866:
867: vm_object_lock(object); /* XXX ? */
868: object->pager = pager;
869: object->paging_offset = paging_offset;
870: vm_object_unlock(object); /* XXX ? */
871: }
872:
873: /*
874: * vm_object_hash hashes the pager/id pair.
875: */
876:
877: #define vm_object_hash(pager) \
878: (((unsigned)pager)%VM_OBJECT_HASH_COUNT)
879:
880: /*
881: * vm_object_lookup looks in the object cache for an object with the
882: * specified pager and paging id.
883: */
884:
885: vm_object_t vm_object_lookup(pager)
886: vm_pager_t pager;
887: {
888: register queue_t bucket;
889: register vm_object_hash_entry_t entry;
890: vm_object_t object;
891:
892: bucket = &vm_object_hashtable[vm_object_hash(pager)];
893:
894: vm_object_cache_lock();
895:
896: entry = (vm_object_hash_entry_t) queue_first(bucket);
897: while (!queue_end(bucket, (queue_entry_t) entry)) {
898: object = entry->object;
899: if (object->pager == pager) {
900: vm_object_lock(object);
901: if (object->ref_count == 0) {
902: queue_remove(&vm_object_cached_list, object,
903: vm_object_t, cached_list);
904: vm_object_cached--;
905: }
906: object->ref_count++;
907: vm_object_unlock(object);
908: vm_object_cache_unlock();
909: return(object);
910: }
911: entry = (vm_object_hash_entry_t) queue_next(&entry->hash_links);
912: }
913:
914: vm_object_cache_unlock();
915: return(NULL);
916: }
917:
918: /*
919: * vm_object_enter enters the specified object/pager/id into
920: * the hash table.
921: */
922:
923: void vm_object_enter(object, pager)
924: vm_object_t object;
925: vm_pager_t pager;
926: {
927: register queue_t bucket;
928: register vm_object_hash_entry_t entry;
929:
930: /*
931: * We don't cache null objects, and we can't cache
932: * objects with the null pager.
933: */
934:
935: if (object == NULL)
936: return;
937: if (pager == NULL)
938: return;
939:
940: bucket = &vm_object_hashtable[vm_object_hash(pager)];
941: entry = (vm_object_hash_entry_t)
942: malloc((u_long)sizeof *entry, M_VMOBJHASH, M_WAITOK);
943: entry->object = object;
944: object->can_persist = TRUE;
945:
946: vm_object_cache_lock();
947: queue_enter(bucket, entry, vm_object_hash_entry_t, hash_links);
948: vm_object_cache_unlock();
949: }
950:
951: /*
952: * vm_object_remove:
953: *
954: * Remove the pager from the hash table.
955: * Note: This assumes that the object cache
956: * is locked. XXX this should be fixed
957: * by reorganizing vm_object_deallocate.
958: */
959: vm_object_remove(pager)
960: register vm_pager_t pager;
961: {
962: register queue_t bucket;
963: register vm_object_hash_entry_t entry;
964: register vm_object_t object;
965:
966: bucket = &vm_object_hashtable[vm_object_hash(pager)];
967:
968: entry = (vm_object_hash_entry_t) queue_first(bucket);
969: while (!queue_end(bucket, (queue_entry_t) entry)) {
970: object = entry->object;
971: if (object->pager == pager) {
972: queue_remove(bucket, entry, vm_object_hash_entry_t,
973: hash_links);
974: free((caddr_t)entry, M_VMOBJHASH);
975: break;
976: }
977: entry = (vm_object_hash_entry_t) queue_next(&entry->hash_links);
978: }
979: }
980:
981: /*
982: * vm_object_cache_clear removes all objects from the cache.
983: *
984: */
985:
986: void vm_object_cache_clear()
987: {
988: register vm_object_t object;
989:
990: /*
991: * Remove each object in the cache by scanning down the
992: * list of cached objects.
993: */
994: vm_object_cache_lock();
995: while (!queue_empty(&vm_object_cached_list)) {
996: object = (vm_object_t) queue_first(&vm_object_cached_list);
997: vm_object_cache_unlock();
998:
999: /*
1000: * Note: it is important that we use vm_object_lookup
1001: * to gain a reference, and not vm_object_reference, because
1002: * the logic for removing an object from the cache lies in
1003: * lookup.
1004: */
1005: if (object != vm_object_lookup(object->pager))
1006: panic("vm_object_cache_clear: I'm sooo confused.");
1007: pager_cache(object, FALSE);
1008:
1009: vm_object_cache_lock();
1010: }
1011: vm_object_cache_unlock();
1012: }
1013:
1014: boolean_t vm_object_collapse_allowed = TRUE;
1015: /*
1016: * vm_object_collapse:
1017: *
1018: * Collapse an object with the object backing it.
1019: * Pages in the backing object are moved into the
1020: * parent, and the backing object is deallocated.
1021: *
1022: * Requires that the object be locked and the page
1023: * queues be unlocked.
1024: *
1025: */
1026: void vm_object_collapse(object)
1027: register vm_object_t object;
1028:
1029: {
1030: register vm_object_t backing_object;
1031: register vm_offset_t backing_offset;
1032: register vm_size_t size;
1033: register vm_offset_t new_offset;
1034: register vm_page_t p, pp;
1035:
1036: if (!vm_object_collapse_allowed)
1037: return;
1038:
1039: while (TRUE) {
1040: /*
1041: * Verify that the conditions are right for collapse:
1042: *
1043: * The object exists and no pages in it are currently
1044: * being paged out (or have ever been paged out).
1045: */
1046: if (object == NULL ||
1047: object->paging_in_progress != 0 ||
1048: object->pager != NULL)
1049: return;
1050:
1051: /*
1052: * There is a backing object, and
1053: */
1054:
1055: if ((backing_object = object->shadow) == NULL)
1056: return;
1057:
1058: vm_object_lock(backing_object);
1059: /*
1060: * ...
1061: * The backing object is not read_only,
1062: * and no pages in the backing object are
1063: * currently being paged out.
1064: * The backing object is internal.
1065: */
1066:
1067: if (!backing_object->internal ||
1068: backing_object->paging_in_progress != 0) {
1069: vm_object_unlock(backing_object);
1070: return;
1071: }
1072:
1073: /*
1074: * The backing object can't be a copy-object:
1075: * the shadow_offset for the copy-object must stay
1076: * as 0. Furthermore (for the 'we have all the
1077: * pages' case), if we bypass backing_object and
1078: * just shadow the next object in the chain, old
1079: * pages from that object would then have to be copied
1080: * BOTH into the (former) backing_object and into the
1081: * parent object.
1082: */
1083: if (backing_object->shadow != NULL &&
1084: backing_object->shadow->copy != NULL) {
1085: vm_object_unlock(backing_object);
1086: return;
1087: }
1088:
1089: /*
1090: * We know that we can either collapse the backing
1091: * object (if the parent is the only reference to
1092: * it) or (perhaps) remove the parent's reference
1093: * to it.
1094: */
1095:
1096: backing_offset = object->shadow_offset;
1097: size = object->size;
1098:
1099: /*
1100: * If there is exactly one reference to the backing
1101: * object, we can collapse it into the parent.
1102: */
1103:
1104: if (backing_object->ref_count == 1) {
1105:
1106: /*
1107: * We can collapse the backing object.
1108: *
1109: * Move all in-memory pages from backing_object
1110: * to the parent. Pages that have been paged out
1111: * will be overwritten by any of the parent's
1112: * pages that shadow them.
1113: */
1114:
1115: while (!queue_empty(&backing_object->memq)) {
1116:
1117: p = (vm_page_t)
1118: queue_first(&backing_object->memq);
1119:
1120: new_offset = (p->offset - backing_offset);
1121:
1122: /*
1123: * If the parent has a page here, or if
1124: * this page falls outside the parent,
1125: * dispose of it.
1126: *
1127: * Otherwise, move it as planned.
1128: */
1129:
1130: if (p->offset < backing_offset ||
1131: new_offset >= size) {
1132: vm_page_lock_queues();
1133: vm_page_free(p);
1134: vm_page_unlock_queues();
1135: } else {
1136: pp = vm_page_lookup(object, new_offset);
1137: if (pp != NULL && !pp->fake) {
1138: vm_page_lock_queues();
1139: vm_page_free(p);
1140: vm_page_unlock_queues();
1141: }
1142: else {
1143: if (pp) {
1144: /* may be someone waiting for it */
1145: PAGE_WAKEUP(pp);
1146: vm_page_lock_queues();
1147: vm_page_free(pp);
1148: vm_page_unlock_queues();
1149: }
1150: vm_page_rename(p, object, new_offset);
1151: }
1152: }
1153: }
1154:
1155: /*
1156: * Move the pager from backing_object to object.
1157: *
1158: * XXX We're only using part of the paging space
1159: * for keeps now... we ought to discard the
1160: * unused portion.
1161: */
1162:
1163: object->pager = backing_object->pager;
1164: object->paging_offset += backing_offset;
1165:
1166: backing_object->pager = NULL;
1167:
1168: /*
1169: * Object now shadows whatever backing_object did.
1170: * Note that the reference to backing_object->shadow
1171: * moves from within backing_object to within object.
1172: */
1173:
1174: object->shadow = backing_object->shadow;
1175: object->shadow_offset += backing_object->shadow_offset;
1176: if (object->shadow != NULL &&
1177: object->shadow->copy != NULL) {
1178: panic("vm_object_collapse: we collapsed a copy-object!");
1179: }
1180: /*
1181: * Discard backing_object.
1182: *
1183: * Since the backing object has no pages, no
1184: * pager left, and no object references within it,
1185: * all that is necessary is to dispose of it.
1186: */
1187:
1188: vm_object_unlock(backing_object);
1189:
1190: simple_lock(&vm_object_list_lock);
1191: queue_remove(&vm_object_list, backing_object,
1192: vm_object_t, object_list);
1193: vm_object_count--;
1194: simple_unlock(&vm_object_list_lock);
1195:
1196: free((caddr_t)backing_object, M_VMOBJ);
1197:
1198: object_collapses++;
1199: }
1200: else {
1201: /*
1202: * If all of the pages in the backing object are
1203: * shadowed by the parent object, the parent
1204: * object no longer has to shadow the backing
1205: * object; it can shadow the next one in the
1206: * chain.
1207: *
1208: * The backing object must not be paged out - we'd
1209: * have to check all of the paged-out pages, as
1210: * well.
1211: */
1212:
1213: if (backing_object->pager != NULL) {
1214: vm_object_unlock(backing_object);
1215: return;
1216: }
1217:
1218: /*
1219: * Should have a check for a 'small' number
1220: * of pages here.
1221: */
1222:
1223: p = (vm_page_t) queue_first(&backing_object->memq);
1224: while (!queue_end(&backing_object->memq,
1225: (queue_entry_t) p)) {
1226:
1227: new_offset = (p->offset - backing_offset);
1228:
1229: /*
1230: * If the parent has a page here, or if
1231: * this page falls outside the parent,
1232: * keep going.
1233: *
1234: * Otherwise, the backing_object must be
1235: * left in the chain.
1236: */
1237:
1238: if (p->offset >= backing_offset &&
1239: new_offset <= size &&
1240: ((pp = vm_page_lookup(object, new_offset))
1241: == NULL ||
1242: pp->fake)) {
1243: /*
1244: * Page still needed.
1245: * Can't go any further.
1246: */
1247: vm_object_unlock(backing_object);
1248: return;
1249: }
1250: p = (vm_page_t) queue_next(&p->listq);
1251: }
1252:
1253: /*
1254: * Make the parent shadow the next object
1255: * in the chain. Deallocating backing_object
1256: * will not remove it, since its reference
1257: * count is at least 2.
1258: */
1259:
1260: vm_object_reference(object->shadow = backing_object->shadow);
1261: object->shadow_offset += backing_object->shadow_offset;
1262:
1263: /* Drop the reference count on backing_object.
1264: * Since its ref_count was at least 2, it
1265: * will not vanish; so we don't need to call
1266: * vm_object_deallocate.
1267: */
1268: backing_object->ref_count--;
1269: vm_object_unlock(backing_object);
1270:
1271: object_bypasses ++;
1272:
1273: }
1274:
1275: /*
1276: * Try again with this object's new backing object.
1277: */
1278: }
1279: }
1280:
1281: /*
1282: * vm_object_page_remove: [internal]
1283: *
1284: * Removes all physical pages in the specified
1285: * object range from the object's list of pages.
1286: *
1287: * The object must be locked.
1288: */
1289: void vm_object_page_remove(object, start, end)
1290: register vm_object_t object;
1291: register vm_offset_t start;
1292: register vm_offset_t end;
1293: {
1294: register vm_page_t p, next;
1295:
1296: if (object == NULL)
1297: return;
1298:
1299: p = (vm_page_t) queue_first(&object->memq);
1300: while (!queue_end(&object->memq, (queue_entry_t) p)) {
1301: next = (vm_page_t) queue_next(&p->listq);
1302: if ((start <= p->offset) && (p->offset < end)) {
1303: pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_NONE);
1304: vm_page_lock_queues();
1305: vm_page_free(p);
1306: vm_page_unlock_queues();
1307: }
1308: p = next;
1309: }
1310: }
1311:
1312: /*
1313: * Routine: vm_object_coalesce
1314: * Function: Coalesces two objects backing up adjoining
1315: * regions of memory into a single object.
1316: *
1317: * returns TRUE if objects were combined.
1318: *
1319: * NOTE: Only works at the moment if the second object is NULL -
1320: * if it's not, which object do we lock first?
1321: *
1322: * Parameters:
1323: * prev_object First object to coalesce
1324: * prev_offset Offset into prev_object
1325: * next_object Second object into coalesce
1326: * next_offset Offset into next_object
1327: *
1328: * prev_size Size of reference to prev_object
1329: * next_size Size of reference to next_object
1330: *
1331: * Conditions:
1332: * The object must *not* be locked.
1333: */
1334: boolean_t vm_object_coalesce(prev_object, next_object,
1335: prev_offset, next_offset,
1336: prev_size, next_size)
1337:
1338: register vm_object_t prev_object;
1339: vm_object_t next_object;
1340: vm_offset_t prev_offset, next_offset;
1341: vm_size_t prev_size, next_size;
1342: {
1343: vm_size_t newsize;
1344:
1345: #ifdef lint
1346: next_offset++;
1347: #endif lint
1348:
1349: if (next_object != NULL) {
1350: return(FALSE);
1351: }
1352:
1353: if (prev_object == NULL) {
1354: return(TRUE);
1355: }
1356:
1357: vm_object_lock(prev_object);
1358:
1359: /*
1360: * Try to collapse the object first
1361: */
1362: vm_object_collapse(prev_object);
1363:
1364: /*
1365: * Can't coalesce if:
1366: * . more than one reference
1367: * . paged out
1368: * . shadows another object
1369: * . has a copy elsewhere
1370: * (any of which mean that the pages not mapped to
1371: * prev_entry may be in use anyway)
1372: */
1373:
1374: if (prev_object->ref_count > 1 ||
1375: prev_object->pager != NULL ||
1376: prev_object->shadow != NULL ||
1377: prev_object->copy != NULL) {
1378: vm_object_unlock(prev_object);
1379: return(FALSE);
1380: }
1381:
1382: /*
1383: * Remove any pages that may still be in the object from
1384: * a previous deallocation.
1385: */
1386:
1387: vm_object_page_remove(prev_object,
1388: prev_offset + prev_size,
1389: prev_offset + prev_size + next_size);
1390:
1391: /*
1392: * Extend the object if necessary.
1393: */
1394: newsize = prev_offset + prev_size + next_size;
1395: if (newsize > prev_object->size)
1396: prev_object->size = newsize;
1397:
1398: vm_object_unlock(prev_object);
1399: return(TRUE);
1400: }
1401:
1402: /*
1403: * vm_object_print: [ debug ]
1404: */
1405: void vm_object_print(object, full)
1406: vm_object_t object;
1407: boolean_t full;
1408: {
1409: register vm_page_t p;
1410: extern indent;
1411:
1412: register int count;
1413:
1414: if (object == NULL)
1415: return;
1416:
1417: iprintf("Object 0x%x: size=0x%x, res=%d, ref=%d, ",
1418: (int) object, (int) object->size,
1419: object->resident_page_count, object->ref_count);
1420: printf("pager=0x%x+0x%x, shadow=(0x%x)+0x%x\n",
1421: (int) object->pager, (int) object->paging_offset,
1422: (int) object->shadow, (int) object->shadow_offset);
1423: printf("cache: next=0x%x, prev=0x%x\n",
1424: object->cached_list.next, object->cached_list.prev);
1425:
1426: if (!full)
1427: return;
1428:
1429: indent += 2;
1430: count = 0;
1431: p = (vm_page_t) queue_first(&object->memq);
1432: while (!queue_end(&object->memq, (queue_entry_t) p)) {
1433: if (count == 0)
1434: iprintf("memory:=");
1435: else if (count == 6) {
1436: printf("\n");
1437: iprintf(" ...");
1438: count = 0;
1439: } else
1440: printf(",");
1441: count++;
1442:
1443: printf("(off=0x%x,page=0x%x)", p->offset, VM_PAGE_TO_PHYS(p));
1444: p = (vm_page_t) queue_next(&p->listq);
1445: }
1446: if (count != 0)
1447: printf("\n");
1448: indent -= 2;
1449: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.