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