vm_pager.c (5202) | vm_pager.c (5455) |
---|---|
1/* | 1/* |
2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. 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 --- 25 unchanged lines hidden (view full) --- 35 * 36 * from: @(#)vm_pager.c 8.6 (Berkeley) 1/12/94 37 * 38 * 39 * Copyright (c) 1987, 1990 Carnegie-Mellon University. 40 * All rights reserved. 41 * 42 * Authors: Avadis Tevanian, Jr., Michael Wayne Young | 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. 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 --- 25 unchanged lines hidden (view full) --- 35 * 36 * from: @(#)vm_pager.c 8.6 (Berkeley) 1/12/94 37 * 38 * 39 * Copyright (c) 1987, 1990 Carnegie-Mellon University. 40 * All rights reserved. 41 * 42 * Authors: Avadis Tevanian, Jr., Michael Wayne Young |
43 * | 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. | 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 | 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. | 52 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. |
53 * | 53 * |
54 * Carnegie Mellon requests users of this software to return to 55 * 56 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 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 * | 54 * Carnegie Mellon requests users of this software to return to 55 * 56 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 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 * $Id: vm_pager.c,v 1.9 1994/12/19 00:02:56 davidg Exp $ | 64 * $Id: vm_pager.c,v 1.10 1994/12/23 04:56:51 davidg Exp $ |
65 */ 66 67/* 68 * Paging space routine stubs. Emulates a matchmaker-like interface 69 * for builtin pagers. 70 */ 71 72#include <sys/param.h> --- 11 unchanged lines hidden (view full) --- 84extern struct pagerops vnodepagerops; 85extern struct pagerops devicepagerops; 86 87struct pagerops *pagertab[] = { 88 &swappagerops, /* PG_SWAP */ 89 &vnodepagerops, /* PG_VNODE */ 90 &devicepagerops, /* PG_DEV */ 91}; | 65 */ 66 67/* 68 * Paging space routine stubs. Emulates a matchmaker-like interface 69 * for builtin pagers. 70 */ 71 72#include <sys/param.h> --- 11 unchanged lines hidden (view full) --- 84extern struct pagerops vnodepagerops; 85extern struct pagerops devicepagerops; 86 87struct pagerops *pagertab[] = { 88 &swappagerops, /* PG_SWAP */ 89 &vnodepagerops, /* PG_VNODE */ 90 &devicepagerops, /* PG_DEV */ 91}; |
92int npagers = sizeof (pagertab) / sizeof (pagertab[0]); | 92int npagers = sizeof(pagertab) / sizeof(pagertab[0]); |
93 94struct pagerops *dfltpagerops = NULL; /* default pager */ 95 96/* 97 * Kernel address space for mapping pages. 98 * Used by pagers where KVAs are needed for IO. 99 * 100 * XXX needs to be large enough to support the number of pending async --- 14 unchanged lines hidden (view full) --- 115{ 116 struct pagerops **pgops; 117 118 /* 119 * Initialize known pagers 120 */ 121 for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++) 122 if (pgops) | 93 94struct pagerops *dfltpagerops = NULL; /* default pager */ 95 96/* 97 * Kernel address space for mapping pages. 98 * Used by pagers where KVAs are needed for IO. 99 * 100 * XXX needs to be large enough to support the number of pending async --- 14 unchanged lines hidden (view full) --- 115{ 116 struct pagerops **pgops; 117 118 /* 119 * Initialize known pagers 120 */ 121 for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++) 122 if (pgops) |
123 (*(*pgops)->pgo_init)(); | 123 (*(*pgops)->pgo_init) (); |
124 if (dfltpagerops == NULL) 125 panic("no default pager"); 126} 127 128void 129vm_pager_bufferinit() 130{ 131 struct buf *bp; 132 int i; | 124 if (dfltpagerops == NULL) 125 panic("no default pager"); 126} 127 128void 129vm_pager_bufferinit() 130{ 131 struct buf *bp; 132 int i; |
133 |
|
133 bp = swbuf; 134 /* 135 * Now set up swap and physical I/O buffer headers. 136 */ 137 for (i = 0; i < nswbuf - 1; i++, bp++) { 138 TAILQ_INSERT_HEAD(&bswlist, bp, b_freelist); 139 bp->b_rcred = bp->b_wcred = NOCRED; 140 bp->b_vnbufs.le_next = NOLIST; 141 } 142 bp->b_rcred = bp->b_wcred = NOCRED; 143 bp->b_vnbufs.le_next = NOLIST; 144 bp->b_actf = NULL; 145 | 134 bp = swbuf; 135 /* 136 * Now set up swap and physical I/O buffer headers. 137 */ 138 for (i = 0; i < nswbuf - 1; i++, bp++) { 139 TAILQ_INSERT_HEAD(&bswlist, bp, b_freelist); 140 bp->b_rcred = bp->b_wcred = NOCRED; 141 bp->b_vnbufs.le_next = NOLIST; 142 } 143 bp->b_rcred = bp->b_wcred = NOCRED; 144 bp->b_vnbufs.le_next = NOLIST; 145 bp->b_actf = NULL; 146 |
146 swapbkva = kmem_alloc_pageable( pager_map, nswbuf * MAXPHYS); 147 if( !swapbkva) | 147 swapbkva = kmem_alloc_pageable(pager_map, nswbuf * MAXPHYS); 148 if (!swapbkva) |
148 panic("Not enough pager_map VM space for physical buffers"); 149} 150 151/* 152 * Allocate an instance of a pager of the given type. 153 * Size, protection and offset parameters are passed in for pagers that 154 * need to perform page-level validation (e.g. the device pager). 155 */ --- 4 unchanged lines hidden (view full) --- 160 vm_size_t size; 161 vm_prot_t prot; 162 vm_offset_t off; 163{ 164 struct pagerops *ops; 165 166 ops = (type == PG_DFLT) ? dfltpagerops : pagertab[type]; 167 if (ops) | 149 panic("Not enough pager_map VM space for physical buffers"); 150} 151 152/* 153 * Allocate an instance of a pager of the given type. 154 * Size, protection and offset parameters are passed in for pagers that 155 * need to perform page-level validation (e.g. the device pager). 156 */ --- 4 unchanged lines hidden (view full) --- 161 vm_size_t size; 162 vm_prot_t prot; 163 vm_offset_t off; 164{ 165 struct pagerops *ops; 166 167 ops = (type == PG_DFLT) ? dfltpagerops : pagertab[type]; 168 if (ops) |
168 return ((*ops->pgo_alloc)(handle, size, prot, off)); | 169 return ((*ops->pgo_alloc) (handle, size, prot, off)); |
169 return (NULL); 170} 171 172void 173vm_pager_deallocate(pager) | 170 return (NULL); 171} 172 173void 174vm_pager_deallocate(pager) |
174 vm_pager_t pager; | 175 vm_pager_t pager; |
175{ 176 if (pager == NULL) 177 panic("vm_pager_deallocate: null pager"); 178 | 176{ 177 if (pager == NULL) 178 panic("vm_pager_deallocate: null pager"); 179 |
179 (*pager->pg_ops->pgo_dealloc)(pager); | 180 (*pager->pg_ops->pgo_dealloc) (pager); |
180} 181 182 183int 184vm_pager_get_pages(pager, m, count, reqpage, sync) | 181} 182 183 184int 185vm_pager_get_pages(pager, m, count, reqpage, sync) |
185 vm_pager_t pager; 186 vm_page_t *m; 187 int count; 188 int reqpage; 189 boolean_t sync; | 186 vm_pager_t pager; 187 vm_page_t *m; 188 int count; 189 int reqpage; 190 boolean_t sync; |
190{ 191 int i; 192 193 if (pager == NULL) { | 191{ 192 int i; 193 194 if (pager == NULL) { |
194 for (i=0;i<count;i++) { 195 if( i != reqpage) { | 195 for (i = 0; i < count; i++) { 196 if (i != reqpage) { |
196 PAGE_WAKEUP(m[i]); 197 vm_page_free(m[i]); 198 } 199 } 200 vm_page_zero_fill(m[reqpage]); 201 return VM_PAGER_OK; 202 } | 197 PAGE_WAKEUP(m[i]); 198 vm_page_free(m[i]); 199 } 200 } 201 vm_page_zero_fill(m[reqpage]); 202 return VM_PAGER_OK; 203 } |
203 204 if( pager->pg_ops->pgo_getpages == 0) { 205 for(i=0;i<count;i++) { 206 if( i != reqpage) { | 204 if (pager->pg_ops->pgo_getpages == 0) { 205 for (i = 0; i < count; i++) { 206 if (i != reqpage) { |
207 PAGE_WAKEUP(m[i]); 208 vm_page_free(m[i]); 209 } 210 } | 207 PAGE_WAKEUP(m[i]); 208 vm_page_free(m[i]); 209 } 210 } |
211 return(VM_PAGER_GET(pager, m[reqpage], sync)); | 211 return (VM_PAGER_GET(pager, m[reqpage], sync)); |
212 } else { | 212 } else { |
213 return(VM_PAGER_GET_MULTI(pager, m, count, reqpage, sync)); | 213 return (VM_PAGER_GET_MULTI(pager, m, count, reqpage, sync)); |
214 } 215} 216 217int 218vm_pager_put_pages(pager, m, count, sync, rtvals) | 214 } 215} 216 217int 218vm_pager_put_pages(pager, m, count, sync, rtvals) |
219 vm_pager_t pager; 220 vm_page_t *m; 221 int count; 222 boolean_t sync; 223 int *rtvals; | 219 vm_pager_t pager; 220 vm_page_t *m; 221 int count; 222 boolean_t sync; 223 int *rtvals; |
224{ 225 int i; 226 | 224{ 225 int i; 226 |
227 if( pager->pg_ops->pgo_putpages) 228 return(VM_PAGER_PUT_MULTI(pager, m, count, sync, rtvals)); | 227 if (pager->pg_ops->pgo_putpages) 228 return (VM_PAGER_PUT_MULTI(pager, m, count, sync, rtvals)); |
229 else { | 229 else { |
230 for(i=0;i<count;i++) { 231 rtvals[i] = VM_PAGER_PUT( pager, m[i], sync); | 230 for (i = 0; i < count; i++) { 231 rtvals[i] = VM_PAGER_PUT(pager, m[i], sync); |
232 } 233 return rtvals[0]; 234 } 235} 236 237boolean_t 238vm_pager_has_page(pager, offset) | 232 } 233 return rtvals[0]; 234 } 235} 236 237boolean_t 238vm_pager_has_page(pager, offset) |
239 vm_pager_t pager; 240 vm_offset_t offset; | 239 vm_pager_t pager; 240 vm_offset_t offset; |
241{ 242 if (pager == NULL) 243 panic("vm_pager_has_page: null pager"); | 241{ 242 if (pager == NULL) 243 panic("vm_pager_has_page: null pager"); |
244 return ((*pager->pg_ops->pgo_haspage)(pager, offset)); | 244 return ((*pager->pg_ops->pgo_haspage) (pager, offset)); |
245} 246 247/* 248 * Called by pageout daemon before going back to sleep. 249 * Gives pagers a chance to clean up any completed async pageing operations. 250 */ 251void 252vm_pager_sync() 253{ 254 struct pagerops **pgops; 255 256 for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++) 257 if (pgops) | 245} 246 247/* 248 * Called by pageout daemon before going back to sleep. 249 * Gives pagers a chance to clean up any completed async pageing operations. 250 */ 251void 252vm_pager_sync() 253{ 254 struct pagerops **pgops; 255 256 for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++) 257 if (pgops) |
258 (*(*pgops)->pgo_putpage)(NULL, NULL, 0); | 258 (*(*pgops)->pgo_putpage) (NULL, NULL, 0); |
259} 260 261#if 0 262void 263vm_pager_cluster(pager, offset, loff, hoff) | 259} 260 261#if 0 262void 263vm_pager_cluster(pager, offset, loff, hoff) |
264 vm_pager_t pager; 265 vm_offset_t offset; 266 vm_offset_t *loff; 267 vm_offset_t *hoff; | 264 vm_pager_t pager; 265 vm_offset_t offset; 266 vm_offset_t *loff; 267 vm_offset_t *hoff; |
268{ 269 if (pager == NULL) 270 panic("vm_pager_cluster: null pager"); | 268{ 269 if (pager == NULL) 270 panic("vm_pager_cluster: null pager"); |
271 return ((*pager->pg_ops->pgo_cluster)(pager, offset, loff, hoff)); | 271 return ((*pager->pg_ops->pgo_cluster) (pager, offset, loff, hoff)); |
272} 273#endif 274 275vm_offset_t 276vm_pager_map_page(m) | 272} 273#endif 274 275vm_offset_t 276vm_pager_map_page(m) |
277 vm_page_t m; | 277 vm_page_t m; |
278{ 279 vm_offset_t kva; 280 281 kva = kmem_alloc_wait(pager_map, PAGE_SIZE); 282 pmap_kenter(kva, VM_PAGE_TO_PHYS(m)); | 278{ 279 vm_offset_t kva; 280 281 kva = kmem_alloc_wait(pager_map, PAGE_SIZE); 282 pmap_kenter(kva, VM_PAGE_TO_PHYS(m)); |
283 return(kva); | 283 return (kva); |
284} 285 286void 287vm_pager_unmap_page(kva) | 284} 285 286void 287vm_pager_unmap_page(kva) |
288 vm_offset_t kva; | 288 vm_offset_t kva; |
289{ 290 pmap_kremove(kva); 291 kmem_free_wakeup(pager_map, kva, PAGE_SIZE); 292} 293 294vm_page_t 295vm_pager_atop(kva) | 289{ 290 pmap_kremove(kva); 291 kmem_free_wakeup(pager_map, kva, PAGE_SIZE); 292} 293 294vm_page_t 295vm_pager_atop(kva) |
296 vm_offset_t kva; | 296 vm_offset_t kva; |
297{ 298 vm_offset_t pa; 299 | 297{ 298 vm_offset_t pa; 299 |
300 pa = pmap_kextract( kva); | 300 pa = pmap_kextract(kva); |
301 if (pa == 0) 302 panic("vm_pager_atop"); 303 return (PHYS_TO_VM_PAGE(pa)); 304} 305 306vm_pager_t 307vm_pager_lookup(pglist, handle) 308 register struct pagerlst *pglist; --- 8 unchanged lines hidden (view full) --- 317} 318 319/* 320 * This routine gains a reference to the object. 321 * Explicit deallocation is necessary. 322 */ 323int 324pager_cache(object, should_cache) | 301 if (pa == 0) 302 panic("vm_pager_atop"); 303 return (PHYS_TO_VM_PAGE(pa)); 304} 305 306vm_pager_t 307vm_pager_lookup(pglist, handle) 308 register struct pagerlst *pglist; --- 8 unchanged lines hidden (view full) --- 317} 318 319/* 320 * This routine gains a reference to the object. 321 * Explicit deallocation is necessary. 322 */ 323int 324pager_cache(object, should_cache) |
325 vm_object_t object; 326 boolean_t should_cache; | 325 vm_object_t object; 326 boolean_t should_cache; |
327{ 328 if (object == NULL) 329 return (KERN_INVALID_ARGUMENT); 330 331 vm_object_cache_lock(); 332 vm_object_lock(object); 333 if (should_cache) 334 object->flags |= OBJ_CANPERSIST; 335 else 336 object->flags &= ~OBJ_CANPERSIST; 337 vm_object_unlock(object); 338 vm_object_cache_unlock(); 339 340 vm_object_deallocate(object); 341 342 return (KERN_SUCCESS); 343} 344 345/* | 327{ 328 if (object == NULL) 329 return (KERN_INVALID_ARGUMENT); 330 331 vm_object_cache_lock(); 332 vm_object_lock(object); 333 if (should_cache) 334 object->flags |= OBJ_CANPERSIST; 335 else 336 object->flags &= ~OBJ_CANPERSIST; 337 vm_object_unlock(object); 338 vm_object_cache_unlock(); 339 340 vm_object_deallocate(object); 341 342 return (KERN_SUCCESS); 343} 344 345/* |
346 * allocate a physical buffer | 346 * allocate a physical buffer |
347 */ 348struct buf * | 347 */ 348struct buf * |
349getpbuf() { | 349getpbuf() 350{ |
350 int s; 351 struct buf *bp; 352 353 s = splbio(); 354 /* get a bp from the swap buffer header pool */ 355 while ((bp = bswlist.tqh_first) == NULL) { 356 bswneeded = 1; | 351 int s; 352 struct buf *bp; 353 354 s = splbio(); 355 /* get a bp from the swap buffer header pool */ 356 while ((bp = bswlist.tqh_first) == NULL) { 357 bswneeded = 1; |
357 tsleep((caddr_t)&bswneeded, PVM, "wswbuf", 0); | 358 tsleep((caddr_t) & bswneeded, PVM, "wswbuf", 0); |
358 } 359 TAILQ_REMOVE(&bswlist, bp, b_freelist); 360 splx(s); 361 362 bzero(bp, sizeof *bp); 363 bp->b_rcred = NOCRED; 364 bp->b_wcred = NOCRED; | 359 } 360 TAILQ_REMOVE(&bswlist, bp, b_freelist); 361 splx(s); 362 363 bzero(bp, sizeof *bp); 364 bp->b_rcred = NOCRED; 365 bp->b_wcred = NOCRED; |
365 bp->b_data = (caddr_t) (MAXPHYS * (bp-swbuf)) + swapbkva; | 366 bp->b_data = (caddr_t) (MAXPHYS * (bp - swbuf)) + swapbkva; |
366 bp->b_vnbufs.le_next = NOLIST; 367 return bp; 368} 369 370/* 371 * allocate a physical buffer, if one is available 372 */ 373struct buf * | 367 bp->b_vnbufs.le_next = NOLIST; 368 return bp; 369} 370 371/* 372 * allocate a physical buffer, if one is available 373 */ 374struct buf * |
374trypbuf() { | 375trypbuf() 376{ |
375 int s; 376 struct buf *bp; 377 378 s = splbio(); 379 if ((bp = bswlist.tqh_first) == NULL) { 380 splx(s); 381 return NULL; 382 } 383 TAILQ_REMOVE(&bswlist, bp, b_freelist); 384 splx(s); 385 386 bzero(bp, sizeof *bp); 387 bp->b_rcred = NOCRED; 388 bp->b_wcred = NOCRED; | 377 int s; 378 struct buf *bp; 379 380 s = splbio(); 381 if ((bp = bswlist.tqh_first) == NULL) { 382 splx(s); 383 return NULL; 384 } 385 TAILQ_REMOVE(&bswlist, bp, b_freelist); 386 splx(s); 387 388 bzero(bp, sizeof *bp); 389 bp->b_rcred = NOCRED; 390 bp->b_wcred = NOCRED; |
389 bp->b_data = (caddr_t) (MAXPHYS * (bp-swbuf)) + swapbkva; | 391 bp->b_data = (caddr_t) (MAXPHYS * (bp - swbuf)) + swapbkva; |
390 bp->b_vnbufs.le_next = NOLIST; 391 return bp; 392} 393 394/* 395 * release a physical buffer 396 */ 397void --- 7 unchanged lines hidden (view full) --- 405 if (bp->b_rcred != NOCRED) { 406 crfree(bp->b_rcred); 407 bp->b_rcred = NOCRED; 408 } 409 if (bp->b_wcred != NOCRED) { 410 crfree(bp->b_wcred); 411 bp->b_wcred = NOCRED; 412 } | 392 bp->b_vnbufs.le_next = NOLIST; 393 return bp; 394} 395 396/* 397 * release a physical buffer 398 */ 399void --- 7 unchanged lines hidden (view full) --- 407 if (bp->b_rcred != NOCRED) { 408 crfree(bp->b_rcred); 409 bp->b_rcred = NOCRED; 410 } 411 if (bp->b_wcred != NOCRED) { 412 crfree(bp->b_wcred); 413 bp->b_wcred = NOCRED; 414 } |
413 | |
414 if (bp->b_vp) | 415 if (bp->b_vp) |
415 brelvp(bp); | 416 pbrelvp(bp); |
416 417 if (bp->b_flags & B_WANTED) | 417 418 if (bp->b_flags & B_WANTED) |
418 wakeup((caddr_t)bp); | 419 wakeup((caddr_t) bp); |
419 420 TAILQ_INSERT_HEAD(&bswlist, bp, b_freelist); 421 422 if (bswneeded) { 423 bswneeded = 0; | 420 421 TAILQ_INSERT_HEAD(&bswlist, bp, b_freelist); 422 423 if (bswneeded) { 424 bswneeded = 0; |
424 wakeup((caddr_t)&bswlist); | 425 wakeup((caddr_t) & bswlist); |
425 } 426 splx(s); 427} | 426 } 427 splx(s); 428} |