xref: /original-bsd/sys/vm/vm_pageout.c (revision a3087256)
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  * %sccs.include.redist.c%
9  *
10  *	@(#)vm_pageout.c	7.7 (Berkeley) 05/04/92
11  *
12  *
13  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
14  * All rights reserved.
15  *
16  * Authors: Avadis Tevanian, Jr., Michael Wayne Young
17  *
18  * Permission to use, copy, modify and distribute this software and
19  * its documentation is hereby granted, provided that both the copyright
20  * notice and this permission notice appear in all copies of the
21  * software, derivative works or modified versions, and any portions
22  * thereof, and that both notices appear in supporting documentation.
23  *
24  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
25  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
26  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
27  *
28  * Carnegie Mellon requests users of this software to return to
29  *
30  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
31  *  School of Computer Science
32  *  Carnegie Mellon University
33  *  Pittsburgh PA 15213-3890
34  *
35  * any improvements or extensions that they make and grant Carnegie the
36  * rights to redistribute these changes.
37  */
38 
39 /*
40  *	The proverbial page-out daemon.
41  */
42 
43 #include <sys/param.h>
44 
45 #include <vm/vm.h>
46 #include <vm/vm_page.h>
47 #include <vm/vm_pageout.h>
48 
49 int	vm_pages_needed;	/* Event on which pageout daemon sleeps */
50 
51 int	vm_page_free_min_sanity = 40;
52 
53 /*
54  *	vm_pageout_scan does the dirty work for the pageout daemon.
55  */
56 void
57 vm_pageout_scan()
58 {
59 	register vm_page_t	m;
60 	register int		page_shortage;
61 	register int		s;
62 	register int		pages_freed;
63 	int			free;
64 
65 	/*
66 	 *	Only continue when we want more pages to be "free"
67 	 */
68 
69 	s = splimp();
70 	simple_lock(&vm_page_queue_free_lock);
71 	free = cnt.v_free_count;
72 	simple_unlock(&vm_page_queue_free_lock);
73 	splx(s);
74 
75 	if (free < cnt.v_free_target) {
76 		swapout_threads();
77 
78 		/*
79 		 *	Be sure the pmap system is updated so
80 		 *	we can scan the inactive queue.
81 		 */
82 
83 		pmap_update();
84 	}
85 
86 	/*
87 	 *	Acquire the resident page system lock,
88 	 *	as we may be changing what's resident quite a bit.
89 	 */
90 	vm_page_lock_queues();
91 
92 	/*
93 	 *	Start scanning the inactive queue for pages we can free.
94 	 *	We keep scanning until we have enough free pages or
95 	 *	we have scanned through the entire queue.  If we
96 	 *	encounter dirty pages, we start cleaning them.
97 	 */
98 
99 	pages_freed = 0;
100 	m = (vm_page_t) queue_first(&vm_page_queue_inactive);
101 	while (!queue_end(&vm_page_queue_inactive, (queue_entry_t) m)) {
102 		vm_page_t	next;
103 
104 		s = splimp();
105 		simple_lock(&vm_page_queue_free_lock);
106 		free = cnt.v_free_count;
107 		simple_unlock(&vm_page_queue_free_lock);
108 		splx(s);
109 
110 		if (free >= cnt.v_free_target)
111 			break;
112 
113 		if (m->clean) {
114 			next = (vm_page_t) queue_next(&m->pageq);
115 			if (pmap_is_referenced(VM_PAGE_TO_PHYS(m))) {
116 				vm_page_activate(m);
117 				cnt.v_reactivated++;
118 			}
119 			else {
120 				register vm_object_t	object;
121 				object = m->object;
122 				if (!vm_object_lock_try(object)) {
123 					/*
124 					 *	Can't lock object -
125 					 *	skip page.
126 					 */
127 					m = next;
128 					continue;
129 				}
130 				pmap_page_protect(VM_PAGE_TO_PHYS(m),
131 						  VM_PROT_NONE);
132 				vm_page_free(m);	/* will dequeue */
133 				pages_freed++;
134 				vm_object_unlock(object);
135 			}
136 			m = next;
137 		}
138 		else {
139 			/*
140 			 *	If a page is dirty, then it is either
141 			 *	being washed (but not yet cleaned)
142 			 *	or it is still in the laundry.  If it is
143 			 *	still in the laundry, then we start the
144 			 *	cleaning operation.
145 			 */
146 
147 			if (m->laundry) {
148 				/*
149 				 *	Clean the page and remove it from the
150 				 *	laundry.
151 				 *
152 				 *	We set the busy bit to cause
153 				 *	potential page faults on this page to
154 				 *	block.
155 				 *
156 				 *	And we set pageout-in-progress to keep
157 				 *	the object from disappearing during
158 				 *	pageout.  This guarantees that the
159 				 *	page won't move from the inactive
160 				 *	queue.  (However, any other page on
161 				 *	the inactive queue may move!)
162 				 */
163 
164 				register vm_object_t	object;
165 				register vm_pager_t	pager;
166 				int			pageout_status;
167 
168 				object = m->object;
169 				if (!vm_object_lock_try(object)) {
170 					/*
171 					 *	Skip page if we can't lock
172 					 *	its object
173 					 */
174 					m = (vm_page_t) queue_next(&m->pageq);
175 					continue;
176 				}
177 
178 				pmap_page_protect(VM_PAGE_TO_PHYS(m),
179 						  VM_PROT_NONE);
180 				m->busy = TRUE;
181 				cnt.v_pageouts++;
182 
183 				/*
184 				 *	Try to collapse the object before
185 				 *	making a pager for it.  We must
186 				 *	unlock the page queues first.
187 				 */
188 				vm_page_unlock_queues();
189 
190 				vm_object_collapse(object);
191 
192 				object->paging_in_progress++;
193 				vm_object_unlock(object);
194 
195 				/*
196 				 *	Do a wakeup here in case the following
197 				 *	operations block.
198 				 */
199 				thread_wakeup((int) &cnt.v_free_count);
200 
201 				/*
202 				 *	If there is no pager for the page,
203 				 *	use the default pager.  If there's
204 				 *	no place to put the page at the
205 				 *	moment, leave it in the laundry and
206 				 *	hope that there will be paging space
207 				 *	later.
208 				 */
209 
210 				if ((pager = object->pager) == NULL) {
211 					pager = vm_pager_allocate(PG_DFLT,
212 								  (caddr_t)0,
213 								  object->size,
214 								  VM_PROT_ALL);
215 					if (pager != NULL) {
216 						vm_object_setpager(object,
217 							pager, 0, FALSE);
218 					}
219 				}
220 				pageout_status = pager ?
221 					vm_pager_put(pager, m, FALSE) :
222 					VM_PAGER_FAIL;
223 				vm_object_lock(object);
224 				vm_page_lock_queues();
225 				next = (vm_page_t) queue_next(&m->pageq);
226 
227 				switch (pageout_status) {
228 				case VM_PAGER_OK:
229 				case VM_PAGER_PEND:
230 					m->laundry = FALSE;
231 					break;
232 				case VM_PAGER_BAD:
233 					/*
234 					 * Page outside of range of object.
235 					 * Right now we essentially lose the
236 					 * changes by pretending it worked.
237 					 * XXX dubious, what should we do?
238 					 */
239 					m->laundry = FALSE;
240 					m->clean = TRUE;
241 					pmap_clear_modify(VM_PAGE_TO_PHYS(m));
242 					break;
243 				case VM_PAGER_FAIL:
244 					/*
245 					 * If page couldn't be paged out, then
246 					 * reactivate the page so it doesn't
247 					 * clog the inactive list.  (We will
248 					 * try paging out it again later).
249 					 */
250 					vm_page_activate(m);
251 					break;
252 				}
253 
254 				pmap_clear_reference(VM_PAGE_TO_PHYS(m));
255 
256 				/*
257 				 * If the operation is still going, leave
258 				 * the page busy to block all other accesses.
259 				 * Also, leave the paging in progress
260 				 * indicator set so that we don't attempt an
261 				 * object collapse.
262 				 */
263 				if (pageout_status != VM_PAGER_PEND) {
264 					m->busy = FALSE;
265 					PAGE_WAKEUP(m);
266 					object->paging_in_progress--;
267 				}
268 				thread_wakeup((int) object);
269 				vm_object_unlock(object);
270 				m = next;
271 			}
272 			else
273 				m = (vm_page_t) queue_next(&m->pageq);
274 		}
275 	}
276 
277 	/*
278 	 *	Compute the page shortage.  If we are still very low on memory
279 	 *	be sure that we will move a minimal amount of pages from active
280 	 *	to inactive.
281 	 */
282 
283 	page_shortage = cnt.v_inactive_target - cnt.v_inactive_count;
284 	page_shortage -= cnt.v_free_count;
285 
286 	if ((page_shortage <= 0) && (pages_freed == 0))
287 		page_shortage = 1;
288 
289 	while (page_shortage > 0) {
290 		/*
291 		 *	Move some more pages from active to inactive.
292 		 */
293 
294 		if (queue_empty(&vm_page_queue_active)) {
295 			break;
296 		}
297 		m = (vm_page_t) queue_first(&vm_page_queue_active);
298 		vm_page_deactivate(m);
299 		page_shortage--;
300 	}
301 
302 	vm_page_unlock_queues();
303 }
304 
305 /*
306  *	vm_pageout is the high level pageout daemon.
307  */
308 
309 void vm_pageout()
310 {
311 	(void) spl0();
312 
313 	/*
314 	 *	Initialize some paging parameters.
315 	 */
316 
317 	if (cnt.v_free_min == 0) {
318 		cnt.v_free_min = cnt.v_free_count / 20;
319 		if (cnt.v_free_min < 3)
320 			cnt.v_free_min = 3;
321 
322 		if (cnt.v_free_min > vm_page_free_min_sanity)
323 			cnt.v_free_min = vm_page_free_min_sanity;
324 	}
325 
326 	if (cnt.v_free_target == 0)
327 		cnt.v_free_target = (cnt.v_free_min * 4) / 3;
328 
329 	if (cnt.v_inactive_target == 0)
330 		cnt.v_inactive_target = cnt.v_free_min * 2;
331 
332 	if (cnt.v_free_target <= cnt.v_free_min)
333 		cnt.v_free_target = cnt.v_free_min + 1;
334 
335 	if (cnt.v_inactive_target <= cnt.v_free_target)
336 		cnt.v_inactive_target = cnt.v_free_target + 1;
337 
338 	/*
339 	 *	The pageout daemon is never done, so loop
340 	 *	forever.
341 	 */
342 
343 	simple_lock(&vm_pages_needed_lock);
344 	while (TRUE) {
345 		thread_sleep((int) &vm_pages_needed, &vm_pages_needed_lock,
346 			     FALSE);
347 		vm_pageout_scan();
348 		vm_pager_sync();
349 		simple_lock(&vm_pages_needed_lock);
350 		thread_wakeup((int) &cnt.v_free_count);
351 	}
352 }
353