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