xref: /netbsd-src/sys/uvm/uvm_object.c (revision 267197ec1eebfcb9810ea27a89625b6ddf68e3e7)
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