Commit | Line | Data |
---|---|---|
984263bc | 1 | /* |
9de48ead | 2 | * Copyright (c) 2019 The DragonFly Project. All rights reserved. |
984263bc MD |
3 | * Copyright (c) 1991, 1993 |
4 | * The Regents of the University of California. All rights reserved. | |
5 | * | |
6 | * This code is derived from software contributed to Berkeley by | |
7 | * The Mach Operating System project at Carnegie-Mellon University. | |
8 | * | |
9de48ead MD |
9 | * This code is derived from software contributed to The DragonFly Project |
10 | * by Matthew Dillon <dillon@backplane.com> | |
11 | * | |
984263bc MD |
12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | |
15 | * 1. Redistributions of source code must retain the above copyright | |
16 | * notice, this list of conditions and the following disclaimer. | |
17 | * 2. Redistributions in binary form must reproduce the above copyright | |
18 | * notice, this list of conditions and the following disclaimer in the | |
19 | * documentation and/or other materials provided with the distribution. | |
c66c7e2f | 20 | * 3. Neither the name of the University nor the names of its contributors |
984263bc MD |
21 | * may be used to endorse or promote products derived from this software |
22 | * without specific prior written permission. | |
23 | * | |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
34 | * SUCH DAMAGE. | |
35 | * | |
36 | * from: @(#)vm_object.h 8.3 (Berkeley) 1/12/94 | |
37 | * | |
38 | * | |
39 | * Copyright (c) 1987, 1990 Carnegie-Mellon University. | |
40 | * All rights reserved. | |
41 | * | |
42 | * Authors: Avadis Tevanian, Jr., Michael Wayne Young | |
43 | * | |
44 | * Permission to use, copy, modify and distribute this software and | |
45 | * its documentation is hereby granted, provided that both the copyright | |
46 | * notice and this permission notice appear in all copies of the | |
47 | * software, derivative works or modified versions, and any portions | |
48 | * thereof, and that both notices appear in supporting documentation. | |
49 | * | |
50 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |
51 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND | |
52 | * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
53 | * | |
54 | * Carnegie Mellon requests users of this software to return to | |
55 | * | |
56 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
57 | * School of Computer Science | |
58 | * Carnegie Mellon University | |
59 | * Pittsburgh PA 15213-3890 | |
60 | * | |
61 | * any improvements or extensions that they make and grant Carnegie the | |
62 | * rights to redistribute these changes. | |
63 | * | |
64 | * $FreeBSD: src/sys/vm/vm_object.h,v 1.63.2.3 2003/05/26 19:17:56 alc Exp $ | |
65 | */ | |
66 | ||
67 | /* | |
68 | * Virtual memory object module definitions. | |
69 | */ | |
70 | ||
1bd40720 MD |
71 | #ifndef _VM_VM_OBJECT_H_ |
72 | #define _VM_VM_OBJECT_H_ | |
984263bc | 73 | |
1bd40720 MD |
74 | #ifndef _SYS_TYPES_H_ |
75 | #include <sys/types.h> | |
76 | #endif | |
77 | #if defined(_KERNEL) && !defined(_SYS_SYSTM_H_) | |
78 | #include <sys/systm.h> | |
79 | #endif | |
80 | #ifndef _SYS_QUEUE_H_ | |
984263bc | 81 | #include <sys/queue.h> |
1bd40720 | 82 | #endif |
96adc753 MD |
83 | #ifndef _SYS_TREE_H_ |
84 | #include <sys/tree.h> | |
85 | #endif | |
2de4f77e MD |
86 | #ifndef _SYS_THREAD_H_ |
87 | #include <sys/thread.h> | |
88 | #endif | |
921c891e MD |
89 | #ifndef _MACHINE_PMAP_H_ |
90 | #include <machine/pmap.h> | |
91 | #endif | |
3b2f3463 | 92 | #ifndef _CPU_ATOMIC_H_ |
984263bc | 93 | #include <machine/atomic.h> |
921c891e | 94 | #endif |
1bd40720 MD |
95 | #ifndef _VM_VM_H_ |
96 | #include <vm/vm.h> | |
97 | #endif | |
1f804340 MD |
98 | #ifndef _VM_VM_PAGE_H_ |
99 | #include <vm/vm_page.h> | |
100 | #endif | |
e32ad78d | 101 | |
c9958a5a MD |
102 | #ifdef _KERNEL |
103 | ||
00db03f1 MD |
104 | #ifndef _SYS_REFCOUNT_H_ |
105 | #include <sys/refcount.h> | |
106 | #endif | |
107 | ||
1bd40720 MD |
108 | #endif |
109 | ||
96adc753 MD |
110 | struct swblock; |
111 | struct swblock_rb_tree; | |
112 | int rb_swblock_compare(struct swblock *, struct swblock *); | |
113 | ||
114 | RB_PROTOTYPE2(swblock_rb_tree, swblock, swb_entry, rb_swblock_compare, | |
115 | vm_pindex_t); | |
8492a2fe | 116 | RB_HEAD(swblock_rb_tree, swblock); |
96adc753 | 117 | |
d1060ff0 HP |
118 | enum obj_type { |
119 | OBJT_DEFAULT, | |
120 | OBJT_SWAP, /* object backed by swap blocks */ | |
121 | OBJT_VNODE, /* object backed by file pages (vnode) */ | |
122 | OBJT_DEVICE, /* object backed by device pages */ | |
f2c2051e | 123 | OBJT_MGTDEVICE, |
d1060ff0 | 124 | OBJT_PHYS, /* object backed by physical pages */ |
00a3fdca MD |
125 | OBJT_DEAD, /* dead object */ |
126 | OBJT_MARKER /* marker object */ | |
d1060ff0 | 127 | }; |
984263bc MD |
128 | typedef u_char objtype_t; |
129 | ||
377d4740 | 130 | /* |
501747bf | 131 | * A VM object which represents an arbitrarily sized data store. |
2de4f77e | 132 | * |
8492a2fe MD |
133 | * vm_objects are soft-locked with their token, meaning that any |
134 | * blocking can allow other threads to squeeze in some work. | |
377d4740 | 135 | */ |
984263bc | 136 | struct vm_object { |
67e7cb85 | 137 | struct lwkt_token token; /* everything else */ |
567a6398 | 138 | struct lock backing_lk; /* lock for backing_list only */ |
5b329e62 MD |
139 | TAILQ_ENTRY(vm_object) object_entry; |
140 | TAILQ_HEAD(, vm_map_backing) backing_list; | |
8492a2fe MD |
141 | struct vm_page_rb_tree rb_memq; /* resident pages */ |
142 | int generation; /* generation ID */ | |
143 | vm_pindex_t size; /* Object size */ | |
144 | int ref_count; | |
145 | vm_memattr_t memattr; /* default memory attribute for pages */ | |
146 | objtype_t type; /* type of pager */ | |
147 | u_short flags; /* see below */ | |
148 | u_short pg_color; /* color of first page in obj */ | |
149 | u_int paging_in_progress; /* Activity in progress */ | |
150 | long resident_page_count; /* number of resident pages */ | |
5b329e62 | 151 | TAILQ_ENTRY(vm_object) pager_object_entry; /* optional use by pager */ |
8492a2fe MD |
152 | void *handle; /* control handle: vp, etc */ |
153 | int hold_count; /* count prevents destruction */ | |
e32ad78d | 154 | |
cb443cbb VS |
155 | #if defined(DEBUG_LOCKS) |
156 | /* | |
157 | * Record threads holding a vm_object | |
158 | */ | |
159 | ||
160 | #define VMOBJ_DEBUG_ARRAY_SIZE (32) | |
8492a2fe MD |
161 | char debug_hold_thrs[VMOBJ_DEBUG_ARRAY_SIZE][64]; |
162 | const char *debug_hold_file[VMOBJ_DEBUG_ARRAY_SIZE]; | |
163 | int debug_hold_line[VMOBJ_DEBUG_ARRAY_SIZE]; | |
164 | int debug_index; | |
cb443cbb VS |
165 | #endif |
166 | ||
984263bc | 167 | union { |
984263bc MD |
168 | /* |
169 | * Device pager | |
170 | * | |
171 | * devp_pglist - list of allocated pages | |
172 | */ | |
173 | struct { | |
174 | TAILQ_HEAD(, vm_page) devp_pglist; | |
f2c2051e JH |
175 | struct cdev_pager_ops *ops; |
176 | struct cdev *dev; | |
984263bc | 177 | } devp; |
984263bc | 178 | } un_pager; |
96adc753 MD |
179 | |
180 | /* | |
181 | * OBJT_SWAP and OBJT_VNODE VM objects may have swap backing | |
182 | * store. For vnodes the swap backing store acts as a fast | |
183 | * data cache but the vnode contains the official data. | |
184 | */ | |
8492a2fe MD |
185 | struct swblock_rb_tree swblock_root; |
186 | long swblock_count; | |
187 | struct md_object md; /* machine specific (typ pmap) */ | |
984263bc MD |
188 | }; |
189 | ||
190 | /* | |
191 | * Flags | |
ce94514e | 192 | * |
46b71cbe MD |
193 | * OBJ_ONEMAPPING - Only applies to DEFAULT and SWAP objects. It may be |
194 | * gratuitously re-cleared in other cases but will already | |
195 | * be clear in those cases. It might not be set on other | |
196 | * object types (particularly OBJT_VNODE). | |
197 | * | |
641f3b0a | 198 | * This flag indicates that any given page index within the |
9de48ead MD |
199 | * object is only mapped to at most one vm_map_entry. |
200 | * | |
201 | * WARNING! An obj->refs of 1 does NOT allow you to | |
202 | * re-set this bit because the object might be part of | |
203 | * a shared chain of vm_map_backing structures. | |
641f3b0a | 204 | * |
46b71cbe MD |
205 | * OBJ_NOPAGEIN - vn and tmpfs set this flag, indicating to swapoff |
206 | * that the objects aren't intended to have any vm_page's, | |
207 | * only swap blocks. vn and tmpfs don't know how to deal | |
208 | * with any actual pages. | |
984263bc | 209 | */ |
9de48ead MD |
210 | #define OBJ_UNUSED0001 0x0001 |
211 | #define OBJ_UNUSED0002 0x0002 | |
984263bc MD |
212 | #define OBJ_ACTIVE 0x0004 /* active objects */ |
213 | #define OBJ_DEAD 0x0008 /* dead objects (during rundown) */ | |
214 | #define OBJ_NOSPLIT 0x0010 /* dont split this object */ | |
46b71cbe | 215 | #define OBJ_NOPAGEIN 0x0040 /* special OBJT_SWAP */ |
984263bc MD |
216 | #define OBJ_WRITEABLE 0x0080 /* object has been made writable */ |
217 | #define OBJ_MIGHTBEDIRTY 0x0100 /* object might be dirty */ | |
218 | #define OBJ_CLEANING 0x0200 | |
9e12ff11 | 219 | #define OBJ_DEADWNT 0x1000 /* waiting because object is dead */ |
641f3b0a | 220 | #define OBJ_ONEMAPPING 0x2000 |
2bc7505b | 221 | #define OBJ_NOMSYNC 0x4000 /* disable msync() system call */ |
984263bc MD |
222 | |
223 | #define IDX_TO_OFF(idx) (((vm_ooffset_t)(idx)) << PAGE_SHIFT) | |
224 | #define OFF_TO_IDX(off) ((vm_pindex_t)(((vm_ooffset_t)(off)) >> PAGE_SHIFT)) | |
225 | ||
562ffbba | 226 | #define VMOBJ_HSIZE 256 |
15553805 | 227 | #define VMOBJ_HMASK (VMOBJ_HSIZE - 1) |
15553805 | 228 | |
984263bc MD |
229 | #ifdef _KERNEL |
230 | ||
cdf89dcf SW |
231 | #define OBJPC_SYNC 0x0001 /* sync I/O */ |
232 | #define OBJPC_INVAL 0x0002 /* invalidate */ | |
233 | #define OBJPC_NOSYNC 0x0004 /* skip if PG_NOSYNC */ | |
234 | #define OBJPC_IGNORE_CLEANCHK 0x0008 | |
235 | #define OBJPC_CLUSTER_OK 0x0010 /* used only by vnode pager */ | |
236 | #define OBJPC_TRY_TO_CACHE 0x0020 /* typically used only in pageout path */ | |
237 | #define OBJPC_ALLOW_ACTIVE 0x0040 /* dito */ | |
984263bc | 238 | |
9de48ead | 239 | #if 0 |
e806bedd MD |
240 | /* |
241 | * Used to chain vm_object deallocations | |
242 | */ | |
243 | struct vm_object_dealloc_list { | |
244 | struct vm_object_dealloc_list *next; | |
245 | vm_object_t object; | |
246 | }; | |
9de48ead | 247 | #endif |
e806bedd | 248 | |
984263bc MD |
249 | TAILQ_HEAD(object_q, vm_object); |
250 | ||
fde6be6a MD |
251 | struct vm_object_hash { |
252 | struct object_q list; | |
253 | struct lwkt_token token; | |
254 | } __cachealign; | |
7b00fbb4 | 255 | |
fde6be6a | 256 | extern struct vm_object_hash vm_object_hash[VMOBJ_HSIZE]; |
984263bc MD |
257 | |
258 | /* lock for object list and count */ | |
259 | ||
712b6620 | 260 | extern struct vm_object *kernel_object; /* the single kernel object */ |
ce94514e | 261 | extern int vm_shared_fault; |
984263bc MD |
262 | |
263 | #endif /* _KERNEL */ | |
264 | ||
265 | #ifdef _KERNEL | |
266 | ||
9a0c03af FT |
267 | #define VM_OBJECT_LOCK(object) vm_object_hold(object) |
268 | #define VM_OBJECT_UNLOCK(object) vm_object_drop(object) | |
269 | ||
984263bc MD |
270 | static __inline void |
271 | vm_object_set_flag(vm_object_t object, u_int bits) | |
272 | { | |
273 | atomic_set_short(&object->flags, bits); | |
274 | } | |
275 | ||
276 | static __inline void | |
277 | vm_object_clear_flag(vm_object_t object, u_int bits) | |
278 | { | |
279 | atomic_clear_short(&object->flags, bits); | |
280 | } | |
281 | ||
282 | static __inline void | |
00db03f1 | 283 | vm_object_pip_add(vm_object_t object, u_int i) |
984263bc | 284 | { |
ad23467e | 285 | refcount_acquire_n(&object->paging_in_progress, i); |
984263bc MD |
286 | } |
287 | ||
288 | static __inline void | |
00db03f1 | 289 | vm_object_pip_wakeup_n(vm_object_t object, u_int i) |
984263bc | 290 | { |
00db03f1 | 291 | refcount_release_wakeup_n(&object->paging_in_progress, i); |
984263bc MD |
292 | } |
293 | ||
294 | static __inline void | |
e1c14c82 | 295 | vm_object_pip_wakeup(vm_object_t object) |
984263bc | 296 | { |
00db03f1 | 297 | vm_object_pip_wakeup_n(object, 1); |
984263bc MD |
298 | } |
299 | ||
300 | static __inline void | |
301 | vm_object_pip_wait(vm_object_t object, char *waitid) | |
302 | { | |
00db03f1 | 303 | refcount_wait(&object->paging_in_progress, waitid); |
984263bc MD |
304 | } |
305 | ||
e42208e6 SW |
306 | static __inline lwkt_token_t |
307 | vm_object_token(vm_object_t obj) | |
308 | { | |
c9958a5a | 309 | return (&obj->token); |
b4460ab3 VS |
310 | } |
311 | ||
aecf2182 | 312 | vm_object_t vm_object_allocate (objtype_t, vm_pindex_t); |
a2ee730d | 313 | vm_object_t vm_object_allocate_hold (objtype_t, vm_pindex_t); |
a7c16d7a | 314 | void _vm_object_allocate (objtype_t, vm_pindex_t, vm_object_t, const char *); |
1388df65 | 315 | boolean_t vm_object_coalesce (vm_object_t, vm_pindex_t, vm_size_t, vm_size_t); |
1c024bc6 | 316 | vm_object_t vm_object_collapse (vm_object_t, vm_object_t); |
1388df65 | 317 | void vm_object_terminate (vm_object_t); |
1388df65 | 318 | void vm_object_set_writeable_dirty (vm_object_t); |
a17c6c05 | 319 | void vm_object_init(vm_object_t, vm_pindex_t); |
4f077c8a | 320 | void vm_object_init1 (void); |
99ebfb7c | 321 | void vm_object_page_clean (vm_object_t, vm_pindex_t, vm_pindex_t, int); |
1388df65 RG |
322 | void vm_object_page_remove (vm_object_t, vm_pindex_t, vm_pindex_t, boolean_t); |
323 | void vm_object_pmap_copy (vm_object_t, vm_pindex_t, vm_pindex_t); | |
76f1911e | 324 | void vm_object_madvise (vm_object_t, vm_pindex_t, vm_pindex_t, int); |
1388df65 | 325 | void vm_object_init2 (void); |
b12defdc | 326 | vm_page_t vm_fault_object_page(vm_object_t, vm_ooffset_t, |
501747bf | 327 | vm_prot_t, int, int *, int *); |
a31129d8 | 328 | void vm_object_lock_swap(void); |
e32ad78d | 329 | void vm_object_lock(vm_object_t); |
54341a3b | 330 | void vm_object_lock_shared(vm_object_t); |
e32ad78d | 331 | void vm_object_unlock(vm_object_t); |
18a4c8dc | 332 | |
15553805 MD |
333 | #if defined(DEBUG_LOCKS) |
334 | ||
335 | #define VMOBJDEBUG(x) debug ## x | |
336 | #define VMOBJDBARGS , char *file, int line | |
337 | #define VMOBJDBFWD , file, line | |
338 | ||
339 | #define vm_object_hold(obj) \ | |
340 | debugvm_object_hold(obj, __FILE__, __LINE__) | |
341 | #define vm_object_hold_try(obj) \ | |
342 | debugvm_object_hold_try(obj, __FILE__, __LINE__) | |
343 | #define vm_object_hold_shared(obj) \ | |
344 | debugvm_object_hold_shared(obj, __FILE__, __LINE__) | |
345 | #define vm_object_drop(obj) \ | |
346 | debugvm_object_drop(obj, __FILE__, __LINE__) | |
347 | #define vm_object_reference_quick(obj) \ | |
348 | debugvm_object_reference_quick(obj, __FILE__, __LINE__) | |
349 | #define vm_object_reference_locked(obj) \ | |
350 | debugvm_object_reference_locked(obj, __FILE__, __LINE__) | |
9de48ead | 351 | #if 0 |
641f3b0a MD |
352 | #define vm_object_reference_locked_chain_held(obj) \ |
353 | debugvm_object_reference_locked_chain_held( \ | |
354 | obj, __FILE__, __LINE__) | |
9de48ead | 355 | #endif |
15553805 MD |
356 | #define vm_object_deallocate(obj) \ |
357 | debugvm_object_deallocate(obj, __FILE__, __LINE__) | |
358 | #define vm_object_deallocate_locked(obj) \ | |
359 | debugvm_object_deallocate_locked(obj, __FILE__, __LINE__) | |
360 | ||
18a4c8dc | 361 | #else |
15553805 MD |
362 | |
363 | #define VMOBJDEBUG(x) x | |
364 | #define VMOBJDBARGS | |
365 | #define VMOBJDBFWD | |
366 | ||
18a4c8dc | 367 | #endif |
15553805 MD |
368 | |
369 | void VMOBJDEBUG(vm_object_hold)(vm_object_t object VMOBJDBARGS); | |
370 | int VMOBJDEBUG(vm_object_hold_try)(vm_object_t object VMOBJDBARGS); | |
371 | void VMOBJDEBUG(vm_object_hold_shared)(vm_object_t object VMOBJDBARGS); | |
372 | void VMOBJDEBUG(vm_object_drop)(vm_object_t object VMOBJDBARGS); | |
373 | void VMOBJDEBUG(vm_object_reference_quick)(vm_object_t object VMOBJDBARGS); | |
374 | void VMOBJDEBUG(vm_object_reference_locked)(vm_object_t object VMOBJDBARGS); | |
9de48ead | 375 | #if 0 |
641f3b0a MD |
376 | void VMOBJDEBUG(vm_object_reference_locked_chain_held)( |
377 | vm_object_t object VMOBJDBARGS); | |
9de48ead | 378 | #endif |
15553805 MD |
379 | void VMOBJDEBUG(vm_object_deallocate)(vm_object_t object VMOBJDBARGS); |
380 | void VMOBJDEBUG(vm_object_deallocate_locked)(vm_object_t object VMOBJDBARGS); | |
381 | ||
501747bf MD |
382 | void vm_object_upgrade(vm_object_t); |
383 | void vm_object_downgrade(vm_object_t); | |
9de48ead | 384 | int vm_quickcolor(void); |
18a4c8dc | 385 | |
984263bc MD |
386 | #endif /* _KERNEL */ |
387 | ||
1bd40720 | 388 | #endif /* _VM_VM_OBJECT_H_ */ |