|
|
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_pageout.c 7.4 (Berkeley) 5/7/91
! 37: * vm_pageout.c,v 1.4 1993/05/20 03:59:40 cgd 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: * The proverbial page-out daemon.
68: */
69:
70: #include "param.h"
71:
72: #include "vm.h"
73: #include "vm_page.h"
74: #include "vm_pageout.h"
1.1.1.3 ! root 75: #include "vmmeter.h"
1.1 root 76:
77: int vm_pages_needed; /* Event on which pageout daemon sleeps */
78: int vm_pageout_free_min = 0; /* Stop pageout to wait for pagers at this free level */
79:
80: int vm_page_free_min_sanity = 40;
81:
1.1.1.3 ! root 82: int vm_page_pagesfreed; /* Pages freed by page daemon */
! 83:
1.1 root 84: /*
85: * vm_pageout_scan does the dirty work for the pageout daemon.
86: */
87: vm_pageout_scan()
88: {
89: register vm_page_t m;
90: register int page_shortage;
91: register int s;
92: register int pages_freed;
93: int free;
94:
95: /*
96: * Only continue when we want more pages to be "free"
97: */
98:
99: s = splimp();
100: simple_lock(&vm_page_queue_free_lock);
101: free = vm_page_free_count;
102: simple_unlock(&vm_page_queue_free_lock);
103: splx(s);
104:
105: if (free < vm_page_free_target) {
1.1.1.2 root 106: #ifdef OMIT
1.1 root 107: swapout_threads();
1.1.1.2 root 108: #endif /* OMIT*/
1.1 root 109:
110: /*
111: * Be sure the pmap system is updated so
112: * we can scan the inactive queue.
113: */
114:
115: pmap_update();
116: }
117:
118: /*
119: * Acquire the resident page system lock,
120: * as we may be changing what's resident quite a bit.
121: */
122: vm_page_lock_queues();
123:
124: /*
125: * Start scanning the inactive queue for pages we can free.
126: * We keep scanning until we have enough free pages or
127: * we have scanned through the entire queue. If we
128: * encounter dirty pages, we start cleaning them.
129: */
130:
131: pages_freed = 0;
132: m = (vm_page_t) queue_first(&vm_page_queue_inactive);
133: while (!queue_end(&vm_page_queue_inactive, (queue_entry_t) m)) {
134: vm_page_t next;
135:
136: s = splimp();
137: simple_lock(&vm_page_queue_free_lock);
138: free = vm_page_free_count;
139: simple_unlock(&vm_page_queue_free_lock);
140: splx(s);
141:
142: if (free >= vm_page_free_target)
143: break;
144:
145: if (m->clean) {
146: next = (vm_page_t) queue_next(&m->pageq);
147: if (pmap_is_referenced(VM_PAGE_TO_PHYS(m))) {
148: vm_page_activate(m);
149: vm_stat.reactivations++;
150: }
151: else {
152: register vm_object_t object;
153: object = m->object;
154: if (!vm_object_lock_try(object)) {
155: /*
156: * Can't lock object -
157: * skip page.
158: */
159: m = next;
160: continue;
161: }
162: pmap_page_protect(VM_PAGE_TO_PHYS(m),
163: VM_PROT_NONE);
164: vm_page_free(m); /* will dequeue */
165: pages_freed++;
166: vm_object_unlock(object);
167: }
168: m = next;
169: }
170: else {
171: /*
172: * If a page is dirty, then it is either
173: * being washed (but not yet cleaned)
174: * or it is still in the laundry. If it is
175: * still in the laundry, then we start the
176: * cleaning operation.
177: */
178:
179: if (m->laundry) {
180: /*
181: * Clean the page and remove it from the
182: * laundry.
183: *
184: * We set the busy bit to cause
185: * potential page faults on this page to
186: * block.
187: *
188: * And we set pageout-in-progress to keep
189: * the object from disappearing during
190: * pageout. This guarantees that the
191: * page won't move from the inactive
192: * queue. (However, any other page on
193: * the inactive queue may move!)
194: */
195:
196: register vm_object_t object;
197: register vm_pager_t pager;
198: int pageout_status;
199:
200: object = m->object;
201: if (!vm_object_lock_try(object)) {
202: /*
203: * Skip page if we can't lock
204: * its object
205: */
206: m = (vm_page_t) queue_next(&m->pageq);
207: continue;
208: }
209:
210: pmap_page_protect(VM_PAGE_TO_PHYS(m),
211: VM_PROT_NONE);
212: m->busy = TRUE;
213: vm_stat.pageouts++;
214:
215: /*
216: * Try to collapse the object before
217: * making a pager for it. We must
218: * unlock the page queues first.
219: */
220: vm_page_unlock_queues();
221:
222: vm_object_collapse(object);
223:
224: object->paging_in_progress++;
225: vm_object_unlock(object);
226:
227: /*
228: * Do a wakeup here in case the following
229: * operations block.
230: */
231: thread_wakeup((int) &vm_page_free_count);
232:
233: /*
234: * If there is no pager for the page,
235: * use the default pager. If there's
236: * no place to put the page at the
237: * moment, leave it in the laundry and
238: * hope that there will be paging space
239: * later.
240: */
241:
242: if ((pager = object->pager) == NULL) {
243: pager = vm_pager_allocate(PG_DFLT,
244: (caddr_t)0,
245: object->size,
246: VM_PROT_ALL);
247: if (pager != NULL) {
248: vm_object_setpager(object,
249: pager, 0, FALSE);
250: }
251: }
252: pageout_status = pager ?
253: vm_pager_put(pager, m, FALSE) :
254: VM_PAGER_FAIL;
255: vm_object_lock(object);
256: vm_page_lock_queues();
257: next = (vm_page_t) queue_next(&m->pageq);
258:
259: switch (pageout_status) {
260: case VM_PAGER_OK:
261: case VM_PAGER_PEND:
262: m->laundry = FALSE;
263: break;
264: case VM_PAGER_BAD:
265: /*
266: * Page outside of range of object.
267: * Right now we essentially lose the
268: * changes by pretending it worked.
269: * XXX dubious, what should we do?
270: */
271: m->laundry = FALSE;
272: m->clean = TRUE;
273: pmap_clear_modify(VM_PAGE_TO_PHYS(m));
274: break;
275: case VM_PAGER_FAIL:
276: /*
277: * If page couldn't be paged out, then
278: * reactivate the page so it doesn't
279: * clog the inactive list. (We will
280: * try paging out it again later).
281: */
282: vm_page_activate(m);
283: break;
284: }
285:
286: pmap_clear_reference(VM_PAGE_TO_PHYS(m));
287:
288: /*
289: * If the operation is still going, leave
290: * the page busy to block all other accesses.
291: * Also, leave the paging in progress
292: * indicator set so that we don't attempt an
293: * object collapse.
294: */
295: if (pageout_status != VM_PAGER_PEND) {
296: m->busy = FALSE;
297: PAGE_WAKEUP(m);
298: object->paging_in_progress--;
299: }
300: thread_wakeup((int) object);
301: vm_object_unlock(object);
302: m = next;
303: }
304: else
305: m = (vm_page_t) queue_next(&m->pageq);
306: }
307: }
308:
309: /*
310: * Compute the page shortage. If we are still very low on memory
311: * be sure that we will move a minimal amount of pages from active
312: * to inactive.
313: */
314:
315: page_shortage = vm_page_inactive_target - vm_page_inactive_count;
316: page_shortage -= vm_page_free_count;
317:
318: if ((page_shortage <= 0) && (pages_freed == 0))
319: page_shortage = 1;
320:
321: while (page_shortage > 0) {
322: /*
323: * Move some more pages from active to inactive.
324: */
325:
326: if (queue_empty(&vm_page_queue_active)) {
327: break;
328: }
329: m = (vm_page_t) queue_first(&vm_page_queue_active);
330: vm_page_deactivate(m);
331: page_shortage--;
332: }
333:
1.1.1.3 ! root 334: vm_page_pagesfreed += pages_freed;
1.1 root 335: vm_page_unlock_queues();
336: }
337:
338: /*
339: * vm_pageout is the high level pageout daemon.
340: */
341:
342: void vm_pageout()
343: {
344: (void) spl0();
345:
346: /*
347: * Initialize some paging parameters.
348: */
349:
350: if (vm_page_free_min == 0) {
351: vm_page_free_min = vm_page_free_count / 20;
352: if (vm_page_free_min < 3)
353: vm_page_free_min = 3;
354:
355: if (vm_page_free_min > vm_page_free_min_sanity)
356: vm_page_free_min = vm_page_free_min_sanity;
357: }
358:
359: if (vm_page_free_reserved == 0) {
360: if ((vm_page_free_reserved = vm_page_free_min / 2) < 10)
361: vm_page_free_reserved = 10;
362: }
363: if (vm_pageout_free_min == 0) {
364: if ((vm_pageout_free_min = vm_page_free_reserved / 2) > 10)
365: vm_pageout_free_min = 10;
366: }
367:
368: if (vm_page_free_target == 0)
369: vm_page_free_target = (vm_page_free_min * 4) / 3;
370:
371: if (vm_page_inactive_target == 0)
372: vm_page_inactive_target = vm_page_free_min * 2;
373:
374: if (vm_page_free_target <= vm_page_free_min)
375: vm_page_free_target = vm_page_free_min + 1;
376:
377: if (vm_page_inactive_target <= vm_page_free_target)
378: vm_page_inactive_target = vm_page_free_target + 1;
379:
380: /*
381: * The pageout daemon is never done, so loop
382: * forever.
383: */
384:
385: simple_lock(&vm_pages_needed_lock);
386: while (TRUE) {
387: thread_sleep((int) &vm_pages_needed, &vm_pages_needed_lock,
388: FALSE);
1.1.1.3 ! root 389: cnt.v_scan++;
1.1 root 390: vm_pageout_scan();
391: vm_pager_sync();
392: simple_lock(&vm_pages_needed_lock);
393: thread_wakeup((int) &vm_page_free_count);
394: }
395: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.