Annotation of sys/uvm/uvm_anon.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: uvm_anon.c,v 1.28 2007/06/18 21:51:15 pedro Exp $ */
2: /* $NetBSD: uvm_anon.c,v 1.10 2000/11/25 06:27:59 chs Exp $ */
3:
4: /*
5: *
6: * Copyright (c) 1997 Charles D. Cranor and Washington University.
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by Charles D. Cranor and
20: * Washington University.
21: * 4. The name of the author may not be used to endorse or promote products
22: * derived from this software without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: /*
37: * uvm_anon.c: uvm anon ops
38: */
39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/proc.h>
43: #include <sys/malloc.h>
44: #include <sys/pool.h>
45: #include <sys/kernel.h>
46:
47: #include <uvm/uvm.h>
48: #include <uvm/uvm_swap.h>
49:
50: struct pool uvm_anon_pool;
51:
52: /*
53: * allocate anons
54: */
55: void
56: uvm_anon_init()
57: {
58: pool_init(&uvm_anon_pool, sizeof(struct vm_anon), 0, 0, 0, "anonpl",
59: &pool_allocator_nointr);
60: pool_sethiwat(&uvm_anon_pool, uvmexp.free / 16);
61: }
62:
63: /*
64: * allocate an anon
65: */
66: struct vm_anon *
67: uvm_analloc()
68: {
69: struct vm_anon *anon;
70:
71: anon = pool_get(&uvm_anon_pool, PR_NOWAIT);
72: if (anon) {
73: simple_lock_init(&anon->an_lock);
74: anon->an_ref = 1;
75: anon->an_page = NULL;
76: anon->an_swslot = 0;
77: simple_lock(&anon->an_lock);
78: }
79: return(anon);
80: }
81:
82: /*
83: * uvm_anfree: free a single anon structure
84: *
85: * => caller must remove anon from its amap before calling (if it was in
86: * an amap).
87: * => anon must be unlocked and have a zero reference count.
88: * => we may lock the pageq's.
89: */
90: void
91: uvm_anfree(anon)
92: struct vm_anon *anon;
93: {
94: struct vm_page *pg;
95: UVMHIST_FUNC("uvm_anfree"); UVMHIST_CALLED(maphist);
96: UVMHIST_LOG(maphist,"(anon=%p)", anon, 0,0,0);
97:
98: /*
99: * get page
100: */
101:
102: pg = anon->an_page;
103:
104: /*
105: * if there is a resident page and it is loaned, then anon may not
106: * own it. call out to uvm_anon_lockpage() to ensure the real owner
107: * of the page has been identified and locked.
108: */
109:
110: if (pg && pg->loan_count)
111: pg = uvm_anon_lockloanpg(anon);
112:
113: /*
114: * if we have a resident page, we must dispose of it before freeing
115: * the anon.
116: */
117:
118: if (pg) {
119:
120: /*
121: * if the page is owned by a uobject (now locked), then we must
122: * kill the loan on the page rather than free it.
123: */
124:
125: if (pg->uobject) {
126: uvm_lock_pageq();
127: KASSERT(pg->loan_count > 0);
128: pg->loan_count--;
129: pg->uanon = NULL;
130: uvm_unlock_pageq();
131: simple_unlock(&pg->uobject->vmobjlock);
132: } else {
133:
134: /*
135: * page has no uobject, so we must be the owner of it.
136: *
137: * if page is busy then we just mark it as released
138: * (who ever has it busy must check for this when they
139: * wake up). if the page is not busy then we can
140: * free it now.
141: */
142:
143: if ((pg->pg_flags & PG_BUSY) != 0) {
144: /* tell them to dump it when done */
145: atomic_setbits_int(&pg->pg_flags, PG_RELEASED);
146: UVMHIST_LOG(maphist,
147: " anon %p, page %p: BUSY (released!)",
148: anon, pg, 0, 0);
149: return;
150: }
151: pmap_page_protect(pg, VM_PROT_NONE);
152: uvm_lock_pageq(); /* lock out pagedaemon */
153: uvm_pagefree(pg); /* bye bye */
154: uvm_unlock_pageq(); /* free the daemon */
155: UVMHIST_LOG(maphist,"anon %p, page %p: freed now!",
156: anon, pg, 0, 0);
157: }
158: }
159:
160: /*
161: * free any swap resources.
162: */
163: uvm_anon_dropswap(anon);
164:
165: /*
166: * now that we've stripped the data areas from the anon, free the anon
167: * itself!
168: */
169: KASSERT(anon->an_page == NULL);
170: KASSERT(anon->an_swslot == 0);
171:
172: pool_put(&uvm_anon_pool, anon);
173: UVMHIST_LOG(maphist,"<- done!",0,0,0,0);
174: }
175:
176: /*
177: * uvm_anon_dropswap: release any swap resources from this anon.
178: *
179: * => anon must be locked or have a reference count of 0.
180: */
181: void
182: uvm_anon_dropswap(anon)
183: struct vm_anon *anon;
184: {
185: UVMHIST_FUNC("uvm_anon_dropswap"); UVMHIST_CALLED(maphist);
186:
187: if (anon->an_swslot == 0)
188: return;
189:
190: UVMHIST_LOG(maphist,"freeing swap for anon %p, paged to swslot 0x%lx",
191: anon, anon->an_swslot, 0, 0);
192: uvm_swap_free(anon->an_swslot, 1);
193: anon->an_swslot = 0;
194:
195: if (anon->an_page == NULL) {
196: /* this page is no longer only in swap. */
197: simple_lock(&uvm.swap_data_lock);
198: uvmexp.swpgonly--;
199: simple_unlock(&uvm.swap_data_lock);
200: }
201: }
202:
203: /*
204: * uvm_anon_lockloanpg: given a locked anon, lock its resident page
205: *
206: * => anon is locked by caller
207: * => on return: anon is locked
208: * if there is a resident page:
209: * if it has a uobject, it is locked by us
210: * if it is ownerless, we take over as owner
211: * we return the resident page (it can change during
212: * this function)
213: * => note that the only time an anon has an ownerless resident page
214: * is if the page was loaned from a uvm_object and the uvm_object
215: * disowned it
216: * => this only needs to be called when you want to do an operation
217: * on an anon's resident page and that page has a non-zero loan
218: * count.
219: */
220: struct vm_page *
221: uvm_anon_lockloanpg(anon)
222: struct vm_anon *anon;
223: {
224: struct vm_page *pg;
225: boolean_t locked = FALSE;
226:
227: /*
228: * loop while we have a resident page that has a non-zero loan count.
229: * if we successfully get our lock, we will "break" the loop.
230: * note that the test for pg->loan_count is not protected -- this
231: * may produce false positive results. note that a false positive
232: * result may cause us to do more work than we need to, but it will
233: * not produce an incorrect result.
234: */
235:
236: while (((pg = anon->an_page) != NULL) && pg->loan_count != 0) {
237:
238: /*
239: * quickly check to see if the page has an object before
240: * bothering to lock the page queues. this may also produce
241: * a false positive result, but that's ok because we do a real
242: * check after that.
243: *
244: * XXX: quick check -- worth it? need volatile?
245: */
246:
247: if (pg->uobject) {
248:
249: uvm_lock_pageq();
250: if (pg->uobject) { /* the "real" check */
251: locked =
252: simple_lock_try(&pg->uobject->vmobjlock);
253: } else {
254: /* object disowned before we got PQ lock */
255: locked = TRUE;
256: }
257: uvm_unlock_pageq();
258:
259: /*
260: * if we didn't get a lock (try lock failed), then we
261: * toggle our anon lock and try again
262: */
263:
264: if (!locked) {
265: simple_unlock(&anon->an_lock);
266:
267: /*
268: * someone locking the object has a chance to
269: * lock us right now
270: */
271:
272: simple_lock(&anon->an_lock);
273: continue;
274: }
275: }
276:
277: /*
278: * if page is un-owned [i.e. the object dropped its ownership],
279: * then we can take over as owner!
280: */
281:
282: if (pg->uobject == NULL && (pg->pg_flags & PQ_ANON) == 0) {
283: uvm_lock_pageq();
284: atomic_setbits_int(&pg->pg_flags, PQ_ANON);
285: pg->loan_count--; /* ... and drop our loan */
286: uvm_unlock_pageq();
287: }
288:
289: /*
290: * we did it! break the loop
291: */
292:
293: break;
294: }
295: return(pg);
296: }
297:
298: /*
299: * fetch an anon's page.
300: *
301: * => anon must be locked, and is unlocked upon return.
302: * => returns TRUE if pagein was aborted due to lack of memory.
303: */
304:
305: boolean_t
306: uvm_anon_pagein(anon)
307: struct vm_anon *anon;
308: {
309: struct vm_page *pg;
310: struct uvm_object *uobj;
311: int rv;
312:
313: /* locked: anon */
314: rv = uvmfault_anonget(NULL, NULL, anon);
315: /*
316: * if rv == VM_PAGER_OK, anon is still locked, else anon
317: * is unlocked
318: */
319:
320: switch (rv) {
321: case VM_PAGER_OK:
322: break;
323:
324: case VM_PAGER_ERROR:
325: case VM_PAGER_REFAULT:
326:
327: /*
328: * nothing more to do on errors.
329: * VM_PAGER_REFAULT can only mean that the anon was freed,
330: * so again there's nothing to do.
331: */
332:
333: return FALSE;
334:
335: default:
336: #ifdef DIAGNOSTIC
337: panic("anon_pagein: uvmfault_anonget -> %d", rv);
338: #else
339: return FALSE;
340: #endif
341: }
342:
343: /*
344: * ok, we've got the page now.
345: * mark it as dirty, clear its swslot and un-busy it.
346: */
347:
348: pg = anon->an_page;
349: uobj = pg->uobject;
350: uvm_swap_free(anon->an_swslot, 1);
351: anon->an_swslot = 0;
352: atomic_clearbits_int(&pg->pg_flags, PG_CLEAN);
353:
354: /*
355: * deactivate the page (to put it on a page queue)
356: */
357:
358: pmap_clear_reference(pg);
359: pmap_page_protect(pg, VM_PROT_NONE);
360: uvm_lock_pageq();
361: uvm_pagedeactivate(pg);
362: uvm_unlock_pageq();
363:
364: /*
365: * unlock the anon and we're done.
366: */
367:
368: simple_unlock(&anon->an_lock);
369: if (uobj) {
370: simple_unlock(&uobj->vmobjlock);
371: }
372: return FALSE;
373: }
CVSweb