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.11 (Berkeley) 06/02/93 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 int vm_page_max_wired = 0; /* XXX max # of wired pages system-wide */ 54 55 /* 56 * vm_pageout_scan does the dirty work for the pageout daemon. 57 */ 58 void 59 vm_pageout_scan() 60 { 61 register vm_page_t m; 62 register int page_shortage; 63 register int s; 64 register int pages_freed; 65 int free; 66 67 /* 68 * Only continue when we want more pages to be "free" 69 */ 70 71 s = splimp(); 72 simple_lock(&vm_page_queue_free_lock); 73 free = cnt.v_free_count; 74 simple_unlock(&vm_page_queue_free_lock); 75 splx(s); 76 77 if (free < cnt.v_free_target) { 78 swapout_threads(); 79 80 /* 81 * Be sure the pmap system is updated so 82 * we can scan the inactive queue. 83 */ 84 85 pmap_update(); 86 } 87 88 /* 89 * Acquire the resident page system lock, 90 * as we may be changing what's resident quite a bit. 91 */ 92 vm_page_lock_queues(); 93 94 /* 95 * Start scanning the inactive queue for pages we can free. 96 * We keep scanning until we have enough free pages or 97 * we have scanned through the entire queue. If we 98 * encounter dirty pages, we start cleaning them. 99 */ 100 101 pages_freed = 0; 102 m = (vm_page_t) queue_first(&vm_page_queue_inactive); 103 while (!queue_end(&vm_page_queue_inactive, (queue_entry_t) m)) { 104 vm_page_t next; 105 vm_object_t object; 106 vm_pager_t pager; 107 int pageout_status; 108 109 s = splimp(); 110 simple_lock(&vm_page_queue_free_lock); 111 free = cnt.v_free_count; 112 simple_unlock(&vm_page_queue_free_lock); 113 splx(s); 114 115 if (free >= cnt.v_free_target) 116 break; 117 118 /* 119 * If the page has been referenced, move it back to the 120 * active queue. 121 */ 122 if (pmap_is_referenced(VM_PAGE_TO_PHYS(m))) { 123 next = (vm_page_t) queue_next(&m->pageq); 124 vm_page_activate(m); 125 cnt.v_reactivated++; 126 m = next; 127 continue; 128 } 129 130 /* 131 * If the page is clean, free it up. 132 */ 133 if (m->flags & PG_CLEAN) { 134 next = (vm_page_t) queue_next(&m->pageq); 135 object = m->object; 136 if (vm_object_lock_try(object)) { 137 pmap_page_protect(VM_PAGE_TO_PHYS(m), 138 VM_PROT_NONE); 139 vm_page_free(m); 140 pages_freed++; 141 vm_object_unlock(object); 142 } 143 m = next; 144 continue; 145 } 146 147 /* 148 * If the page is dirty but already being washed, skip it. 149 */ 150 if ((m->flags & PG_LAUNDRY) == 0) { 151 m = (vm_page_t) queue_next(&m->pageq); 152 continue; 153 } 154 155 /* 156 * Otherwise the page is dirty and still in the laundry, 157 * so we start the cleaning operation and remove it from 158 * the laundry. 159 * 160 * We set the busy bit to cause potential page faults on 161 * this page to block. 162 * 163 * We also set pageout-in-progress to keep the object from 164 * disappearing during pageout. This guarantees that the 165 * page won't move from the inactive queue. (However, any 166 * other page on the inactive queue may move!) 167 */ 168 object = m->object; 169 if (!vm_object_lock_try(object)) { 170 m = (vm_page_t) queue_next(&m->pageq); 171 continue; 172 } 173 pmap_page_protect(VM_PAGE_TO_PHYS(m), VM_PROT_NONE); 174 m->flags |= PG_BUSY; 175 cnt.v_pageouts++; 176 177 /* 178 * Try to collapse the object before making a pager for it. 179 * We must unlock the page queues first. 180 */ 181 vm_page_unlock_queues(); 182 vm_object_collapse(object); 183 184 object->paging_in_progress++; 185 vm_object_unlock(object); 186 187 /* 188 * Do a wakeup here in case the following operations block. 189 */ 190 thread_wakeup((int) &cnt.v_free_count); 191 192 /* 193 * If there is no pager for the page, use the default pager. 194 * If there is no place to put the page at the moment, 195 * leave it in the laundry and hope that there will be 196 * paging space later. 197 */ 198 if ((pager = object->pager) == NULL) { 199 pager = vm_pager_allocate(PG_DFLT, (caddr_t)0, 200 object->size, VM_PROT_ALL); 201 if (pager != NULL) 202 vm_object_setpager(object, pager, 0, FALSE); 203 } 204 pageout_status = pager ? 205 vm_pager_put(pager, m, FALSE) : VM_PAGER_FAIL; 206 vm_object_lock(object); 207 vm_page_lock_queues(); 208 next = (vm_page_t) queue_next(&m->pageq); 209 210 switch (pageout_status) { 211 case VM_PAGER_OK: 212 case VM_PAGER_PEND: 213 m->flags &= ~PG_LAUNDRY; 214 break; 215 case VM_PAGER_BAD: 216 /* 217 * Page outside of range of object. Right now we 218 * essentially lose the changes by pretending it 219 * worked. 220 * 221 * XXX dubious, what should we do? 222 */ 223 m->flags &= ~PG_LAUNDRY; 224 m->flags |= PG_CLEAN; 225 pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 226 break; 227 case VM_PAGER_FAIL: 228 case VM_PAGER_ERROR: 229 /* 230 * If page couldn't be paged out, then reactivate 231 * the page so it doesn't clog the inactive list. 232 * (We will try paging out it again later). 233 */ 234 vm_page_activate(m); 235 break; 236 } 237 238 pmap_clear_reference(VM_PAGE_TO_PHYS(m)); 239 240 /* 241 * If the operation is still going, leave the page busy 242 * to block all other accesses. Also, leave the paging 243 * in progress indicator set so that we don't attempt an 244 * object collapse. 245 */ 246 if (pageout_status != VM_PAGER_PEND) { 247 m->flags &= ~PG_BUSY; 248 PAGE_WAKEUP(m); 249 object->paging_in_progress--; 250 } 251 thread_wakeup((int) object); 252 vm_object_unlock(object); 253 m = next; 254 } 255 256 /* 257 * Compute the page shortage. If we are still very low on memory 258 * be sure that we will move a minimal amount of pages from active 259 * to inactive. 260 */ 261 262 page_shortage = cnt.v_inactive_target - cnt.v_inactive_count; 263 if (page_shortage <= 0 && pages_freed == 0) 264 page_shortage = 1; 265 266 while (page_shortage > 0) { 267 /* 268 * Move some more pages from active to inactive. 269 */ 270 271 if (queue_empty(&vm_page_queue_active)) { 272 break; 273 } 274 m = (vm_page_t) queue_first(&vm_page_queue_active); 275 vm_page_deactivate(m); 276 page_shortage--; 277 } 278 279 vm_page_unlock_queues(); 280 } 281 282 /* 283 * vm_pageout is the high level pageout daemon. 284 */ 285 286 void vm_pageout() 287 { 288 (void) spl0(); 289 290 /* 291 * Initialize some paging parameters. 292 */ 293 294 if (cnt.v_free_min == 0) { 295 cnt.v_free_min = cnt.v_free_count / 20; 296 if (cnt.v_free_min < 3) 297 cnt.v_free_min = 3; 298 299 if (cnt.v_free_min > vm_page_free_min_sanity) 300 cnt.v_free_min = vm_page_free_min_sanity; 301 } 302 303 if (cnt.v_free_target == 0) 304 cnt.v_free_target = (cnt.v_free_min * 4) / 3; 305 306 if (cnt.v_free_target <= cnt.v_free_min) 307 cnt.v_free_target = cnt.v_free_min + 1; 308 309 /* XXX does not really belong here */ 310 if (vm_page_max_wired == 0) 311 vm_page_max_wired = cnt.v_free_count / 3; 312 313 /* 314 * The pageout daemon is never done, so loop 315 * forever. 316 */ 317 318 simple_lock(&vm_pages_needed_lock); 319 while (TRUE) { 320 thread_sleep((int) &vm_pages_needed, &vm_pages_needed_lock, 321 FALSE); 322 /* 323 * Compute the inactive target for this scan. 324 * We need to keep a reasonable amount of memory in the 325 * inactive list to better simulate LRU behavior. 326 */ 327 cnt.v_inactive_target = 328 (cnt.v_active_count + cnt.v_inactive_count) / 3; 329 if (cnt.v_inactive_target <= cnt.v_free_target) 330 cnt.v_inactive_target = cnt.v_free_target + 1; 331 332 vm_pageout_scan(); 333 vm_pager_sync(); 334 simple_lock(&vm_pages_needed_lock); 335 thread_wakeup((int) &cnt.v_free_count); 336 } 337 } 338