1 /* $NetBSD: uvm_object.c,v 1.5 2008/01/04 21:18:18 ad Exp $ */ 2 3 /* 4 * Copyright (c) 2006 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Mindaugas Rasiukevicius. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * uvm_object.c: operate with memory objects 41 * 42 * TODO: 43 * 1. Support PG_RELEASED-using objects 44 * 45 */ 46 47 #include <sys/cdefs.h> 48 __KERNEL_RCSID(0, "$NetBSD: uvm_object.c,v 1.5 2008/01/04 21:18:18 ad Exp $"); 49 50 #include "opt_uvmhist.h" 51 52 #include <sys/param.h> 53 54 #include <uvm/uvm.h> 55 56 /* We will fetch this page count per step */ 57 #define FETCH_PAGECOUNT 16 58 59 /* 60 * uobj_wirepages: wire the pages of entire uobj 61 * 62 * => NOTE: this function should only be used for types of objects 63 * where PG_RELEASED flag is never set (aobj objects) 64 * => caller must pass page-aligned start and end values 65 */ 66 67 int 68 uobj_wirepages(struct uvm_object *uobj, off_t start, off_t end) 69 { 70 int i, npages, error; 71 struct vm_page *pgs[FETCH_PAGECOUNT], *pg = NULL; 72 off_t offset = start, left; 73 74 left = (end - start) >> PAGE_SHIFT; 75 76 mutex_enter(&uobj->vmobjlock); 77 while (left) { 78 79 npages = MIN(FETCH_PAGECOUNT, left); 80 81 /* Get the pages */ 82 memset(pgs, 0, sizeof(pgs)); 83 error = (*uobj->pgops->pgo_get)(uobj, offset, pgs, &npages, 0, 84 VM_PROT_READ | VM_PROT_WRITE, UVM_ADV_SEQUENTIAL, 85 PGO_ALLPAGES | PGO_SYNCIO); 86 87 if (error) 88 goto error; 89 90 mutex_enter(&uobj->vmobjlock); 91 for (i = 0; i < npages; i++) { 92 93 KASSERT(pgs[i] != NULL); 94 KASSERT(!(pgs[i]->flags & PG_RELEASED)); 95 96 /* 97 * Loan break 98 */ 99 if (pgs[i]->loan_count) { 100 while (pgs[i]->loan_count) { 101 pg = uvm_loanbreak(pgs[i]); 102 if (!pg) { 103 mutex_exit(&uobj->vmobjlock); 104 uvm_wait("uobjwirepg"); 105 mutex_enter(&uobj->vmobjlock); 106 continue; 107 } 108 } 109 pgs[i] = pg; 110 } 111 112 if (pgs[i]->pqflags & PQ_AOBJ) { 113 pgs[i]->flags &= ~(PG_CLEAN); 114 uao_dropswap(uobj, i); 115 } 116 } 117 118 /* Wire the pages */ 119 mutex_enter(&uvm_pageqlock); 120 for (i = 0; i < npages; i++) { 121 uvm_pagewire(pgs[i]); 122 } 123 mutex_exit(&uvm_pageqlock); 124 125 /* Unbusy the pages */ 126 uvm_page_unbusy(pgs, npages); 127 128 left -= npages; 129 offset += npages << PAGE_SHIFT; 130 } 131 mutex_exit(&uobj->vmobjlock); 132 133 return 0; 134 135 error: 136 /* Unwire the pages which has been wired */ 137 uobj_unwirepages(uobj, start, offset); 138 139 return error; 140 } 141 142 /* 143 * uobj_unwirepages: unwire the pages of entire uobj 144 * 145 * => NOTE: this function should only be used for types of objects 146 * where PG_RELEASED flag is never set 147 * => caller must pass page-aligned start and end values 148 */ 149 150 void 151 uobj_unwirepages(struct uvm_object *uobj, off_t start, off_t end) 152 { 153 struct vm_page *pg; 154 off_t offset; 155 156 mutex_enter(&uobj->vmobjlock); 157 mutex_enter(&uvm_pageqlock); 158 for (offset = start; offset < end; offset += PAGE_SIZE) { 159 pg = uvm_pagelookup(uobj, offset); 160 161 KASSERT(pg != NULL); 162 KASSERT(!(pg->flags & PG_RELEASED)); 163 164 uvm_pageunwire(pg); 165 } 166 mutex_exit(&uvm_pageqlock); 167 mutex_exit(&uobj->vmobjlock); 168 } 169