Annotation of sys/uvm/uvm_page_i.h, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: uvm_page_i.h,v 1.17 2007/04/13 18:57:49 art Exp $ */
2: /* $NetBSD: uvm_page_i.h,v 1.14 2000/11/27 07:47:42 chs Exp $ */
3:
4: /*
5: * Copyright (c) 1997 Charles D. Cranor and Washington University.
6: * Copyright (c) 1991, 1993, The Regents of the University of California.
7: *
8: * All rights reserved.
9: *
10: * This code is derived from software contributed to Berkeley by
11: * The Mach Operating System project at Carnegie-Mellon University.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. All advertising materials mentioning features or use of this software
22: * must display the following acknowledgement:
23: * This product includes software developed by Charles D. Cranor,
24: * Washington University, the University of California, Berkeley and
25: * its contributors.
26: * 4. Neither the name of the University nor the names of its contributors
27: * may be used to endorse or promote products derived from this software
28: * without specific prior written permission.
29: *
30: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40: * SUCH DAMAGE.
41: *
42: * @(#)vm_page.c 8.3 (Berkeley) 3/21/94
43: * from: Id: uvm_page_i.h,v 1.1.2.7 1998/01/05 00:26:02 chuck Exp
44: *
45: *
46: * Copyright (c) 1987, 1990 Carnegie-Mellon University.
47: * All rights reserved.
48: *
49: * Permission to use, copy, modify and distribute this software and
50: * its documentation is hereby granted, provided that both the copyright
51: * notice and this permission notice appear in all copies of the
52: * software, derivative works or modified versions, and any portions
53: * thereof, and that both notices appear in supporting documentation.
54: *
55: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
56: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
57: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
58: *
59: * Carnegie Mellon requests users of this software to return to
60: *
61: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
62: * School of Computer Science
63: * Carnegie Mellon University
64: * Pittsburgh PA 15213-3890
65: *
66: * any improvements or extensions that they make and grant Carnegie the
67: * rights to redistribute these changes.
68: */
69:
70: #ifndef _UVM_UVM_PAGE_I_H_
71: #define _UVM_UVM_PAGE_I_H_
72:
73: /*
74: * uvm_page_i.h
75: */
76:
77: /*
78: * inline functions [maybe]
79: */
80:
81: #if defined(UVM_PAGE_INLINE) || defined(UVM_PAGE)
82:
83: /*
84: * uvm_lock_fpageq: lock the free page queue
85: *
86: * => free page queue can be accessed in interrupt context, so this
87: * blocks all interrupts that can cause memory allocation, and
88: * returns the previous interrupt level.
89: */
90:
91: PAGE_INLINE int
92: uvm_lock_fpageq(void)
93: {
94: int s;
95:
96: s = splvm();
97: simple_lock(&uvm.fpageqlock);
98: return (s);
99: }
100:
101: /*
102: * uvm_unlock_fpageq: unlock the free page queue
103: *
104: * => caller must supply interrupt level returned by uvm_lock_fpageq()
105: * so that it may be restored.
106: */
107:
108: PAGE_INLINE void
109: uvm_unlock_fpageq(int s)
110: {
111:
112: simple_unlock(&uvm.fpageqlock);
113: splx(s);
114: }
115:
116: /*
117: * uvm_pagelookup: look up a page
118: *
119: * => caller should lock object to keep someone from pulling the page
120: * out from under it
121: */
122:
123: struct vm_page *
124: uvm_pagelookup(struct uvm_object *obj, voff_t off)
125: {
126: struct vm_page *pg;
127: struct pglist *buck;
128: int s;
129:
130: buck = &uvm.page_hash[uvm_pagehash(obj,off)];
131:
132: s = splvm();
133: simple_lock(&uvm.hashlock);
134: TAILQ_FOREACH(pg, buck, hashq) {
135: if (pg->uobject == obj && pg->offset == off) {
136: break;
137: }
138: }
139: simple_unlock(&uvm.hashlock);
140: splx(s);
141: return(pg);
142: }
143:
144: /*
145: * uvm_pagewire: wire the page, thus removing it from the daemon's grasp
146: *
147: * => caller must lock page queues
148: */
149:
150: PAGE_INLINE void
151: uvm_pagewire(struct vm_page *pg)
152: {
153: if (pg->wire_count == 0) {
154: if (pg->pg_flags & PQ_ACTIVE) {
155: TAILQ_REMOVE(&uvm.page_active, pg, pageq);
156: atomic_clearbits_int(&pg->pg_flags, PQ_ACTIVE);
157: uvmexp.active--;
158: }
159: if (pg->pg_flags & PQ_INACTIVE) {
160: if (pg->pg_flags & PQ_SWAPBACKED)
161: TAILQ_REMOVE(&uvm.page_inactive_swp, pg, pageq);
162: else
163: TAILQ_REMOVE(&uvm.page_inactive_obj, pg, pageq);
164: atomic_clearbits_int(&pg->pg_flags, PQ_INACTIVE);
165: uvmexp.inactive--;
166: }
167: uvmexp.wired++;
168: }
169: pg->wire_count++;
170: }
171:
172: /*
173: * uvm_pageunwire: unwire the page.
174: *
175: * => activate if wire count goes to zero.
176: * => caller must lock page queues
177: */
178:
179: PAGE_INLINE void
180: uvm_pageunwire(struct vm_page *pg)
181: {
182: pg->wire_count--;
183: if (pg->wire_count == 0) {
184: TAILQ_INSERT_TAIL(&uvm.page_active, pg, pageq);
185: uvmexp.active++;
186: atomic_setbits_int(&pg->pg_flags, PQ_ACTIVE);
187: uvmexp.wired--;
188: }
189: }
190:
191: /*
192: * uvm_pagedeactivate: deactivate page -- no pmaps have access to page
193: *
194: * => caller must lock page queues
195: * => caller must check to make sure page is not wired
196: * => object that page belongs to must be locked (so we can adjust pg->flags)
197: */
198:
199: PAGE_INLINE void
200: uvm_pagedeactivate(struct vm_page *pg)
201: {
202: if (pg->pg_flags & PQ_ACTIVE) {
203: TAILQ_REMOVE(&uvm.page_active, pg, pageq);
204: atomic_clearbits_int(&pg->pg_flags, PQ_ACTIVE);
205: uvmexp.active--;
206: }
207: if ((pg->pg_flags & PQ_INACTIVE) == 0) {
208: KASSERT(pg->wire_count == 0);
209: if (pg->pg_flags & PQ_SWAPBACKED)
210: TAILQ_INSERT_TAIL(&uvm.page_inactive_swp, pg, pageq);
211: else
212: TAILQ_INSERT_TAIL(&uvm.page_inactive_obj, pg, pageq);
213: atomic_setbits_int(&pg->pg_flags, PQ_INACTIVE);
214: uvmexp.inactive++;
215: pmap_clear_reference(pg);
216: /*
217: * update the "clean" bit. this isn't 100%
218: * accurate, and doesn't have to be. we'll
219: * re-sync it after we zap all mappings when
220: * scanning the inactive list.
221: */
222: if ((pg->pg_flags & PG_CLEAN) != 0 &&
223: pmap_is_modified(pg))
224: atomic_clearbits_int(&pg->pg_flags, PG_CLEAN);
225: }
226: }
227:
228: /*
229: * uvm_pageactivate: activate page
230: *
231: * => caller must lock page queues
232: */
233:
234: PAGE_INLINE void
235: uvm_pageactivate(struct vm_page *pg)
236: {
237: if (pg->pg_flags & PQ_INACTIVE) {
238: if (pg->pg_flags & PQ_SWAPBACKED)
239: TAILQ_REMOVE(&uvm.page_inactive_swp, pg, pageq);
240: else
241: TAILQ_REMOVE(&uvm.page_inactive_obj, pg, pageq);
242: atomic_clearbits_int(&pg->pg_flags, PQ_INACTIVE);
243: uvmexp.inactive--;
244: }
245: if (pg->wire_count == 0) {
246:
247: /*
248: * if page is already active, remove it from list so we
249: * can put it at tail. if it wasn't active, then mark
250: * it active and bump active count
251: */
252: if (pg->pg_flags & PQ_ACTIVE)
253: TAILQ_REMOVE(&uvm.page_active, pg, pageq);
254: else {
255: atomic_setbits_int(&pg->pg_flags, PQ_ACTIVE);
256: uvmexp.active++;
257: }
258:
259: TAILQ_INSERT_TAIL(&uvm.page_active, pg, pageq);
260: }
261: }
262:
263: /*
264: * uvm_pagezero: zero fill a page
265: *
266: * => if page is part of an object then the object should be locked
267: * to protect pg->flags.
268: */
269:
270: PAGE_INLINE void
271: uvm_pagezero(struct vm_page *pg)
272: {
273: atomic_clearbits_int(&pg->pg_flags, PG_CLEAN);
274: pmap_zero_page(pg);
275: }
276:
277: /*
278: * uvm_pagecopy: copy a page
279: *
280: * => if page is part of an object then the object should be locked
281: * to protect pg->flags.
282: */
283:
284: PAGE_INLINE void
285: uvm_pagecopy(struct vm_page *src, struct vm_page *dst)
286: {
287: atomic_clearbits_int(&dst->pg_flags, PG_CLEAN);
288: pmap_copy_page(src, dst);
289: }
290:
291: /*
292: * uvm_page_lookup_freelist: look up the free list for the specified page
293: */
294:
295: PAGE_INLINE int
296: uvm_page_lookup_freelist(struct vm_page *pg)
297: {
298: int lcv;
299:
300: lcv = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), NULL);
301: KASSERT(lcv != -1);
302: return (vm_physmem[lcv].free_list);
303: }
304:
305: #endif /* defined(UVM_PAGE_INLINE) || defined(UVM_PAGE) */
306:
307: #endif /* _UVM_UVM_PAGE_I_H_ */
CVSweb