FreeBSD/Linux Kernel Cross Reference
sys/uvm/uvm_amap_i.h
1 /* $NetBSD: uvm_amap_i.h,v 1.21 2005/02/28 15:31:04 chs Exp $ */
2
3 /*
4 *
5 * Copyright (c) 1997 Charles D. Cranor and Washington University.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Charles D. Cranor and
19 * Washington University.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 * from: Id: uvm_amap_i.h,v 1.1.2.4 1998/01/05 18:12:57 chuck Exp
35 */
36
37 /*
38 * uvm_amap_i.h
39 */
40
41 /*
42 * if inlines are enabled always pull in these functions, otherwise
43 * pull them in only once (when we are compiling uvm_amap.c).
44 */
45 #if defined(UVM_AMAP_INLINE) || defined(UVM_AMAP_C)
46 #ifndef _UVM_UVM_AMAP_I_H_
47 #define _UVM_UVM_AMAP_I_H_
48
49 /*
50 * amap_lookup: look up a page in an amap
51 *
52 * => amap should be locked by caller.
53 */
54 AMAP_INLINE struct vm_anon *
55 amap_lookup(aref, offset)
56 struct vm_aref *aref;
57 vaddr_t offset;
58 {
59 int slot;
60 struct vm_amap *amap = aref->ar_amap;
61 UVMHIST_FUNC("amap_lookup"); UVMHIST_CALLED(maphist);
62 LOCK_ASSERT(simple_lock_held(&amap->am_l));
63
64 AMAP_B2SLOT(slot, offset);
65 slot += aref->ar_pageoff;
66
67 if (slot >= amap->am_nslot)
68 panic("amap_lookup: offset out of range");
69
70 UVMHIST_LOG(maphist, "<- done (amap=0x%x, offset=0x%x, result=0x%x)",
71 amap, offset, amap->am_anon[slot], 0);
72 return(amap->am_anon[slot]);
73 }
74
75 /*
76 * amap_lookups: look up a range of pages in an amap
77 *
78 * => amap should be locked by caller.
79 * => XXXCDC: this interface is biased toward array-based amaps. fix.
80 */
81 AMAP_INLINE void
82 amap_lookups(aref, offset, anons, npages)
83 struct vm_aref *aref;
84 vaddr_t offset;
85 struct vm_anon **anons;
86 int npages;
87 {
88 int slot;
89 struct vm_amap *amap = aref->ar_amap;
90 UVMHIST_FUNC("amap_lookups"); UVMHIST_CALLED(maphist);
91 LOCK_ASSERT(simple_lock_held(&amap->am_l));
92
93 AMAP_B2SLOT(slot, offset);
94 slot += aref->ar_pageoff;
95
96 UVMHIST_LOG(maphist, " slot=%d, npages=%d, nslot=%d", slot, npages,
97 amap->am_nslot, 0);
98
99 if ((slot + (npages - 1)) >= amap->am_nslot)
100 panic("amap_lookups: offset out of range");
101
102 memcpy(anons, &amap->am_anon[slot], npages * sizeof(struct vm_anon *));
103
104 UVMHIST_LOG(maphist, "<- done", 0, 0, 0, 0);
105 return;
106 }
107
108 /*
109 * amap_add: add (or replace) a page to an amap
110 *
111 * => caller must lock amap.
112 * => if (replace) caller must lock anon because we might have to call
113 * pmap_page_protect on the anon's page.
114 */
115 AMAP_INLINE void
116 amap_add(aref, offset, anon, replace)
117 struct vm_aref *aref;
118 vaddr_t offset;
119 struct vm_anon *anon;
120 boolean_t replace;
121 {
122 int slot;
123 struct vm_amap *amap = aref->ar_amap;
124 UVMHIST_FUNC("amap_add"); UVMHIST_CALLED(maphist);
125 LOCK_ASSERT(simple_lock_held(&amap->am_l));
126
127 AMAP_B2SLOT(slot, offset);
128 slot += aref->ar_pageoff;
129
130 if (slot >= amap->am_nslot)
131 panic("amap_add: offset out of range");
132
133 if (replace) {
134
135 if (amap->am_anon[slot] == NULL)
136 panic("amap_add: replacing null anon");
137 if (amap->am_anon[slot]->u.an_page != NULL &&
138 (amap->am_flags & AMAP_SHARED) != 0) {
139 pmap_page_protect(amap->am_anon[slot]->u.an_page,
140 VM_PROT_NONE);
141 /*
142 * XXX: suppose page is supposed to be wired somewhere?
143 */
144 }
145 } else { /* !replace */
146 if (amap->am_anon[slot] != NULL)
147 panic("amap_add: slot in use");
148
149 amap->am_bckptr[slot] = amap->am_nused;
150 amap->am_slots[amap->am_nused] = slot;
151 amap->am_nused++;
152 }
153 amap->am_anon[slot] = anon;
154 UVMHIST_LOG(maphist,
155 "<- done (amap=0x%x, offset=0x%x, anon=0x%x, rep=%d)",
156 amap, offset, anon, replace);
157 }
158
159 /*
160 * amap_unadd: remove a page from an amap
161 *
162 * => caller must lock amap
163 */
164 AMAP_INLINE void
165 amap_unadd(aref, offset)
166 struct vm_aref *aref;
167 vaddr_t offset;
168 {
169 int ptr, slot;
170 struct vm_amap *amap = aref->ar_amap;
171 UVMHIST_FUNC("amap_unadd"); UVMHIST_CALLED(maphist);
172 LOCK_ASSERT(simple_lock_held(&amap->am_l));
173
174 AMAP_B2SLOT(slot, offset);
175 slot += aref->ar_pageoff;
176
177 if (slot >= amap->am_nslot)
178 panic("amap_unadd: offset out of range");
179
180 if (amap->am_anon[slot] == NULL)
181 panic("amap_unadd: nothing there");
182
183 amap->am_anon[slot] = NULL;
184 ptr = amap->am_bckptr[slot];
185
186 if (ptr != (amap->am_nused - 1)) { /* swap to keep slots contig? */
187 amap->am_slots[ptr] = amap->am_slots[amap->am_nused - 1];
188 amap->am_bckptr[amap->am_slots[ptr]] = ptr; /* back link */
189 }
190 amap->am_nused--;
191 UVMHIST_LOG(maphist, "<- done (amap=0x%x, slot=0x%x)", amap, slot,0, 0);
192 }
193
194 /*
195 * amap_ref: gain a reference to an amap
196 *
197 * => amap must not be locked (we will lock)
198 * => "offset" and "len" are in units of pages
199 * => called at fork time to gain the child's reference
200 */
201 AMAP_INLINE void
202 amap_ref(amap, offset, len, flags)
203 struct vm_amap *amap;
204 vaddr_t offset;
205 vsize_t len;
206 int flags;
207 {
208 UVMHIST_FUNC("amap_ref"); UVMHIST_CALLED(maphist);
209
210 amap_lock(amap);
211 if (flags & AMAP_SHARED)
212 amap->am_flags |= AMAP_SHARED;
213 #ifdef UVM_AMAP_PPREF
214 if (amap->am_ppref == NULL && (flags & AMAP_REFALL) == 0 &&
215 len != amap->am_nslot)
216 amap_pp_establish(amap, offset);
217 #endif
218 amap->am_ref++;
219 #ifdef UVM_AMAP_PPREF
220 if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
221 if (flags & AMAP_REFALL)
222 amap_pp_adjref(amap, 0, amap->am_nslot, 1);
223 else
224 amap_pp_adjref(amap, offset, len, 1);
225 }
226 #endif
227 amap_unlock(amap);
228 UVMHIST_LOG(maphist,"<- done! amap=0x%x", amap, 0, 0, 0);
229 }
230
231 /*
232 * amap_unref: remove a reference to an amap
233 *
234 * => caller must remove all pmap-level references to this amap before
235 * dropping the reference
236 * => called from uvm_unmap_detach [only] ... note that entry is no
237 * longer part of a map and thus has no need for locking
238 * => amap must be unlocked (we will lock it).
239 */
240 AMAP_INLINE void
241 amap_unref(amap, offset, len, all)
242 struct vm_amap *amap;
243 vaddr_t offset;
244 vsize_t len;
245 boolean_t all;
246 {
247 UVMHIST_FUNC("amap_unref"); UVMHIST_CALLED(maphist);
248
249 /*
250 * lock it
251 */
252 amap_lock(amap);
253 UVMHIST_LOG(maphist," amap=0x%x refs=%d, nused=%d",
254 amap, amap->am_ref, amap->am_nused, 0);
255
256 /*
257 * if we are the last reference, free the amap and return.
258 */
259
260 if (amap->am_ref == 1) {
261 amap_wipeout(amap); /* drops final ref and frees */
262 UVMHIST_LOG(maphist,"<- done (was last ref)!", 0, 0, 0, 0);
263 return; /* no need to unlock */
264 }
265
266 /*
267 * otherwise just drop the reference count(s)
268 */
269
270 amap->am_ref--;
271 if (amap->am_ref == 1 && (amap->am_flags & AMAP_SHARED) != 0)
272 amap->am_flags &= ~AMAP_SHARED; /* clear shared flag */
273 #ifdef UVM_AMAP_PPREF
274 if (amap->am_ppref == NULL && all == 0 && len != amap->am_nslot)
275 amap_pp_establish(amap, offset);
276 if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
277 if (all)
278 amap_pp_adjref(amap, 0, amap->am_nslot, -1);
279 else
280 amap_pp_adjref(amap, offset, len, -1);
281 }
282 #endif
283 amap_unlock(amap);
284
285 UVMHIST_LOG(maphist,"<- done!", 0, 0, 0, 0);
286 }
287
288 #endif /* _UVM_UVM_AMAP_I_H_ */
289
290 #endif /* defined(UVM_AMAP_INLINE) || defined(UVM_AMAP_C) */
291
Cache object: fba0fdc52a60ca684f38c7ecc4b50a35
|