Add an optional pglist argument to uvm_obj_wirepages, to be filled with the list of pages that were wired.diff -r1.121 -r1.122 src/sys/kern/sysv_shm.c
(christos)
--- src/sys/kern/sysv_shm.c 2011/07/30 06:19:02 1.121
+++ src/sys/kern/sysv_shm.c 2011/08/27 09:11:52 1.122
@@ -1,1093 +1,1093 @@ | @@ -1,1093 +1,1093 @@ | |||
1 | /* $NetBSD: sysv_shm.c,v 1.121 2011/07/30 06:19:02 uebayasi Exp $ */ | 1 | /* $NetBSD: sysv_shm.c,v 1.122 2011/08/27 09:11:52 christos Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1999, 2007 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1999, 2007 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | |
9 | * NASA Ames Research Center, and by Mindaugas Rasiukevicius. | 9 | * NASA Ames Research Center, and by Mindaugas Rasiukevicius. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions and the following disclaimer. | 15 | * notice, this list of conditions and the following disclaimer. | |
16 | * 2. Redistributions in binary form must reproduce the above copyright | 16 | * 2. Redistributions in binary form must reproduce the above copyright | |
17 | * notice, this list of conditions and the following disclaimer in the | 17 | * notice, this list of conditions and the following disclaimer in the | |
18 | * documentation and/or other materials provided with the distribution. | 18 | * documentation and/or other materials provided with the distribution. | |
19 | * | 19 | * | |
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | /* | 33 | /* | |
34 | * Copyright (c) 1994 Adam Glass and Charles M. Hannum. All rights reserved. | 34 | * Copyright (c) 1994 Adam Glass and Charles M. Hannum. All rights reserved. | |
35 | * | 35 | * | |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without | |
37 | * modification, are permitted provided that the following conditions | 37 | * modification, are permitted provided that the following conditions | |
38 | * are met: | 38 | * are met: | |
39 | * 1. Redistributions of source code must retain the above copyright | 39 | * 1. Redistributions of source code must retain the above copyright | |
40 | * notice, this list of conditions and the following disclaimer. | 40 | * notice, this list of conditions and the following disclaimer. | |
41 | * 2. Redistributions in binary form must reproduce the above copyright | 41 | * 2. Redistributions in binary form must reproduce the above copyright | |
42 | * notice, this list of conditions and the following disclaimer in the | 42 | * notice, this list of conditions and the following disclaimer in the | |
43 | * documentation and/or other materials provided with the distribution. | 43 | * documentation and/or other materials provided with the distribution. | |
44 | * 3. All advertising materials mentioning features or use of this software | 44 | * 3. All advertising materials mentioning features or use of this software | |
45 | * must display the following acknowledgement: | 45 | * must display the following acknowledgement: | |
46 | * This product includes software developed by Adam Glass and Charles M. | 46 | * This product includes software developed by Adam Glass and Charles M. | |
47 | * Hannum. | 47 | * Hannum. | |
48 | * 4. The names of the authors may not be used to endorse or promote products | 48 | * 4. The names of the authors may not be used to endorse or promote products | |
49 | * derived from this software without specific prior written permission. | 49 | * derived from this software without specific prior written permission. | |
50 | * | 50 | * | |
51 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR | 51 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR | |
52 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 52 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
53 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 53 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
54 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, | 54 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
55 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 55 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
56 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 56 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
60 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 60 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
61 | */ | 61 | */ | |
62 | 62 | |||
63 | #include <sys/cdefs.h> | 63 | #include <sys/cdefs.h> | |
64 | __KERNEL_RCSID(0, "$NetBSD: sysv_shm.c,v 1.121 2011/07/30 06:19:02 uebayasi Exp $"); | 64 | __KERNEL_RCSID(0, "$NetBSD: sysv_shm.c,v 1.122 2011/08/27 09:11:52 christos Exp $"); | |
65 | 65 | |||
66 | #define SYSVSHM | 66 | #define SYSVSHM | |
67 | 67 | |||
68 | #include <sys/param.h> | 68 | #include <sys/param.h> | |
69 | #include <sys/kernel.h> | 69 | #include <sys/kernel.h> | |
70 | #include <sys/kmem.h> | 70 | #include <sys/kmem.h> | |
71 | #include <sys/shm.h> | 71 | #include <sys/shm.h> | |
72 | #include <sys/mutex.h> | 72 | #include <sys/mutex.h> | |
73 | #include <sys/mman.h> | 73 | #include <sys/mman.h> | |
74 | #include <sys/stat.h> | 74 | #include <sys/stat.h> | |
75 | #include <sys/sysctl.h> | 75 | #include <sys/sysctl.h> | |
76 | #include <sys/mount.h> /* XXX for <sys/syscallargs.h> */ | 76 | #include <sys/mount.h> /* XXX for <sys/syscallargs.h> */ | |
77 | #include <sys/syscallargs.h> | 77 | #include <sys/syscallargs.h> | |
78 | #include <sys/queue.h> | 78 | #include <sys/queue.h> | |
79 | #include <sys/kauth.h> | 79 | #include <sys/kauth.h> | |
80 | 80 | |||
81 | #include <uvm/uvm_extern.h> | 81 | #include <uvm/uvm_extern.h> | |
82 | #include <uvm/uvm_object.h> | 82 | #include <uvm/uvm_object.h> | |
83 | 83 | |||
84 | struct shmmap_entry { | 84 | struct shmmap_entry { | |
85 | SLIST_ENTRY(shmmap_entry) next; | 85 | SLIST_ENTRY(shmmap_entry) next; | |
86 | vaddr_t va; | 86 | vaddr_t va; | |
87 | int shmid; | 87 | int shmid; | |
88 | }; | 88 | }; | |
89 | 89 | |||
90 | int shm_nused __cacheline_aligned; | 90 | int shm_nused __cacheline_aligned; | |
91 | struct shmid_ds * shmsegs __read_mostly; | 91 | struct shmid_ds * shmsegs __read_mostly; | |
92 | 92 | |||
93 | static kmutex_t shm_lock __cacheline_aligned; | 93 | static kmutex_t shm_lock __cacheline_aligned; | |
94 | static kcondvar_t * shm_cv __cacheline_aligned; | 94 | static kcondvar_t * shm_cv __cacheline_aligned; | |
95 | static int shm_last_free __cacheline_aligned; | 95 | static int shm_last_free __cacheline_aligned; | |
96 | static size_t shm_committed __cacheline_aligned; | 96 | static size_t shm_committed __cacheline_aligned; | |
97 | static int shm_use_phys __read_mostly; | 97 | static int shm_use_phys __read_mostly; | |
98 | 98 | |||
99 | static kcondvar_t shm_realloc_cv; | 99 | static kcondvar_t shm_realloc_cv; | |
100 | static bool shm_realloc_state; | 100 | static bool shm_realloc_state; | |
101 | static u_int shm_realloc_disable; | 101 | static u_int shm_realloc_disable; | |
102 | 102 | |||
103 | struct shmmap_state { | 103 | struct shmmap_state { | |
104 | unsigned int nitems; | 104 | unsigned int nitems; | |
105 | unsigned int nrefs; | 105 | unsigned int nrefs; | |
106 | SLIST_HEAD(, shmmap_entry) entries; | 106 | SLIST_HEAD(, shmmap_entry) entries; | |
107 | }; | 107 | }; | |
108 | 108 | |||
109 | #ifdef SHMDEBUG | 109 | #ifdef SHMDEBUG | |
110 | #define SHMPRINTF(a) printf a | 110 | #define SHMPRINTF(a) printf a | |
111 | #else | 111 | #else | |
112 | #define SHMPRINTF(a) | 112 | #define SHMPRINTF(a) | |
113 | #endif | 113 | #endif | |
114 | 114 | |||
115 | static int shmrealloc(int); | 115 | static int shmrealloc(int); | |
116 | 116 | |||
117 | /* | 117 | /* | |
118 | * Find the shared memory segment by the identifier. | 118 | * Find the shared memory segment by the identifier. | |
119 | * => must be called with shm_lock held; | 119 | * => must be called with shm_lock held; | |
120 | */ | 120 | */ | |
121 | static struct shmid_ds * | 121 | static struct shmid_ds * | |
122 | shm_find_segment_by_shmid(int shmid) | 122 | shm_find_segment_by_shmid(int shmid) | |
123 | { | 123 | { | |
124 | int segnum; | 124 | int segnum; | |
125 | struct shmid_ds *shmseg; | 125 | struct shmid_ds *shmseg; | |
126 | 126 | |||
127 | KASSERT(mutex_owned(&shm_lock)); | 127 | KASSERT(mutex_owned(&shm_lock)); | |
128 | 128 | |||
129 | segnum = IPCID_TO_IX(shmid); | 129 | segnum = IPCID_TO_IX(shmid); | |
130 | if (segnum < 0 || segnum >= shminfo.shmmni) | 130 | if (segnum < 0 || segnum >= shminfo.shmmni) | |
131 | return NULL; | 131 | return NULL; | |
132 | shmseg = &shmsegs[segnum]; | 132 | shmseg = &shmsegs[segnum]; | |
133 | if ((shmseg->shm_perm.mode & SHMSEG_ALLOCATED) == 0) | 133 | if ((shmseg->shm_perm.mode & SHMSEG_ALLOCATED) == 0) | |
134 | return NULL; | 134 | return NULL; | |
135 | if ((shmseg->shm_perm.mode & | 135 | if ((shmseg->shm_perm.mode & | |
136 | (SHMSEG_REMOVED|SHMSEG_RMLINGER)) == SHMSEG_REMOVED) | 136 | (SHMSEG_REMOVED|SHMSEG_RMLINGER)) == SHMSEG_REMOVED) | |
137 | return NULL; | 137 | return NULL; | |
138 | if (shmseg->shm_perm._seq != IPCID_TO_SEQ(shmid)) | 138 | if (shmseg->shm_perm._seq != IPCID_TO_SEQ(shmid)) | |
139 | return NULL; | 139 | return NULL; | |
140 | 140 | |||
141 | return shmseg; | 141 | return shmseg; | |
142 | } | 142 | } | |
143 | 143 | |||
144 | /* | 144 | /* | |
145 | * Free memory segment. | 145 | * Free memory segment. | |
146 | * => must be called with shm_lock held; | 146 | * => must be called with shm_lock held; | |
147 | */ | 147 | */ | |
148 | static void | 148 | static void | |
149 | shm_free_segment(int segnum) | 149 | shm_free_segment(int segnum) | |
150 | { | 150 | { | |
151 | struct shmid_ds *shmseg; | 151 | struct shmid_ds *shmseg; | |
152 | size_t size; | 152 | size_t size; | |
153 | bool wanted; | 153 | bool wanted; | |
154 | 154 | |||
155 | KASSERT(mutex_owned(&shm_lock)); | 155 | KASSERT(mutex_owned(&shm_lock)); | |
156 | 156 | |||
157 | shmseg = &shmsegs[segnum]; | 157 | shmseg = &shmsegs[segnum]; | |
158 | SHMPRINTF(("shm freeing key 0x%lx seq 0x%x\n", | 158 | SHMPRINTF(("shm freeing key 0x%lx seq 0x%x\n", | |
159 | shmseg->shm_perm._key, shmseg->shm_perm._seq)); | 159 | shmseg->shm_perm._key, shmseg->shm_perm._seq)); | |
160 | 160 | |||
161 | size = (shmseg->shm_segsz + PGOFSET) & ~PGOFSET; | 161 | size = (shmseg->shm_segsz + PGOFSET) & ~PGOFSET; | |
162 | wanted = (shmseg->shm_perm.mode & SHMSEG_WANTED); | 162 | wanted = (shmseg->shm_perm.mode & SHMSEG_WANTED); | |
163 | 163 | |||
164 | shmseg->_shm_internal = NULL; | 164 | shmseg->_shm_internal = NULL; | |
165 | shm_committed -= btoc(size); | 165 | shm_committed -= btoc(size); | |
166 | shm_nused--; | 166 | shm_nused--; | |
167 | shmseg->shm_perm.mode = SHMSEG_FREE; | 167 | shmseg->shm_perm.mode = SHMSEG_FREE; | |
168 | shm_last_free = segnum; | 168 | shm_last_free = segnum; | |
169 | if (wanted == true) | 169 | if (wanted == true) | |
170 | cv_broadcast(&shm_cv[segnum]); | 170 | cv_broadcast(&shm_cv[segnum]); | |
171 | } | 171 | } | |
172 | 172 | |||
173 | /* | 173 | /* | |
174 | * Delete entry from the shm map. | 174 | * Delete entry from the shm map. | |
175 | * => must be called with shm_lock held; | 175 | * => must be called with shm_lock held; | |
176 | */ | 176 | */ | |
177 | static struct uvm_object * | 177 | static struct uvm_object * | |
178 | shm_delete_mapping(struct shmmap_state *shmmap_s, | 178 | shm_delete_mapping(struct shmmap_state *shmmap_s, | |
179 | struct shmmap_entry *shmmap_se) | 179 | struct shmmap_entry *shmmap_se) | |
180 | { | 180 | { | |
181 | struct uvm_object *uobj = NULL; | 181 | struct uvm_object *uobj = NULL; | |
182 | struct shmid_ds *shmseg; | 182 | struct shmid_ds *shmseg; | |
183 | int segnum; | 183 | int segnum; | |
184 | 184 | |||
185 | KASSERT(mutex_owned(&shm_lock)); | 185 | KASSERT(mutex_owned(&shm_lock)); | |
186 | 186 | |||
187 | segnum = IPCID_TO_IX(shmmap_se->shmid); | 187 | segnum = IPCID_TO_IX(shmmap_se->shmid); | |
188 | shmseg = &shmsegs[segnum]; | 188 | shmseg = &shmsegs[segnum]; | |
189 | SLIST_REMOVE(&shmmap_s->entries, shmmap_se, shmmap_entry, next); | 189 | SLIST_REMOVE(&shmmap_s->entries, shmmap_se, shmmap_entry, next); | |
190 | shmmap_s->nitems--; | 190 | shmmap_s->nitems--; | |
191 | shmseg->shm_dtime = time_second; | 191 | shmseg->shm_dtime = time_second; | |
192 | if ((--shmseg->shm_nattch <= 0) && | 192 | if ((--shmseg->shm_nattch <= 0) && | |
193 | (shmseg->shm_perm.mode & SHMSEG_REMOVED)) { | 193 | (shmseg->shm_perm.mode & SHMSEG_REMOVED)) { | |
194 | uobj = shmseg->_shm_internal; | 194 | uobj = shmseg->_shm_internal; | |
195 | shm_free_segment(segnum); | 195 | shm_free_segment(segnum); | |
196 | } | 196 | } | |
197 | 197 | |||
198 | return uobj; | 198 | return uobj; | |
199 | } | 199 | } | |
200 | 200 | |||
201 | /* | 201 | /* | |
202 | * Get a non-shared shm map for that vmspace. Note, that memory | 202 | * Get a non-shared shm map for that vmspace. Note, that memory | |
203 | * allocation might be performed with lock held. | 203 | * allocation might be performed with lock held. | |
204 | */ | 204 | */ | |
205 | static struct shmmap_state * | 205 | static struct shmmap_state * | |
206 | shmmap_getprivate(struct proc *p) | 206 | shmmap_getprivate(struct proc *p) | |
207 | { | 207 | { | |
208 | struct shmmap_state *oshmmap_s, *shmmap_s; | 208 | struct shmmap_state *oshmmap_s, *shmmap_s; | |
209 | struct shmmap_entry *oshmmap_se, *shmmap_se; | 209 | struct shmmap_entry *oshmmap_se, *shmmap_se; | |
210 | 210 | |||
211 | KASSERT(mutex_owned(&shm_lock)); | 211 | KASSERT(mutex_owned(&shm_lock)); | |
212 | 212 | |||
213 | /* 1. A shm map with refcnt = 1, used by ourselves, thus return */ | 213 | /* 1. A shm map with refcnt = 1, used by ourselves, thus return */ | |
214 | oshmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; | 214 | oshmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; | |
215 | if (oshmmap_s && oshmmap_s->nrefs == 1) | 215 | if (oshmmap_s && oshmmap_s->nrefs == 1) | |
216 | return oshmmap_s; | 216 | return oshmmap_s; | |
217 | 217 | |||
218 | /* 2. No shm map preset - create a fresh one */ | 218 | /* 2. No shm map preset - create a fresh one */ | |
219 | shmmap_s = kmem_zalloc(sizeof(struct shmmap_state), KM_SLEEP); | 219 | shmmap_s = kmem_zalloc(sizeof(struct shmmap_state), KM_SLEEP); | |
220 | shmmap_s->nrefs = 1; | 220 | shmmap_s->nrefs = 1; | |
221 | SLIST_INIT(&shmmap_s->entries); | 221 | SLIST_INIT(&shmmap_s->entries); | |
222 | p->p_vmspace->vm_shm = (void *)shmmap_s; | 222 | p->p_vmspace->vm_shm = (void *)shmmap_s; | |
223 | 223 | |||
224 | if (oshmmap_s == NULL) | 224 | if (oshmmap_s == NULL) | |
225 | return shmmap_s; | 225 | return shmmap_s; | |
226 | 226 | |||
227 | SHMPRINTF(("shmmap_getprivate: vm %p split (%d entries), was used by %d\n", | 227 | SHMPRINTF(("shmmap_getprivate: vm %p split (%d entries), was used by %d\n", | |
228 | p->p_vmspace, oshmmap_s->nitems, oshmmap_s->nrefs)); | 228 | p->p_vmspace, oshmmap_s->nitems, oshmmap_s->nrefs)); | |
229 | 229 | |||
230 | /* 3. A shared shm map, copy to a fresh one and adjust refcounts */ | 230 | /* 3. A shared shm map, copy to a fresh one and adjust refcounts */ | |
231 | SLIST_FOREACH(oshmmap_se, &oshmmap_s->entries, next) { | 231 | SLIST_FOREACH(oshmmap_se, &oshmmap_s->entries, next) { | |
232 | shmmap_se = kmem_alloc(sizeof(struct shmmap_entry), KM_SLEEP); | 232 | shmmap_se = kmem_alloc(sizeof(struct shmmap_entry), KM_SLEEP); | |
233 | shmmap_se->va = oshmmap_se->va; | 233 | shmmap_se->va = oshmmap_se->va; | |
234 | shmmap_se->shmid = oshmmap_se->shmid; | 234 | shmmap_se->shmid = oshmmap_se->shmid; | |
235 | SLIST_INSERT_HEAD(&shmmap_s->entries, shmmap_se, next); | 235 | SLIST_INSERT_HEAD(&shmmap_s->entries, shmmap_se, next); | |
236 | } | 236 | } | |
237 | shmmap_s->nitems = oshmmap_s->nitems; | 237 | shmmap_s->nitems = oshmmap_s->nitems; | |
238 | oshmmap_s->nrefs--; | 238 | oshmmap_s->nrefs--; | |
239 | 239 | |||
240 | return shmmap_s; | 240 | return shmmap_s; | |
241 | } | 241 | } | |
242 | 242 | |||
243 | /* | 243 | /* | |
244 | * Lock/unlock the memory. | 244 | * Lock/unlock the memory. | |
245 | * => must be called with shm_lock held; | 245 | * => must be called with shm_lock held; | |
246 | * => called from one place, thus, inline; | 246 | * => called from one place, thus, inline; | |
247 | */ | 247 | */ | |
248 | static inline int | 248 | static inline int | |
249 | shm_memlock(struct lwp *l, struct shmid_ds *shmseg, int shmid, int cmd) | 249 | shm_memlock(struct lwp *l, struct shmid_ds *shmseg, int shmid, int cmd) | |
250 | { | 250 | { | |
251 | struct proc *p = l->l_proc; | 251 | struct proc *p = l->l_proc; | |
252 | struct shmmap_entry *shmmap_se; | 252 | struct shmmap_entry *shmmap_se; | |
253 | struct shmmap_state *shmmap_s; | 253 | struct shmmap_state *shmmap_s; | |
254 | size_t size; | 254 | size_t size; | |
255 | int error; | 255 | int error; | |
256 | 256 | |||
257 | KASSERT(mutex_owned(&shm_lock)); | 257 | KASSERT(mutex_owned(&shm_lock)); | |
258 | shmmap_s = shmmap_getprivate(p); | 258 | shmmap_s = shmmap_getprivate(p); | |
259 | 259 | |||
260 | /* Find our shared memory address by shmid */ | 260 | /* Find our shared memory address by shmid */ | |
261 | SLIST_FOREACH(shmmap_se, &shmmap_s->entries, next) { | 261 | SLIST_FOREACH(shmmap_se, &shmmap_s->entries, next) { | |
262 | if (shmmap_se->shmid != shmid) | 262 | if (shmmap_se->shmid != shmid) | |
263 | continue; | 263 | continue; | |
264 | 264 | |||
265 | size = (shmseg->shm_segsz + PGOFSET) & ~PGOFSET; | 265 | size = (shmseg->shm_segsz + PGOFSET) & ~PGOFSET; | |
266 | 266 | |||
267 | if (cmd == SHM_LOCK && | 267 | if (cmd == SHM_LOCK && | |
268 | (shmseg->shm_perm.mode & SHMSEG_WIRED) == 0) { | 268 | (shmseg->shm_perm.mode & SHMSEG_WIRED) == 0) { | |
269 | /* Wire the object and map, then tag it */ | 269 | /* Wire the object and map, then tag it */ | |
270 | error = uvm_obj_wirepages(shmseg->_shm_internal, | 270 | error = uvm_obj_wirepages(shmseg->_shm_internal, | |
271 | 0, size); | 271 | 0, size, NULL); | |
272 | if (error) | 272 | if (error) | |
273 | return EIO; | 273 | return EIO; | |
274 | error = uvm_map_pageable(&p->p_vmspace->vm_map, | 274 | error = uvm_map_pageable(&p->p_vmspace->vm_map, | |
275 | shmmap_se->va, shmmap_se->va + size, false, 0); | 275 | shmmap_se->va, shmmap_se->va + size, false, 0); | |
276 | if (error) { | 276 | if (error) { | |
277 | uvm_obj_unwirepages(shmseg->_shm_internal, | 277 | uvm_obj_unwirepages(shmseg->_shm_internal, | |
278 | 0, size); | 278 | 0, size); | |
279 | if (error == EFAULT) | 279 | if (error == EFAULT) | |
280 | error = ENOMEM; | 280 | error = ENOMEM; | |
281 | return error; | 281 | return error; | |
282 | } | 282 | } | |
283 | shmseg->shm_perm.mode |= SHMSEG_WIRED; | 283 | shmseg->shm_perm.mode |= SHMSEG_WIRED; | |
284 | 284 | |||
285 | } else if (cmd == SHM_UNLOCK && | 285 | } else if (cmd == SHM_UNLOCK && | |
286 | (shmseg->shm_perm.mode & SHMSEG_WIRED) != 0) { | 286 | (shmseg->shm_perm.mode & SHMSEG_WIRED) != 0) { | |
287 | /* Unwire the object and map, then untag it */ | 287 | /* Unwire the object and map, then untag it */ | |
288 | uvm_obj_unwirepages(shmseg->_shm_internal, 0, size); | 288 | uvm_obj_unwirepages(shmseg->_shm_internal, 0, size); | |
289 | error = uvm_map_pageable(&p->p_vmspace->vm_map, | 289 | error = uvm_map_pageable(&p->p_vmspace->vm_map, | |
290 | shmmap_se->va, shmmap_se->va + size, true, 0); | 290 | shmmap_se->va, shmmap_se->va + size, true, 0); | |
291 | if (error) | 291 | if (error) | |
292 | return EIO; | 292 | return EIO; | |
293 | shmseg->shm_perm.mode &= ~SHMSEG_WIRED; | 293 | shmseg->shm_perm.mode &= ~SHMSEG_WIRED; | |
294 | } | 294 | } | |
295 | } | 295 | } | |
296 | 296 | |||
297 | return 0; | 297 | return 0; | |
298 | } | 298 | } | |
299 | 299 | |||
300 | /* | 300 | /* | |
301 | * Unmap shared memory. | 301 | * Unmap shared memory. | |
302 | */ | 302 | */ | |
303 | int | 303 | int | |
304 | sys_shmdt(struct lwp *l, const struct sys_shmdt_args *uap, register_t *retval) | 304 | sys_shmdt(struct lwp *l, const struct sys_shmdt_args *uap, register_t *retval) | |
305 | { | 305 | { | |
306 | /* { | 306 | /* { | |
307 | syscallarg(const void *) shmaddr; | 307 | syscallarg(const void *) shmaddr; | |
308 | } */ | 308 | } */ | |
309 | struct proc *p = l->l_proc; | 309 | struct proc *p = l->l_proc; | |
310 | struct shmmap_state *shmmap_s1, *shmmap_s; | 310 | struct shmmap_state *shmmap_s1, *shmmap_s; | |
311 | struct shmmap_entry *shmmap_se; | 311 | struct shmmap_entry *shmmap_se; | |
312 | struct uvm_object *uobj; | 312 | struct uvm_object *uobj; | |
313 | struct shmid_ds *shmseg; | 313 | struct shmid_ds *shmseg; | |
314 | size_t size; | 314 | size_t size; | |
315 | 315 | |||
316 | mutex_enter(&shm_lock); | 316 | mutex_enter(&shm_lock); | |
317 | /* In case of reallocation, we will wait for completion */ | 317 | /* In case of reallocation, we will wait for completion */ | |
318 | while (__predict_false(shm_realloc_state)) | 318 | while (__predict_false(shm_realloc_state)) | |
319 | cv_wait(&shm_realloc_cv, &shm_lock); | 319 | cv_wait(&shm_realloc_cv, &shm_lock); | |
320 | 320 | |||
321 | shmmap_s1 = (struct shmmap_state *)p->p_vmspace->vm_shm; | 321 | shmmap_s1 = (struct shmmap_state *)p->p_vmspace->vm_shm; | |
322 | if (shmmap_s1 == NULL) { | 322 | if (shmmap_s1 == NULL) { | |
323 | mutex_exit(&shm_lock); | 323 | mutex_exit(&shm_lock); | |
324 | return EINVAL; | 324 | return EINVAL; | |
325 | } | 325 | } | |
326 | 326 | |||
327 | /* Find the map entry */ | 327 | /* Find the map entry */ | |
328 | SLIST_FOREACH(shmmap_se, &shmmap_s1->entries, next) | 328 | SLIST_FOREACH(shmmap_se, &shmmap_s1->entries, next) | |
329 | if (shmmap_se->va == (vaddr_t)SCARG(uap, shmaddr)) | 329 | if (shmmap_se->va == (vaddr_t)SCARG(uap, shmaddr)) | |
330 | break; | 330 | break; | |
331 | if (shmmap_se == NULL) { | 331 | if (shmmap_se == NULL) { | |
332 | mutex_exit(&shm_lock); | 332 | mutex_exit(&shm_lock); | |
333 | return EINVAL; | 333 | return EINVAL; | |
334 | } | 334 | } | |
335 | 335 | |||
336 | shmmap_s = shmmap_getprivate(p); | 336 | shmmap_s = shmmap_getprivate(p); | |
337 | if (shmmap_s != shmmap_s1) { | 337 | if (shmmap_s != shmmap_s1) { | |
338 | /* Map has been copied, lookup entry in new map */ | 338 | /* Map has been copied, lookup entry in new map */ | |
339 | SLIST_FOREACH(shmmap_se, &shmmap_s->entries, next) | 339 | SLIST_FOREACH(shmmap_se, &shmmap_s->entries, next) | |
340 | if (shmmap_se->va == (vaddr_t)SCARG(uap, shmaddr)) | 340 | if (shmmap_se->va == (vaddr_t)SCARG(uap, shmaddr)) | |
341 | break; | 341 | break; | |
342 | if (shmmap_se == NULL) { | 342 | if (shmmap_se == NULL) { | |
343 | mutex_exit(&shm_lock); | 343 | mutex_exit(&shm_lock); | |
344 | return EINVAL; | 344 | return EINVAL; | |
345 | } | 345 | } | |
346 | } | 346 | } | |
347 | 347 | |||
348 | SHMPRINTF(("shmdt: vm %p: remove %d @%lx\n", | 348 | SHMPRINTF(("shmdt: vm %p: remove %d @%lx\n", | |
349 | p->p_vmspace, shmmap_se->shmid, shmmap_se->va)); | 349 | p->p_vmspace, shmmap_se->shmid, shmmap_se->va)); | |
350 | 350 | |||
351 | /* Delete the entry from shm map */ | 351 | /* Delete the entry from shm map */ | |
352 | uobj = shm_delete_mapping(shmmap_s, shmmap_se); | 352 | uobj = shm_delete_mapping(shmmap_s, shmmap_se); | |
353 | shmseg = &shmsegs[IPCID_TO_IX(shmmap_se->shmid)]; | 353 | shmseg = &shmsegs[IPCID_TO_IX(shmmap_se->shmid)]; | |
354 | size = (shmseg->shm_segsz + PGOFSET) & ~PGOFSET; | 354 | size = (shmseg->shm_segsz + PGOFSET) & ~PGOFSET; | |
355 | mutex_exit(&shm_lock); | 355 | mutex_exit(&shm_lock); | |
356 | 356 | |||
357 | uvm_deallocate(&p->p_vmspace->vm_map, shmmap_se->va, size); | 357 | uvm_deallocate(&p->p_vmspace->vm_map, shmmap_se->va, size); | |
358 | if (uobj != NULL) { | 358 | if (uobj != NULL) { | |
359 | uao_detach(uobj); | 359 | uao_detach(uobj); | |
360 | } | 360 | } | |
361 | kmem_free(shmmap_se, sizeof(struct shmmap_entry)); | 361 | kmem_free(shmmap_se, sizeof(struct shmmap_entry)); | |
362 | 362 | |||
363 | return 0; | 363 | return 0; | |
364 | } | 364 | } | |
365 | 365 | |||
366 | /* | 366 | /* | |
367 | * Map shared memory. | 367 | * Map shared memory. | |
368 | */ | 368 | */ | |
369 | int | 369 | int | |
370 | sys_shmat(struct lwp *l, const struct sys_shmat_args *uap, register_t *retval) | 370 | sys_shmat(struct lwp *l, const struct sys_shmat_args *uap, register_t *retval) | |
371 | { | 371 | { | |
372 | /* { | 372 | /* { | |
373 | syscallarg(int) shmid; | 373 | syscallarg(int) shmid; | |
374 | syscallarg(const void *) shmaddr; | 374 | syscallarg(const void *) shmaddr; | |
375 | syscallarg(int) shmflg; | 375 | syscallarg(int) shmflg; | |
376 | } */ | 376 | } */ | |
377 | int error, flags = 0; | 377 | int error, flags = 0; | |
378 | struct proc *p = l->l_proc; | 378 | struct proc *p = l->l_proc; | |
379 | kauth_cred_t cred = l->l_cred; | 379 | kauth_cred_t cred = l->l_cred; | |
380 | struct shmid_ds *shmseg; | 380 | struct shmid_ds *shmseg; | |
381 | struct shmmap_state *shmmap_s; | 381 | struct shmmap_state *shmmap_s; | |
382 | struct shmmap_entry *shmmap_se; | 382 | struct shmmap_entry *shmmap_se; | |
383 | struct uvm_object *uobj; | 383 | struct uvm_object *uobj; | |
384 | struct vmspace *vm; | 384 | struct vmspace *vm; | |
385 | vaddr_t attach_va; | 385 | vaddr_t attach_va; | |
386 | vm_prot_t prot; | 386 | vm_prot_t prot; | |
387 | vsize_t size; | 387 | vsize_t size; | |
388 | 388 | |||
389 | /* Allocate a new map entry and set it */ | 389 | /* Allocate a new map entry and set it */ | |
390 | shmmap_se = kmem_alloc(sizeof(struct shmmap_entry), KM_SLEEP); | 390 | shmmap_se = kmem_alloc(sizeof(struct shmmap_entry), KM_SLEEP); | |
391 | shmmap_se->shmid = SCARG(uap, shmid); | 391 | shmmap_se->shmid = SCARG(uap, shmid); | |
392 | 392 | |||
393 | mutex_enter(&shm_lock); | 393 | mutex_enter(&shm_lock); | |
394 | /* In case of reallocation, we will wait for completion */ | 394 | /* In case of reallocation, we will wait for completion */ | |
395 | while (__predict_false(shm_realloc_state)) | 395 | while (__predict_false(shm_realloc_state)) | |
396 | cv_wait(&shm_realloc_cv, &shm_lock); | 396 | cv_wait(&shm_realloc_cv, &shm_lock); | |
397 | 397 | |||
398 | shmseg = shm_find_segment_by_shmid(SCARG(uap, shmid)); | 398 | shmseg = shm_find_segment_by_shmid(SCARG(uap, shmid)); | |
399 | if (shmseg == NULL) { | 399 | if (shmseg == NULL) { | |
400 | error = EINVAL; | 400 | error = EINVAL; | |
401 | goto err; | 401 | goto err; | |
402 | } | 402 | } | |
403 | error = ipcperm(cred, &shmseg->shm_perm, | 403 | error = ipcperm(cred, &shmseg->shm_perm, | |
404 | (SCARG(uap, shmflg) & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W); | 404 | (SCARG(uap, shmflg) & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W); | |
405 | if (error) | 405 | if (error) | |
406 | goto err; | 406 | goto err; | |
407 | 407 | |||
408 | vm = p->p_vmspace; | 408 | vm = p->p_vmspace; | |
409 | shmmap_s = (struct shmmap_state *)vm->vm_shm; | 409 | shmmap_s = (struct shmmap_state *)vm->vm_shm; | |
410 | if (shmmap_s && shmmap_s->nitems >= shminfo.shmseg) { | 410 | if (shmmap_s && shmmap_s->nitems >= shminfo.shmseg) { | |
411 | error = EMFILE; | 411 | error = EMFILE; | |
412 | goto err; | 412 | goto err; | |
413 | } | 413 | } | |
414 | 414 | |||
415 | size = (shmseg->shm_segsz + PGOFSET) & ~PGOFSET; | 415 | size = (shmseg->shm_segsz + PGOFSET) & ~PGOFSET; | |
416 | prot = VM_PROT_READ; | 416 | prot = VM_PROT_READ; | |
417 | if ((SCARG(uap, shmflg) & SHM_RDONLY) == 0) | 417 | if ((SCARG(uap, shmflg) & SHM_RDONLY) == 0) | |
418 | prot |= VM_PROT_WRITE; | 418 | prot |= VM_PROT_WRITE; | |
419 | if (SCARG(uap, shmaddr)) { | 419 | if (SCARG(uap, shmaddr)) { | |
420 | flags |= UVM_FLAG_FIXED; | 420 | flags |= UVM_FLAG_FIXED; | |
421 | if (SCARG(uap, shmflg) & SHM_RND) | 421 | if (SCARG(uap, shmflg) & SHM_RND) | |
422 | attach_va = | 422 | attach_va = | |
423 | (vaddr_t)SCARG(uap, shmaddr) & ~(SHMLBA-1); | 423 | (vaddr_t)SCARG(uap, shmaddr) & ~(SHMLBA-1); | |
424 | else if (((vaddr_t)SCARG(uap, shmaddr) & (SHMLBA-1)) == 0) | 424 | else if (((vaddr_t)SCARG(uap, shmaddr) & (SHMLBA-1)) == 0) | |
425 | attach_va = (vaddr_t)SCARG(uap, shmaddr); | 425 | attach_va = (vaddr_t)SCARG(uap, shmaddr); | |
426 | else { | 426 | else { | |
427 | error = EINVAL; | 427 | error = EINVAL; | |
428 | goto err; | 428 | goto err; | |
429 | } | 429 | } | |
430 | } else { | 430 | } else { | |
431 | /* This is just a hint to uvm_map() about where to put it. */ | 431 | /* This is just a hint to uvm_map() about where to put it. */ | |
432 | attach_va = p->p_emul->e_vm_default_addr(p, | 432 | attach_va = p->p_emul->e_vm_default_addr(p, | |
433 | (vaddr_t)vm->vm_daddr, size); | 433 | (vaddr_t)vm->vm_daddr, size); | |
434 | } | 434 | } | |
435 | 435 | |||
436 | /* | 436 | /* | |
437 | * Create a map entry, add it to the list and increase the counters. | 437 | * Create a map entry, add it to the list and increase the counters. | |
438 | * The lock will be dropped before the mapping, disable reallocation. | 438 | * The lock will be dropped before the mapping, disable reallocation. | |
439 | */ | 439 | */ | |
440 | shmmap_s = shmmap_getprivate(p); | 440 | shmmap_s = shmmap_getprivate(p); | |
441 | SLIST_INSERT_HEAD(&shmmap_s->entries, shmmap_se, next); | 441 | SLIST_INSERT_HEAD(&shmmap_s->entries, shmmap_se, next); | |
442 | shmmap_s->nitems++; | 442 | shmmap_s->nitems++; | |
443 | shmseg->shm_lpid = p->p_pid; | 443 | shmseg->shm_lpid = p->p_pid; | |
444 | shmseg->shm_nattch++; | 444 | shmseg->shm_nattch++; | |
445 | shm_realloc_disable++; | 445 | shm_realloc_disable++; | |
446 | mutex_exit(&shm_lock); | 446 | mutex_exit(&shm_lock); | |
447 | 447 | |||
448 | /* | 448 | /* | |
449 | * Add a reference to the memory object, map it to the | 449 | * Add a reference to the memory object, map it to the | |
450 | * address space, and lock the memory, if needed. | 450 | * address space, and lock the memory, if needed. | |
451 | */ | 451 | */ | |
452 | uobj = shmseg->_shm_internal; | 452 | uobj = shmseg->_shm_internal; | |
453 | uao_reference(uobj); | 453 | uao_reference(uobj); | |
454 | error = uvm_map(&vm->vm_map, &attach_va, size, uobj, 0, 0, | 454 | error = uvm_map(&vm->vm_map, &attach_va, size, uobj, 0, 0, | |
455 | UVM_MAPFLAG(prot, prot, UVM_INH_SHARE, UVM_ADV_RANDOM, flags)); | 455 | UVM_MAPFLAG(prot, prot, UVM_INH_SHARE, UVM_ADV_RANDOM, flags)); | |
456 | if (error) | 456 | if (error) | |
457 | goto err_detach; | 457 | goto err_detach; | |
458 | if (shm_use_phys || (shmseg->shm_perm.mode & SHMSEG_WIRED)) { | 458 | if (shm_use_phys || (shmseg->shm_perm.mode & SHMSEG_WIRED)) { | |
459 | error = uvm_map_pageable(&vm->vm_map, attach_va, | 459 | error = uvm_map_pageable(&vm->vm_map, attach_va, | |
460 | attach_va + size, false, 0); | 460 | attach_va + size, false, 0); | |
461 | if (error) { | 461 | if (error) { | |
462 | if (error == EFAULT) | 462 | if (error == EFAULT) | |
463 | error = ENOMEM; | 463 | error = ENOMEM; | |
464 | uvm_deallocate(&vm->vm_map, attach_va, size); | 464 | uvm_deallocate(&vm->vm_map, attach_va, size); | |
465 | goto err_detach; | 465 | goto err_detach; | |
466 | } | 466 | } | |
467 | } | 467 | } | |
468 | 468 | |||
469 | /* Set the new address, and update the time */ | 469 | /* Set the new address, and update the time */ | |
470 | mutex_enter(&shm_lock); | 470 | mutex_enter(&shm_lock); | |
471 | shmmap_se->va = attach_va; | 471 | shmmap_se->va = attach_va; | |
472 | shmseg->shm_atime = time_second; | 472 | shmseg->shm_atime = time_second; | |
473 | shm_realloc_disable--; | 473 | shm_realloc_disable--; | |
474 | retval[0] = attach_va; | 474 | retval[0] = attach_va; | |
475 | SHMPRINTF(("shmat: vm %p: add %d @%lx\n", | 475 | SHMPRINTF(("shmat: vm %p: add %d @%lx\n", | |
476 | p->p_vmspace, shmmap_se->shmid, attach_va)); | 476 | p->p_vmspace, shmmap_se->shmid, attach_va)); | |
477 | err: | 477 | err: | |
478 | cv_broadcast(&shm_realloc_cv); | 478 | cv_broadcast(&shm_realloc_cv); | |
479 | mutex_exit(&shm_lock); | 479 | mutex_exit(&shm_lock); | |
480 | if (error && shmmap_se) { | 480 | if (error && shmmap_se) { | |
481 | kmem_free(shmmap_se, sizeof(struct shmmap_entry)); | 481 | kmem_free(shmmap_se, sizeof(struct shmmap_entry)); | |
482 | } | 482 | } | |
483 | return error; | 483 | return error; | |
484 | 484 | |||
485 | err_detach: | 485 | err_detach: | |
486 | uao_detach(uobj); | 486 | uao_detach(uobj); | |
487 | mutex_enter(&shm_lock); | 487 | mutex_enter(&shm_lock); | |
488 | uobj = shm_delete_mapping(shmmap_s, shmmap_se); | 488 | uobj = shm_delete_mapping(shmmap_s, shmmap_se); | |
489 | shm_realloc_disable--; | 489 | shm_realloc_disable--; | |
490 | cv_broadcast(&shm_realloc_cv); | 490 | cv_broadcast(&shm_realloc_cv); | |
491 | mutex_exit(&shm_lock); | 491 | mutex_exit(&shm_lock); | |
492 | if (uobj != NULL) { | 492 | if (uobj != NULL) { | |
493 | uao_detach(uobj); | 493 | uao_detach(uobj); | |
494 | } | 494 | } | |
495 | kmem_free(shmmap_se, sizeof(struct shmmap_entry)); | 495 | kmem_free(shmmap_se, sizeof(struct shmmap_entry)); | |
496 | return error; | 496 | return error; | |
497 | } | 497 | } | |
498 | 498 | |||
499 | /* | 499 | /* | |
500 | * Shared memory control operations. | 500 | * Shared memory control operations. | |
501 | */ | 501 | */ | |
502 | int | 502 | int | |
503 | sys___shmctl50(struct lwp *l, const struct sys___shmctl50_args *uap, | 503 | sys___shmctl50(struct lwp *l, const struct sys___shmctl50_args *uap, | |
504 | register_t *retval) | 504 | register_t *retval) | |
505 | { | 505 | { | |
506 | /* { | 506 | /* { | |
507 | syscallarg(int) shmid; | 507 | syscallarg(int) shmid; | |
508 | syscallarg(int) cmd; | 508 | syscallarg(int) cmd; | |
509 | syscallarg(struct shmid_ds *) buf; | 509 | syscallarg(struct shmid_ds *) buf; | |
510 | } */ | 510 | } */ | |
511 | struct shmid_ds shmbuf; | 511 | struct shmid_ds shmbuf; | |
512 | int cmd, error; | 512 | int cmd, error; | |
513 | 513 | |||
514 | cmd = SCARG(uap, cmd); | 514 | cmd = SCARG(uap, cmd); | |
515 | if (cmd == IPC_SET) { | 515 | if (cmd == IPC_SET) { | |
516 | error = copyin(SCARG(uap, buf), &shmbuf, sizeof(shmbuf)); | 516 | error = copyin(SCARG(uap, buf), &shmbuf, sizeof(shmbuf)); | |
517 | if (error) | 517 | if (error) | |
518 | return error; | 518 | return error; | |
519 | } | 519 | } | |
520 | 520 | |||
521 | error = shmctl1(l, SCARG(uap, shmid), cmd, | 521 | error = shmctl1(l, SCARG(uap, shmid), cmd, | |
522 | (cmd == IPC_SET || cmd == IPC_STAT) ? &shmbuf : NULL); | 522 | (cmd == IPC_SET || cmd == IPC_STAT) ? &shmbuf : NULL); | |
523 | 523 | |||
524 | if (error == 0 && cmd == IPC_STAT) | 524 | if (error == 0 && cmd == IPC_STAT) | |
525 | error = copyout(&shmbuf, SCARG(uap, buf), sizeof(shmbuf)); | 525 | error = copyout(&shmbuf, SCARG(uap, buf), sizeof(shmbuf)); | |
526 | 526 | |||
527 | return error; | 527 | return error; | |
528 | } | 528 | } | |
529 | 529 | |||
530 | int | 530 | int | |
531 | shmctl1(struct lwp *l, int shmid, int cmd, struct shmid_ds *shmbuf) | 531 | shmctl1(struct lwp *l, int shmid, int cmd, struct shmid_ds *shmbuf) | |
532 | { | 532 | { | |
533 | struct uvm_object *uobj = NULL; | 533 | struct uvm_object *uobj = NULL; | |
534 | kauth_cred_t cred = l->l_cred; | 534 | kauth_cred_t cred = l->l_cred; | |
535 | struct shmid_ds *shmseg; | 535 | struct shmid_ds *shmseg; | |
536 | int error = 0; | 536 | int error = 0; | |
537 | 537 | |||
538 | mutex_enter(&shm_lock); | 538 | mutex_enter(&shm_lock); | |
539 | /* In case of reallocation, we will wait for completion */ | 539 | /* In case of reallocation, we will wait for completion */ | |
540 | while (__predict_false(shm_realloc_state)) | 540 | while (__predict_false(shm_realloc_state)) | |
541 | cv_wait(&shm_realloc_cv, &shm_lock); | 541 | cv_wait(&shm_realloc_cv, &shm_lock); | |
542 | 542 | |||
543 | shmseg = shm_find_segment_by_shmid(shmid); | 543 | shmseg = shm_find_segment_by_shmid(shmid); | |
544 | if (shmseg == NULL) { | 544 | if (shmseg == NULL) { | |
545 | mutex_exit(&shm_lock); | 545 | mutex_exit(&shm_lock); | |
546 | return EINVAL; | 546 | return EINVAL; | |
547 | } | 547 | } | |
548 | 548 | |||
549 | switch (cmd) { | 549 | switch (cmd) { | |
550 | case IPC_STAT: | 550 | case IPC_STAT: | |
551 | if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_R)) != 0) | 551 | if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_R)) != 0) | |
552 | break; | 552 | break; | |
553 | memcpy(shmbuf, shmseg, sizeof(struct shmid_ds)); | 553 | memcpy(shmbuf, shmseg, sizeof(struct shmid_ds)); | |
554 | break; | 554 | break; | |
555 | case IPC_SET: | 555 | case IPC_SET: | |
556 | if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_M)) != 0) | 556 | if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_M)) != 0) | |
557 | break; | 557 | break; | |
558 | shmseg->shm_perm.uid = shmbuf->shm_perm.uid; | 558 | shmseg->shm_perm.uid = shmbuf->shm_perm.uid; | |
559 | shmseg->shm_perm.gid = shmbuf->shm_perm.gid; | 559 | shmseg->shm_perm.gid = shmbuf->shm_perm.gid; | |
560 | shmseg->shm_perm.mode = | 560 | shmseg->shm_perm.mode = | |
561 | (shmseg->shm_perm.mode & ~ACCESSPERMS) | | 561 | (shmseg->shm_perm.mode & ~ACCESSPERMS) | | |
562 | (shmbuf->shm_perm.mode & ACCESSPERMS); | 562 | (shmbuf->shm_perm.mode & ACCESSPERMS); | |
563 | shmseg->shm_ctime = time_second; | 563 | shmseg->shm_ctime = time_second; | |
564 | break; | 564 | break; | |
565 | case IPC_RMID: | 565 | case IPC_RMID: | |
566 | if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_M)) != 0) | 566 | if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_M)) != 0) | |
567 | break; | 567 | break; | |
568 | shmseg->shm_perm._key = IPC_PRIVATE; | 568 | shmseg->shm_perm._key = IPC_PRIVATE; | |
569 | shmseg->shm_perm.mode |= SHMSEG_REMOVED; | 569 | shmseg->shm_perm.mode |= SHMSEG_REMOVED; | |
570 | if (shmseg->shm_nattch <= 0) { | 570 | if (shmseg->shm_nattch <= 0) { | |
571 | uobj = shmseg->_shm_internal; | 571 | uobj = shmseg->_shm_internal; | |
572 | shm_free_segment(IPCID_TO_IX(shmid)); | 572 | shm_free_segment(IPCID_TO_IX(shmid)); | |
573 | } | 573 | } | |
574 | break; | 574 | break; | |
575 | case SHM_LOCK: | 575 | case SHM_LOCK: | |
576 | case SHM_UNLOCK: | 576 | case SHM_UNLOCK: | |
577 | if ((error = kauth_authorize_generic(cred, | 577 | if ((error = kauth_authorize_generic(cred, | |
578 | KAUTH_GENERIC_ISSUSER, NULL)) != 0) | 578 | KAUTH_GENERIC_ISSUSER, NULL)) != 0) | |
579 | break; | 579 | break; | |
580 | error = shm_memlock(l, shmseg, shmid, cmd); | 580 | error = shm_memlock(l, shmseg, shmid, cmd); | |
581 | break; | 581 | break; | |
582 | default: | 582 | default: | |
583 | error = EINVAL; | 583 | error = EINVAL; | |
584 | } | 584 | } | |
585 | 585 | |||
586 | mutex_exit(&shm_lock); | 586 | mutex_exit(&shm_lock); | |
587 | if (uobj != NULL) | 587 | if (uobj != NULL) | |
588 | uao_detach(uobj); | 588 | uao_detach(uobj); | |
589 | return error; | 589 | return error; | |
590 | } | 590 | } | |
591 | 591 | |||
592 | /* | 592 | /* | |
593 | * Try to take an already existing segment. | 593 | * Try to take an already existing segment. | |
594 | * => must be called with shm_lock held; | 594 | * => must be called with shm_lock held; | |
595 | * => called from one place, thus, inline; | 595 | * => called from one place, thus, inline; | |
596 | */ | 596 | */ | |
597 | static inline int | 597 | static inline int | |
598 | shmget_existing(struct lwp *l, const struct sys_shmget_args *uap, int mode, | 598 | shmget_existing(struct lwp *l, const struct sys_shmget_args *uap, int mode, | |
599 | register_t *retval) | 599 | register_t *retval) | |
600 | { | 600 | { | |
601 | struct shmid_ds *shmseg; | 601 | struct shmid_ds *shmseg; | |
602 | kauth_cred_t cred = l->l_cred; | 602 | kauth_cred_t cred = l->l_cred; | |
603 | int segnum, error; | 603 | int segnum, error; | |
604 | again: | 604 | again: | |
605 | KASSERT(mutex_owned(&shm_lock)); | 605 | KASSERT(mutex_owned(&shm_lock)); | |
606 | 606 | |||
607 | /* Find segment by key */ | 607 | /* Find segment by key */ | |
608 | for (segnum = 0; segnum < shminfo.shmmni; segnum++) | 608 | for (segnum = 0; segnum < shminfo.shmmni; segnum++) | |
609 | if ((shmsegs[segnum].shm_perm.mode & SHMSEG_ALLOCATED) && | 609 | if ((shmsegs[segnum].shm_perm.mode & SHMSEG_ALLOCATED) && | |
610 | shmsegs[segnum].shm_perm._key == SCARG(uap, key)) | 610 | shmsegs[segnum].shm_perm._key == SCARG(uap, key)) | |
611 | break; | 611 | break; | |
612 | if (segnum == shminfo.shmmni) { | 612 | if (segnum == shminfo.shmmni) { | |
613 | /* Not found */ | 613 | /* Not found */ | |
614 | return -1; | 614 | return -1; | |
615 | } | 615 | } | |
616 | 616 | |||
617 | shmseg = &shmsegs[segnum]; | 617 | shmseg = &shmsegs[segnum]; | |
618 | if (shmseg->shm_perm.mode & SHMSEG_REMOVED) { | 618 | if (shmseg->shm_perm.mode & SHMSEG_REMOVED) { | |
619 | /* | 619 | /* | |
620 | * This segment is in the process of being allocated. Wait | 620 | * This segment is in the process of being allocated. Wait | |
621 | * until it's done, and look the key up again (in case the | 621 | * until it's done, and look the key up again (in case the | |
622 | * allocation failed or it was freed). | 622 | * allocation failed or it was freed). | |
623 | */ | 623 | */ | |
624 | shmseg->shm_perm.mode |= SHMSEG_WANTED; | 624 | shmseg->shm_perm.mode |= SHMSEG_WANTED; | |
625 | error = cv_wait_sig(&shm_cv[segnum], &shm_lock); | 625 | error = cv_wait_sig(&shm_cv[segnum], &shm_lock); | |
626 | if (error) | 626 | if (error) | |
627 | return error; | 627 | return error; | |
628 | goto again; | 628 | goto again; | |
629 | } | 629 | } | |
630 | 630 | |||
631 | /* | 631 | /* | |
632 | * First check the flags, to generate a useful error when a | 632 | * First check the flags, to generate a useful error when a | |
633 | * segment already exists. | 633 | * segment already exists. | |
634 | */ | 634 | */ | |
635 | if ((SCARG(uap, shmflg) & (IPC_CREAT | IPC_EXCL)) == | 635 | if ((SCARG(uap, shmflg) & (IPC_CREAT | IPC_EXCL)) == | |
636 | (IPC_CREAT | IPC_EXCL)) | 636 | (IPC_CREAT | IPC_EXCL)) | |
637 | return EEXIST; | 637 | return EEXIST; | |
638 | 638 | |||
639 | /* Check the permission and segment size. */ | 639 | /* Check the permission and segment size. */ | |
640 | error = ipcperm(cred, &shmseg->shm_perm, mode); | 640 | error = ipcperm(cred, &shmseg->shm_perm, mode); | |
641 | if (error) | 641 | if (error) | |
642 | return error; | 642 | return error; | |
643 | if (SCARG(uap, size) && SCARG(uap, size) > shmseg->shm_segsz) | 643 | if (SCARG(uap, size) && SCARG(uap, size) > shmseg->shm_segsz) | |
644 | return EINVAL; | 644 | return EINVAL; | |
645 | 645 | |||
646 | *retval = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm); | 646 | *retval = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm); | |
647 | return 0; | 647 | return 0; | |
648 | } | 648 | } | |
649 | 649 | |||
650 | int | 650 | int | |
651 | sys_shmget(struct lwp *l, const struct sys_shmget_args *uap, register_t *retval) | 651 | sys_shmget(struct lwp *l, const struct sys_shmget_args *uap, register_t *retval) | |
652 | { | 652 | { | |
653 | /* { | 653 | /* { | |
654 | syscallarg(key_t) key; | 654 | syscallarg(key_t) key; | |
655 | syscallarg(size_t) size; | 655 | syscallarg(size_t) size; | |
656 | syscallarg(int) shmflg; | 656 | syscallarg(int) shmflg; | |
657 | } */ | 657 | } */ | |
658 | struct shmid_ds *shmseg; | 658 | struct shmid_ds *shmseg; | |
659 | kauth_cred_t cred = l->l_cred; | 659 | kauth_cred_t cred = l->l_cred; | |
660 | key_t key = SCARG(uap, key); | 660 | key_t key = SCARG(uap, key); | |
661 | size_t size; | 661 | size_t size; | |
662 | int error, mode, segnum; | 662 | int error, mode, segnum; | |
663 | bool lockmem; | 663 | bool lockmem; | |
664 | 664 | |||
665 | mode = SCARG(uap, shmflg) & ACCESSPERMS; | 665 | mode = SCARG(uap, shmflg) & ACCESSPERMS; | |
666 | if (SCARG(uap, shmflg) & _SHM_RMLINGER) | 666 | if (SCARG(uap, shmflg) & _SHM_RMLINGER) | |
667 | mode |= SHMSEG_RMLINGER; | 667 | mode |= SHMSEG_RMLINGER; | |
668 | 668 | |||
669 | SHMPRINTF(("shmget: key 0x%lx size 0x%zx shmflg 0x%x mode 0x%x\n", | 669 | SHMPRINTF(("shmget: key 0x%lx size 0x%zx shmflg 0x%x mode 0x%x\n", | |
670 | SCARG(uap, key), SCARG(uap, size), SCARG(uap, shmflg), mode)); | 670 | SCARG(uap, key), SCARG(uap, size), SCARG(uap, shmflg), mode)); | |
671 | 671 | |||
672 | mutex_enter(&shm_lock); | 672 | mutex_enter(&shm_lock); | |
673 | /* In case of reallocation, we will wait for completion */ | 673 | /* In case of reallocation, we will wait for completion */ | |
674 | while (__predict_false(shm_realloc_state)) | 674 | while (__predict_false(shm_realloc_state)) | |
675 | cv_wait(&shm_realloc_cv, &shm_lock); | 675 | cv_wait(&shm_realloc_cv, &shm_lock); | |
676 | 676 | |||
677 | if (key != IPC_PRIVATE) { | 677 | if (key != IPC_PRIVATE) { | |
678 | error = shmget_existing(l, uap, mode, retval); | 678 | error = shmget_existing(l, uap, mode, retval); | |
679 | if (error != -1) { | 679 | if (error != -1) { | |
680 | mutex_exit(&shm_lock); | 680 | mutex_exit(&shm_lock); | |
681 | return error; | 681 | return error; | |
682 | } | 682 | } | |
683 | if ((SCARG(uap, shmflg) & IPC_CREAT) == 0) { | 683 | if ((SCARG(uap, shmflg) & IPC_CREAT) == 0) { | |
684 | mutex_exit(&shm_lock); | 684 | mutex_exit(&shm_lock); | |
685 | return ENOENT; | 685 | return ENOENT; | |
686 | } | 686 | } | |
687 | } | 687 | } | |
688 | error = 0; | 688 | error = 0; | |
689 | 689 | |||
690 | /* | 690 | /* | |
691 | * Check the for the limits. | 691 | * Check the for the limits. | |
692 | */ | 692 | */ | |
693 | size = SCARG(uap, size); | 693 | size = SCARG(uap, size); | |
694 | if (size < shminfo.shmmin || size > shminfo.shmmax) { | 694 | if (size < shminfo.shmmin || size > shminfo.shmmax) { | |
695 | mutex_exit(&shm_lock); | 695 | mutex_exit(&shm_lock); | |
696 | return EINVAL; | 696 | return EINVAL; | |
697 | } | 697 | } | |
698 | if (shm_nused >= shminfo.shmmni) { | 698 | if (shm_nused >= shminfo.shmmni) { | |
699 | mutex_exit(&shm_lock); | 699 | mutex_exit(&shm_lock); | |
700 | return ENOSPC; | 700 | return ENOSPC; | |
701 | } | 701 | } | |
702 | size = (size + PGOFSET) & ~PGOFSET; | 702 | size = (size + PGOFSET) & ~PGOFSET; | |
703 | if (shm_committed + btoc(size) > shminfo.shmall) { | 703 | if (shm_committed + btoc(size) > shminfo.shmall) { | |
704 | mutex_exit(&shm_lock); | 704 | mutex_exit(&shm_lock); | |
705 | return ENOMEM; | 705 | return ENOMEM; | |
706 | } | 706 | } | |
707 | 707 | |||
708 | /* Find the first available segment */ | 708 | /* Find the first available segment */ | |
709 | if (shm_last_free < 0) { | 709 | if (shm_last_free < 0) { | |
710 | for (segnum = 0; segnum < shminfo.shmmni; segnum++) | 710 | for (segnum = 0; segnum < shminfo.shmmni; segnum++) | |
711 | if (shmsegs[segnum].shm_perm.mode & SHMSEG_FREE) | 711 | if (shmsegs[segnum].shm_perm.mode & SHMSEG_FREE) | |
712 | break; | 712 | break; | |
713 | KASSERT(segnum < shminfo.shmmni); | 713 | KASSERT(segnum < shminfo.shmmni); | |
714 | } else { | 714 | } else { | |
715 | segnum = shm_last_free; | 715 | segnum = shm_last_free; | |
716 | shm_last_free = -1; | 716 | shm_last_free = -1; | |
717 | } | 717 | } | |
718 | 718 | |||
719 | /* | 719 | /* | |
720 | * Initialize the segment. | 720 | * Initialize the segment. | |
721 | * We will drop the lock while allocating the memory, thus mark the | 721 | * We will drop the lock while allocating the memory, thus mark the | |
722 | * segment present, but removed, that no other thread could take it. | 722 | * segment present, but removed, that no other thread could take it. | |
723 | * Also, disable reallocation, while lock is dropped. | 723 | * Also, disable reallocation, while lock is dropped. | |
724 | */ | 724 | */ | |
725 | shmseg = &shmsegs[segnum]; | 725 | shmseg = &shmsegs[segnum]; | |
726 | shmseg->shm_perm.mode = SHMSEG_ALLOCATED | SHMSEG_REMOVED; | 726 | shmseg->shm_perm.mode = SHMSEG_ALLOCATED | SHMSEG_REMOVED; | |
727 | shm_committed += btoc(size); | 727 | shm_committed += btoc(size); | |
728 | shm_nused++; | 728 | shm_nused++; | |
729 | lockmem = shm_use_phys; | 729 | lockmem = shm_use_phys; | |
730 | shm_realloc_disable++; | 730 | shm_realloc_disable++; | |
731 | mutex_exit(&shm_lock); | 731 | mutex_exit(&shm_lock); | |
732 | 732 | |||
733 | /* Allocate the memory object and lock it if needed */ | 733 | /* Allocate the memory object and lock it if needed */ | |
734 | shmseg->_shm_internal = uao_create(size, 0); | 734 | shmseg->_shm_internal = uao_create(size, 0); | |
735 | if (lockmem) { | 735 | if (lockmem) { | |
736 | /* Wire the pages and tag it */ | 736 | /* Wire the pages and tag it */ | |
737 | error = uvm_obj_wirepages(shmseg->_shm_internal, 0, size); | 737 | error = uvm_obj_wirepages(shmseg->_shm_internal, 0, size, NULL); | |
738 | if (error) { | 738 | if (error) { | |
739 | uao_detach(shmseg->_shm_internal); | 739 | uao_detach(shmseg->_shm_internal); | |
740 | mutex_enter(&shm_lock); | 740 | mutex_enter(&shm_lock); | |
741 | shm_free_segment(segnum); | 741 | shm_free_segment(segnum); | |
742 | shm_realloc_disable--; | 742 | shm_realloc_disable--; | |
743 | mutex_exit(&shm_lock); | 743 | mutex_exit(&shm_lock); | |
744 | return error; | 744 | return error; | |
745 | } | 745 | } | |
746 | } | 746 | } | |
747 | 747 | |||
748 | /* | 748 | /* | |
749 | * Please note, while segment is marked, there are no need to hold the | 749 | * Please note, while segment is marked, there are no need to hold the | |
750 | * lock, while setting it (except shm_perm.mode). | 750 | * lock, while setting it (except shm_perm.mode). | |
751 | */ | 751 | */ | |
752 | shmseg->shm_perm._key = SCARG(uap, key); | 752 | shmseg->shm_perm._key = SCARG(uap, key); | |
753 | shmseg->shm_perm._seq = (shmseg->shm_perm._seq + 1) & 0x7fff; | 753 | shmseg->shm_perm._seq = (shmseg->shm_perm._seq + 1) & 0x7fff; | |
754 | *retval = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm); | 754 | *retval = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm); | |
755 | 755 | |||
756 | shmseg->shm_perm.cuid = shmseg->shm_perm.uid = kauth_cred_geteuid(cred); | 756 | shmseg->shm_perm.cuid = shmseg->shm_perm.uid = kauth_cred_geteuid(cred); | |
757 | shmseg->shm_perm.cgid = shmseg->shm_perm.gid = kauth_cred_getegid(cred); | 757 | shmseg->shm_perm.cgid = shmseg->shm_perm.gid = kauth_cred_getegid(cred); | |
758 | shmseg->shm_segsz = SCARG(uap, size); | 758 | shmseg->shm_segsz = SCARG(uap, size); | |
759 | shmseg->shm_cpid = l->l_proc->p_pid; | 759 | shmseg->shm_cpid = l->l_proc->p_pid; | |
760 | shmseg->shm_lpid = shmseg->shm_nattch = 0; | 760 | shmseg->shm_lpid = shmseg->shm_nattch = 0; | |
761 | shmseg->shm_atime = shmseg->shm_dtime = 0; | 761 | shmseg->shm_atime = shmseg->shm_dtime = 0; | |
762 | shmseg->shm_ctime = time_second; | 762 | shmseg->shm_ctime = time_second; | |
763 | 763 | |||
764 | /* | 764 | /* | |
765 | * Segment is initialized. | 765 | * Segment is initialized. | |
766 | * Enter the lock, mark as allocated, and notify waiters (if any). | 766 | * Enter the lock, mark as allocated, and notify waiters (if any). | |
767 | * Also, unmark the state of reallocation. | 767 | * Also, unmark the state of reallocation. | |
768 | */ | 768 | */ | |
769 | mutex_enter(&shm_lock); | 769 | mutex_enter(&shm_lock); | |
770 | shmseg->shm_perm.mode = (shmseg->shm_perm.mode & SHMSEG_WANTED) | | 770 | shmseg->shm_perm.mode = (shmseg->shm_perm.mode & SHMSEG_WANTED) | | |
771 | (mode & (ACCESSPERMS | SHMSEG_RMLINGER)) | | 771 | (mode & (ACCESSPERMS | SHMSEG_RMLINGER)) | | |
772 | SHMSEG_ALLOCATED | (lockmem ? SHMSEG_WIRED : 0); | 772 | SHMSEG_ALLOCATED | (lockmem ? SHMSEG_WIRED : 0); | |
773 | if (shmseg->shm_perm.mode & SHMSEG_WANTED) { | 773 | if (shmseg->shm_perm.mode & SHMSEG_WANTED) { | |
774 | shmseg->shm_perm.mode &= ~SHMSEG_WANTED; | 774 | shmseg->shm_perm.mode &= ~SHMSEG_WANTED; | |
775 | cv_broadcast(&shm_cv[segnum]); | 775 | cv_broadcast(&shm_cv[segnum]); | |
776 | } | 776 | } | |
777 | shm_realloc_disable--; | 777 | shm_realloc_disable--; | |
778 | cv_broadcast(&shm_realloc_cv); | 778 | cv_broadcast(&shm_realloc_cv); | |
779 | mutex_exit(&shm_lock); | 779 | mutex_exit(&shm_lock); | |
780 | 780 | |||
781 | return error; | 781 | return error; | |
782 | } | 782 | } | |
783 | 783 | |||
784 | void | 784 | void | |
785 | shmfork(struct vmspace *vm1, struct vmspace *vm2) | 785 | shmfork(struct vmspace *vm1, struct vmspace *vm2) | |
786 | { | 786 | { | |
787 | struct shmmap_state *shmmap_s; | 787 | struct shmmap_state *shmmap_s; | |
788 | struct shmmap_entry *shmmap_se; | 788 | struct shmmap_entry *shmmap_se; | |
789 | 789 | |||
790 | SHMPRINTF(("shmfork %p->%p\n", vm1, vm2)); | 790 | SHMPRINTF(("shmfork %p->%p\n", vm1, vm2)); | |
791 | mutex_enter(&shm_lock); | 791 | mutex_enter(&shm_lock); | |
792 | vm2->vm_shm = vm1->vm_shm; | 792 | vm2->vm_shm = vm1->vm_shm; | |
793 | if (vm1->vm_shm) { | 793 | if (vm1->vm_shm) { | |
794 | shmmap_s = (struct shmmap_state *)vm1->vm_shm; | 794 | shmmap_s = (struct shmmap_state *)vm1->vm_shm; | |
795 | SLIST_FOREACH(shmmap_se, &shmmap_s->entries, next) | 795 | SLIST_FOREACH(shmmap_se, &shmmap_s->entries, next) | |
796 | shmsegs[IPCID_TO_IX(shmmap_se->shmid)].shm_nattch++; | 796 | shmsegs[IPCID_TO_IX(shmmap_se->shmid)].shm_nattch++; | |
797 | shmmap_s->nrefs++; | 797 | shmmap_s->nrefs++; | |
798 | } | 798 | } | |
799 | mutex_exit(&shm_lock); | 799 | mutex_exit(&shm_lock); | |
800 | } | 800 | } | |
801 | 801 | |||
802 | void | 802 | void | |
803 | shmexit(struct vmspace *vm) | 803 | shmexit(struct vmspace *vm) | |
804 | { | 804 | { | |
805 | struct shmmap_state *shmmap_s; | 805 | struct shmmap_state *shmmap_s; | |
806 | struct shmmap_entry *shmmap_se; | 806 | struct shmmap_entry *shmmap_se; | |
807 | 807 | |||
808 | mutex_enter(&shm_lock); | 808 | mutex_enter(&shm_lock); | |
809 | shmmap_s = (struct shmmap_state *)vm->vm_shm; | 809 | shmmap_s = (struct shmmap_state *)vm->vm_shm; | |
810 | if (shmmap_s == NULL) { | 810 | if (shmmap_s == NULL) { | |
811 | mutex_exit(&shm_lock); | 811 | mutex_exit(&shm_lock); | |
812 | return; | 812 | return; | |
813 | } | 813 | } | |
814 | vm->vm_shm = NULL; | 814 | vm->vm_shm = NULL; | |
815 | 815 | |||
816 | if (--shmmap_s->nrefs > 0) { | 816 | if (--shmmap_s->nrefs > 0) { | |
817 | SHMPRINTF(("shmexit: vm %p drop ref (%d entries), refs = %d\n", | 817 | SHMPRINTF(("shmexit: vm %p drop ref (%d entries), refs = %d\n", | |
818 | vm, shmmap_s->nitems, shmmap_s->nrefs)); | 818 | vm, shmmap_s->nitems, shmmap_s->nrefs)); | |
819 | SLIST_FOREACH(shmmap_se, &shmmap_s->entries, next) { | 819 | SLIST_FOREACH(shmmap_se, &shmmap_s->entries, next) { | |
820 | shmsegs[IPCID_TO_IX(shmmap_se->shmid)].shm_nattch--; | 820 | shmsegs[IPCID_TO_IX(shmmap_se->shmid)].shm_nattch--; | |
821 | } | 821 | } | |
822 | mutex_exit(&shm_lock); | 822 | mutex_exit(&shm_lock); | |
823 | return; | 823 | return; | |
824 | } | 824 | } | |
825 | 825 | |||
826 | SHMPRINTF(("shmexit: vm %p cleanup (%d entries)\n", vm, shmmap_s->nitems)); | 826 | SHMPRINTF(("shmexit: vm %p cleanup (%d entries)\n", vm, shmmap_s->nitems)); | |
827 | if (shmmap_s->nitems == 0) { | 827 | if (shmmap_s->nitems == 0) { | |
828 | mutex_exit(&shm_lock); | 828 | mutex_exit(&shm_lock); | |
829 | kmem_free(shmmap_s, sizeof(struct shmmap_state)); | 829 | kmem_free(shmmap_s, sizeof(struct shmmap_state)); | |
830 | return; | 830 | return; | |
831 | } | 831 | } | |
832 | 832 | |||
833 | /* | 833 | /* | |
834 | * Delete the entry from shm map. | 834 | * Delete the entry from shm map. | |
835 | */ | 835 | */ | |
836 | for (;;) { | 836 | for (;;) { | |
837 | struct shmid_ds *shmseg; | 837 | struct shmid_ds *shmseg; | |
838 | struct uvm_object *uobj; | 838 | struct uvm_object *uobj; | |
839 | size_t sz; | 839 | size_t sz; | |
840 | 840 | |||
841 | shmmap_se = SLIST_FIRST(&shmmap_s->entries); | 841 | shmmap_se = SLIST_FIRST(&shmmap_s->entries); | |
842 | KASSERT(shmmap_se != NULL); | 842 | KASSERT(shmmap_se != NULL); | |
843 | 843 | |||
844 | shmseg = &shmsegs[IPCID_TO_IX(shmmap_se->shmid)]; | 844 | shmseg = &shmsegs[IPCID_TO_IX(shmmap_se->shmid)]; | |
845 | sz = (shmseg->shm_segsz + PGOFSET) & ~PGOFSET; | 845 | sz = (shmseg->shm_segsz + PGOFSET) & ~PGOFSET; | |
846 | /* shm_delete_mapping() removes from the list. */ | 846 | /* shm_delete_mapping() removes from the list. */ | |
847 | uobj = shm_delete_mapping(shmmap_s, shmmap_se); | 847 | uobj = shm_delete_mapping(shmmap_s, shmmap_se); | |
848 | mutex_exit(&shm_lock); | 848 | mutex_exit(&shm_lock); | |
849 | 849 | |||
850 | uvm_deallocate(&vm->vm_map, shmmap_se->va, sz); | 850 | uvm_deallocate(&vm->vm_map, shmmap_se->va, sz); | |
851 | if (uobj != NULL) { | 851 | if (uobj != NULL) { | |
852 | uao_detach(uobj); | 852 | uao_detach(uobj); | |
853 | } | 853 | } | |
854 | kmem_free(shmmap_se, sizeof(struct shmmap_entry)); | 854 | kmem_free(shmmap_se, sizeof(struct shmmap_entry)); | |
855 | 855 | |||
856 | if (SLIST_EMPTY(&shmmap_s->entries)) { | 856 | if (SLIST_EMPTY(&shmmap_s->entries)) { | |
857 | break; | 857 | break; | |
858 | } | 858 | } | |
859 | mutex_enter(&shm_lock); | 859 | mutex_enter(&shm_lock); | |
860 | KASSERT(!SLIST_EMPTY(&shmmap_s->entries)); | 860 | KASSERT(!SLIST_EMPTY(&shmmap_s->entries)); | |
861 | } | 861 | } | |
862 | kmem_free(shmmap_s, sizeof(struct shmmap_state)); | 862 | kmem_free(shmmap_s, sizeof(struct shmmap_state)); | |
863 | } | 863 | } | |
864 | 864 | |||
865 | static int | 865 | static int | |
866 | shmrealloc(int newshmni) | 866 | shmrealloc(int newshmni) | |
867 | { | 867 | { | |
868 | vaddr_t v; | 868 | vaddr_t v; | |
869 | struct shmid_ds *oldshmsegs, *newshmsegs; | 869 | struct shmid_ds *oldshmsegs, *newshmsegs; | |
870 | kcondvar_t *newshm_cv, *oldshm_cv; | 870 | kcondvar_t *newshm_cv, *oldshm_cv; | |
871 | size_t sz; | 871 | size_t sz; | |
872 | int i, lsegid, oldshmni; | 872 | int i, lsegid, oldshmni; | |
873 | 873 | |||
874 | if (newshmni < 1) | 874 | if (newshmni < 1) | |
875 | return EINVAL; | 875 | return EINVAL; | |
876 | 876 | |||
877 | /* Allocate new memory area */ | 877 | /* Allocate new memory area */ | |
878 | sz = ALIGN(newshmni * sizeof(struct shmid_ds)) + | 878 | sz = ALIGN(newshmni * sizeof(struct shmid_ds)) + | |
879 | ALIGN(newshmni * sizeof(kcondvar_t)); | 879 | ALIGN(newshmni * sizeof(kcondvar_t)); | |
880 | sz = round_page(sz); | 880 | sz = round_page(sz); | |
881 | v = uvm_km_alloc(kernel_map, sz, 0, UVM_KMF_WIRED|UVM_KMF_ZERO); | 881 | v = uvm_km_alloc(kernel_map, sz, 0, UVM_KMF_WIRED|UVM_KMF_ZERO); | |
882 | if (v == 0) | 882 | if (v == 0) | |
883 | return ENOMEM; | 883 | return ENOMEM; | |
884 | 884 | |||
885 | mutex_enter(&shm_lock); | 885 | mutex_enter(&shm_lock); | |
886 | while (shm_realloc_state || shm_realloc_disable) | 886 | while (shm_realloc_state || shm_realloc_disable) | |
887 | cv_wait(&shm_realloc_cv, &shm_lock); | 887 | cv_wait(&shm_realloc_cv, &shm_lock); | |
888 | 888 | |||
889 | /* | 889 | /* | |
890 | * Get the number of last segment. Fail we are trying to | 890 | * Get the number of last segment. Fail we are trying to | |
891 | * reallocate less memory than we use. | 891 | * reallocate less memory than we use. | |
892 | */ | 892 | */ | |
893 | lsegid = 0; | 893 | lsegid = 0; | |
894 | for (i = 0; i < shminfo.shmmni; i++) | 894 | for (i = 0; i < shminfo.shmmni; i++) | |
895 | if ((shmsegs[i].shm_perm.mode & SHMSEG_FREE) == 0) | 895 | if ((shmsegs[i].shm_perm.mode & SHMSEG_FREE) == 0) | |
896 | lsegid = i; | 896 | lsegid = i; | |
897 | if (lsegid >= newshmni) { | 897 | if (lsegid >= newshmni) { | |
898 | mutex_exit(&shm_lock); | 898 | mutex_exit(&shm_lock); | |
899 | uvm_km_free(kernel_map, v, sz, UVM_KMF_WIRED); | 899 | uvm_km_free(kernel_map, v, sz, UVM_KMF_WIRED); | |
900 | return EBUSY; | 900 | return EBUSY; | |
901 | } | 901 | } | |
902 | shm_realloc_state = true; | 902 | shm_realloc_state = true; | |
903 | 903 | |||
904 | newshmsegs = (void *)v; | 904 | newshmsegs = (void *)v; | |
905 | newshm_cv = (void *)((uintptr_t)newshmsegs + | 905 | newshm_cv = (void *)((uintptr_t)newshmsegs + | |
906 | ALIGN(newshmni * sizeof(struct shmid_ds))); | 906 | ALIGN(newshmni * sizeof(struct shmid_ds))); | |
907 | 907 | |||
908 | /* Copy all memory to the new area */ | 908 | /* Copy all memory to the new area */ | |
909 | for (i = 0; i < shm_nused; i++) | 909 | for (i = 0; i < shm_nused; i++) | |
910 | (void)memcpy(&newshmsegs[i], &shmsegs[i], | 910 | (void)memcpy(&newshmsegs[i], &shmsegs[i], | |
911 | sizeof(newshmsegs[0])); | 911 | sizeof(newshmsegs[0])); | |
912 | 912 | |||
913 | /* Mark as free all new segments, if there is any */ | 913 | /* Mark as free all new segments, if there is any */ | |
914 | for (; i < newshmni; i++) { | 914 | for (; i < newshmni; i++) { | |
915 | cv_init(&newshm_cv[i], "shmwait"); | 915 | cv_init(&newshm_cv[i], "shmwait"); | |
916 | newshmsegs[i].shm_perm.mode = SHMSEG_FREE; | 916 | newshmsegs[i].shm_perm.mode = SHMSEG_FREE; | |
917 | newshmsegs[i].shm_perm._seq = 0; | 917 | newshmsegs[i].shm_perm._seq = 0; | |
918 | } | 918 | } | |
919 | 919 | |||
920 | oldshmsegs = shmsegs; | 920 | oldshmsegs = shmsegs; | |
921 | oldshmni = shminfo.shmmni; | 921 | oldshmni = shminfo.shmmni; | |
922 | shminfo.shmmni = newshmni; | 922 | shminfo.shmmni = newshmni; | |
923 | shmsegs = newshmsegs; | 923 | shmsegs = newshmsegs; | |
924 | shm_cv = newshm_cv; | 924 | shm_cv = newshm_cv; | |
925 | 925 | |||
926 | /* Reallocation completed - notify all waiters, if any */ | 926 | /* Reallocation completed - notify all waiters, if any */ | |
927 | shm_realloc_state = false; | 927 | shm_realloc_state = false; | |
928 | cv_broadcast(&shm_realloc_cv); | 928 | cv_broadcast(&shm_realloc_cv); | |
929 | mutex_exit(&shm_lock); | 929 | mutex_exit(&shm_lock); | |
930 | 930 | |||
931 | /* Release now unused resources. */ | 931 | /* Release now unused resources. */ | |
932 | oldshm_cv = (void *)((uintptr_t)oldshmsegs + | 932 | oldshm_cv = (void *)((uintptr_t)oldshmsegs + | |
933 | ALIGN(oldshmni * sizeof(struct shmid_ds))); | 933 | ALIGN(oldshmni * sizeof(struct shmid_ds))); | |
934 | for (i = 0; i < oldshmni; i++) | 934 | for (i = 0; i < oldshmni; i++) | |
935 | cv_destroy(&oldshm_cv[i]); | 935 | cv_destroy(&oldshm_cv[i]); | |
936 | 936 | |||
937 | sz = ALIGN(oldshmni * sizeof(struct shmid_ds)) + | 937 | sz = ALIGN(oldshmni * sizeof(struct shmid_ds)) + | |
938 | ALIGN(oldshmni * sizeof(kcondvar_t)); | 938 | ALIGN(oldshmni * sizeof(kcondvar_t)); | |
939 | sz = round_page(sz); | 939 | sz = round_page(sz); | |
940 | uvm_km_free(kernel_map, (vaddr_t)oldshmsegs, sz, UVM_KMF_WIRED); | 940 | uvm_km_free(kernel_map, (vaddr_t)oldshmsegs, sz, UVM_KMF_WIRED); | |
941 | 941 | |||
942 | return 0; | 942 | return 0; | |
943 | } | 943 | } | |
944 | 944 | |||
945 | void | 945 | void | |
946 | shminit(void) | 946 | shminit(void) | |
947 | { | 947 | { | |
948 | vaddr_t v; | 948 | vaddr_t v; | |
949 | size_t sz; | 949 | size_t sz; | |
950 | int i; | 950 | int i; | |
951 | 951 | |||
952 | mutex_init(&shm_lock, MUTEX_DEFAULT, IPL_NONE); | 952 | mutex_init(&shm_lock, MUTEX_DEFAULT, IPL_NONE); | |
953 | cv_init(&shm_realloc_cv, "shmrealc"); | 953 | cv_init(&shm_realloc_cv, "shmrealc"); | |
954 | 954 | |||
955 | /* Allocate the wired memory for our structures */ | 955 | /* Allocate the wired memory for our structures */ | |
956 | sz = ALIGN(shminfo.shmmni * sizeof(struct shmid_ds)) + | 956 | sz = ALIGN(shminfo.shmmni * sizeof(struct shmid_ds)) + | |
957 | ALIGN(shminfo.shmmni * sizeof(kcondvar_t)); | 957 | ALIGN(shminfo.shmmni * sizeof(kcondvar_t)); | |
958 | sz = round_page(sz); | 958 | sz = round_page(sz); | |
959 | v = uvm_km_alloc(kernel_map, sz, 0, UVM_KMF_WIRED|UVM_KMF_ZERO); | 959 | v = uvm_km_alloc(kernel_map, sz, 0, UVM_KMF_WIRED|UVM_KMF_ZERO); | |
960 | if (v == 0) | 960 | if (v == 0) | |
961 | panic("sysv_shm: cannot allocate memory"); | 961 | panic("sysv_shm: cannot allocate memory"); | |
962 | shmsegs = (void *)v; | 962 | shmsegs = (void *)v; | |
963 | shm_cv = (void *)((uintptr_t)shmsegs + | 963 | shm_cv = (void *)((uintptr_t)shmsegs + | |
964 | ALIGN(shminfo.shmmni * sizeof(struct shmid_ds))); | 964 | ALIGN(shminfo.shmmni * sizeof(struct shmid_ds))); | |
965 | 965 | |||
966 | if (shminfo.shmmax == 0) | 966 | if (shminfo.shmmax == 0) | |
967 | shminfo.shmmax = max(physmem / 4, 1024) * PAGE_SIZE; | 967 | shminfo.shmmax = max(physmem / 4, 1024) * PAGE_SIZE; | |
968 | else | 968 | else | |
969 | shminfo.shmmax *= PAGE_SIZE; | 969 | shminfo.shmmax *= PAGE_SIZE; | |
970 | shminfo.shmall = shminfo.shmmax / PAGE_SIZE; | 970 | shminfo.shmall = shminfo.shmmax / PAGE_SIZE; | |
971 | 971 | |||
972 | for (i = 0; i < shminfo.shmmni; i++) { | 972 | for (i = 0; i < shminfo.shmmni; i++) { | |
973 | cv_init(&shm_cv[i], "shmwait"); | 973 | cv_init(&shm_cv[i], "shmwait"); | |
974 | shmsegs[i].shm_perm.mode = SHMSEG_FREE; | 974 | shmsegs[i].shm_perm.mode = SHMSEG_FREE; | |
975 | shmsegs[i].shm_perm._seq = 0; | 975 | shmsegs[i].shm_perm._seq = 0; | |
976 | } | 976 | } | |
977 | shm_last_free = 0; | 977 | shm_last_free = 0; | |
978 | shm_nused = 0; | 978 | shm_nused = 0; | |
979 | shm_committed = 0; | 979 | shm_committed = 0; | |
980 | shm_realloc_disable = 0; | 980 | shm_realloc_disable = 0; | |
981 | shm_realloc_state = false; | 981 | shm_realloc_state = false; | |
982 | } | 982 | } | |
983 | 983 | |||
984 | static int | 984 | static int | |
985 | sysctl_ipc_shmmni(SYSCTLFN_ARGS) | 985 | sysctl_ipc_shmmni(SYSCTLFN_ARGS) | |
986 | { | 986 | { | |
987 | int newsize, error; | 987 | int newsize, error; | |
988 | struct sysctlnode node; | 988 | struct sysctlnode node; | |
989 | node = *rnode; | 989 | node = *rnode; | |
990 | node.sysctl_data = &newsize; | 990 | node.sysctl_data = &newsize; | |
991 | 991 | |||
992 | newsize = shminfo.shmmni; | 992 | newsize = shminfo.shmmni; | |
993 | error = sysctl_lookup(SYSCTLFN_CALL(&node)); | 993 | error = sysctl_lookup(SYSCTLFN_CALL(&node)); | |
994 | if (error || newp == NULL) | 994 | if (error || newp == NULL) | |
995 | return error; | 995 | return error; | |
996 | 996 | |||
997 | sysctl_unlock(); | 997 | sysctl_unlock(); | |
998 | error = shmrealloc(newsize); | 998 | error = shmrealloc(newsize); | |
999 | sysctl_relock(); | 999 | sysctl_relock(); | |
1000 | return error; | 1000 | return error; | |
1001 | } | 1001 | } | |
1002 | 1002 | |||
1003 | static int | 1003 | static int | |
1004 | sysctl_ipc_shmmaxpgs(SYSCTLFN_ARGS) | 1004 | sysctl_ipc_shmmaxpgs(SYSCTLFN_ARGS) | |
1005 | { | 1005 | { | |
1006 | uint32_t newsize; | 1006 | uint32_t newsize; | |
1007 | int error; | 1007 | int error; | |
1008 | struct sysctlnode node; | 1008 | struct sysctlnode node; | |
1009 | node = *rnode; | 1009 | node = *rnode; | |
1010 | node.sysctl_data = &newsize; | 1010 | node.sysctl_data = &newsize; | |
1011 | 1011 | |||
1012 | newsize = shminfo.shmall; | 1012 | newsize = shminfo.shmall; | |
1013 | error = sysctl_lookup(SYSCTLFN_CALL(&node)); | 1013 | error = sysctl_lookup(SYSCTLFN_CALL(&node)); | |
1014 | if (error || newp == NULL) | 1014 | if (error || newp == NULL) | |
1015 | return error; | 1015 | return error; | |
1016 | 1016 | |||
1017 | if (newsize < 1) | 1017 | if (newsize < 1) | |
1018 | return EINVAL; | 1018 | return EINVAL; | |
1019 | 1019 | |||
1020 | shminfo.shmall = newsize; | 1020 | shminfo.shmall = newsize; | |
1021 | shminfo.shmmax = (uint64_t)shminfo.shmall * PAGE_SIZE; | 1021 | shminfo.shmmax = (uint64_t)shminfo.shmall * PAGE_SIZE; | |
1022 | 1022 | |||
1023 | return 0; | 1023 | return 0; | |
1024 | } | 1024 | } | |
1025 | 1025 | |||
1026 | static int | 1026 | static int | |
1027 | sysctl_ipc_shmmax(SYSCTLFN_ARGS) | 1027 | sysctl_ipc_shmmax(SYSCTLFN_ARGS) | |
1028 | { | 1028 | { | |
1029 | uint64_t newsize; | 1029 | uint64_t newsize; | |
1030 | int error; | 1030 | int error; | |
1031 | struct sysctlnode node; | 1031 | struct sysctlnode node; | |
1032 | node = *rnode; | 1032 | node = *rnode; | |
1033 | node.sysctl_data = &newsize; | 1033 | node.sysctl_data = &newsize; | |
1034 | 1034 | |||
1035 | newsize = shminfo.shmmax; | 1035 | newsize = shminfo.shmmax; | |
1036 | error = sysctl_lookup(SYSCTLFN_CALL(&node)); | 1036 | error = sysctl_lookup(SYSCTLFN_CALL(&node)); | |
1037 | if (error || newp == NULL) | 1037 | if (error || newp == NULL) | |
1038 | return error; | 1038 | return error; | |
1039 | 1039 | |||
1040 | if (newsize < PAGE_SIZE) | 1040 | if (newsize < PAGE_SIZE) | |
1041 | return EINVAL; | 1041 | return EINVAL; | |
1042 | 1042 | |||
1043 | shminfo.shmmax = round_page(newsize); | 1043 | shminfo.shmmax = round_page(newsize); | |
1044 | shminfo.shmall = shminfo.shmmax >> PAGE_SHIFT; | 1044 | shminfo.shmall = shminfo.shmmax >> PAGE_SHIFT; | |
1045 | 1045 | |||
1046 | return 0; | 1046 | return 0; | |
1047 | } | 1047 | } | |
1048 | 1048 | |||
1049 | SYSCTL_SETUP(sysctl_ipc_shm_setup, "sysctl kern.ipc subtree setup") | 1049 | SYSCTL_SETUP(sysctl_ipc_shm_setup, "sysctl kern.ipc subtree setup") | |
1050 | { | 1050 | { | |
1051 | 1051 | |||
1052 | sysctl_createv(clog, 0, NULL, NULL, | 1052 | sysctl_createv(clog, 0, NULL, NULL, | |
1053 | CTLFLAG_PERMANENT, | 1053 | CTLFLAG_PERMANENT, | |
1054 | CTLTYPE_NODE, "kern", NULL, | 1054 | CTLTYPE_NODE, "kern", NULL, | |
1055 | NULL, 0, NULL, 0, | 1055 | NULL, 0, NULL, 0, | |
1056 | CTL_KERN, CTL_EOL); | 1056 | CTL_KERN, CTL_EOL); | |
1057 | sysctl_createv(clog, 0, NULL, NULL, | 1057 | sysctl_createv(clog, 0, NULL, NULL, | |
1058 | CTLFLAG_PERMANENT, | 1058 | CTLFLAG_PERMANENT, | |
1059 | CTLTYPE_NODE, "ipc", | 1059 | CTLTYPE_NODE, "ipc", | |
1060 | SYSCTL_DESCR("SysV IPC options"), | 1060 | SYSCTL_DESCR("SysV IPC options"), | |
1061 | NULL, 0, NULL, 0, | 1061 | NULL, 0, NULL, 0, | |
1062 | CTL_KERN, KERN_SYSVIPC, CTL_EOL); | 1062 | CTL_KERN, KERN_SYSVIPC, CTL_EOL); | |
1063 | sysctl_createv(clog, 0, NULL, NULL, | 1063 | sysctl_createv(clog, 0, NULL, NULL, | |
1064 | CTLFLAG_PERMANENT | CTLFLAG_READWRITE, | 1064 | CTLFLAG_PERMANENT | CTLFLAG_READWRITE, | |
1065 | CTLTYPE_QUAD, "shmmax", | 1065 | CTLTYPE_QUAD, "shmmax", | |
1066 | SYSCTL_DESCR("Max shared memory segment size in bytes"), | 1066 | SYSCTL_DESCR("Max shared memory segment size in bytes"), | |
1067 | sysctl_ipc_shmmax, 0, &shminfo.shmmax, 0, | 1067 | sysctl_ipc_shmmax, 0, &shminfo.shmmax, 0, | |
1068 | CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_SHMMAX, CTL_EOL); | 1068 | CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_SHMMAX, CTL_EOL); | |
1069 | sysctl_createv(clog, 0, NULL, NULL, | 1069 | sysctl_createv(clog, 0, NULL, NULL, | |
1070 | CTLFLAG_PERMANENT | CTLFLAG_READWRITE, | 1070 | CTLFLAG_PERMANENT | CTLFLAG_READWRITE, | |
1071 | CTLTYPE_INT, "shmmni", | 1071 | CTLTYPE_INT, "shmmni", | |
1072 | SYSCTL_DESCR("Max number of shared memory identifiers"), | 1072 | SYSCTL_DESCR("Max number of shared memory identifiers"), | |
1073 | sysctl_ipc_shmmni, 0, &shminfo.shmmni, 0, | 1073 | sysctl_ipc_shmmni, 0, &shminfo.shmmni, 0, | |
1074 | CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_SHMMNI, CTL_EOL); | 1074 | CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_SHMMNI, CTL_EOL); | |
1075 | sysctl_createv(clog, 0, NULL, NULL, | 1075 | sysctl_createv(clog, 0, NULL, NULL, | |
1076 | CTLFLAG_PERMANENT | CTLFLAG_READWRITE, | 1076 | CTLFLAG_PERMANENT | CTLFLAG_READWRITE, | |
1077 | CTLTYPE_INT, "shmseg", | 1077 | CTLTYPE_INT, "shmseg", | |
1078 | SYSCTL_DESCR("Max shared memory segments per process"), | 1078 | SYSCTL_DESCR("Max shared memory segments per process"), | |
1079 | NULL, 0, &shminfo.shmseg, 0, | 1079 | NULL, 0, &shminfo.shmseg, 0, | |
1080 | CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_SHMSEG, CTL_EOL); | 1080 | CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_SHMSEG, CTL_EOL); | |
1081 | sysctl_createv(clog, 0, NULL, NULL, | 1081 | sysctl_createv(clog, 0, NULL, NULL, | |
1082 | CTLFLAG_PERMANENT | CTLFLAG_READWRITE, | 1082 | CTLFLAG_PERMANENT | CTLFLAG_READWRITE, | |
1083 | CTLTYPE_INT, "shmmaxpgs", | 1083 | CTLTYPE_INT, "shmmaxpgs", | |
1084 | SYSCTL_DESCR("Max amount of shared memory in pages"), | 1084 | SYSCTL_DESCR("Max amount of shared memory in pages"), | |
1085 | sysctl_ipc_shmmaxpgs, 0, &shminfo.shmall, 0, | 1085 | sysctl_ipc_shmmaxpgs, 0, &shminfo.shmall, 0, | |
1086 | CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_SHMMAXPGS, CTL_EOL); | 1086 | CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_SHMMAXPGS, CTL_EOL); | |
1087 | sysctl_createv(clog, 0, NULL, NULL, | 1087 | sysctl_createv(clog, 0, NULL, NULL, | |
1088 | CTLFLAG_PERMANENT | CTLFLAG_READWRITE, | 1088 | CTLFLAG_PERMANENT | CTLFLAG_READWRITE, | |
1089 | CTLTYPE_INT, "shm_use_phys", | 1089 | CTLTYPE_INT, "shm_use_phys", | |
1090 | SYSCTL_DESCR("Enable/disable locking of shared memory in " | 1090 | SYSCTL_DESCR("Enable/disable locking of shared memory in " | |
1091 | "physical memory"), NULL, 0, &shm_use_phys, 0, | 1091 | "physical memory"), NULL, 0, &shm_use_phys, 0, | |
1092 | CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_SHMUSEPHYS, CTL_EOL); | 1092 | CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_SHMUSEPHYS, CTL_EOL); | |
1093 | } | 1093 | } |
--- src/sys/uvm/uvm_extern.h 2011/06/16 09:21:03 1.174
+++ src/sys/uvm/uvm_extern.h 2011/08/27 09:11:53 1.175
@@ -1,771 +1,772 @@ | @@ -1,771 +1,772 @@ | |||
1 | /* $NetBSD: uvm_extern.h,v 1.174 2011/06/16 09:21:03 hannken Exp $ */ | 1 | /* $NetBSD: uvm_extern.h,v 1.175 2011/08/27 09:11:53 christos Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1997 Charles D. Cranor and Washington University. | 4 | * Copyright (c) 1997 Charles D. Cranor and Washington University. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
15 | * | 15 | * | |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 | * | 26 | * | |
27 | * from: Id: uvm_extern.h,v 1.1.2.21 1998/02/07 01:16:53 chs Exp | 27 | * from: Id: uvm_extern.h,v 1.1.2.21 1998/02/07 01:16:53 chs Exp | |
28 | */ | 28 | */ | |
29 | 29 | |||
30 | /*- | 30 | /*- | |
31 | * Copyright (c) 1991, 1992, 1993 | 31 | * Copyright (c) 1991, 1992, 1993 | |
32 | * The Regents of the University of California. All rights reserved. | 32 | * The Regents of the University of California. All rights reserved. | |
33 | * | 33 | * | |
34 | * Redistribution and use in source and binary forms, with or without | 34 | * Redistribution and use in source and binary forms, with or without | |
35 | * modification, are permitted provided that the following conditions | 35 | * modification, are permitted provided that the following conditions | |
36 | * are met: | 36 | * are met: | |
37 | * 1. Redistributions of source code must retain the above copyright | 37 | * 1. Redistributions of source code must retain the above copyright | |
38 | * notice, this list of conditions and the following disclaimer. | 38 | * notice, this list of conditions and the following disclaimer. | |
39 | * 2. Redistributions in binary form must reproduce the above copyright | 39 | * 2. Redistributions in binary form must reproduce the above copyright | |
40 | * notice, this list of conditions and the following disclaimer in the | 40 | * notice, this list of conditions and the following disclaimer in the | |
41 | * documentation and/or other materials provided with the distribution. | 41 | * documentation and/or other materials provided with the distribution. | |
42 | * 3. Neither the name of the University nor the names of its contributors | 42 | * 3. Neither the name of the University nor the names of its contributors | |
43 | * may be used to endorse or promote products derived from this software | 43 | * may be used to endorse or promote products derived from this software | |
44 | * without specific prior written permission. | 44 | * without specific prior written permission. | |
45 | * | 45 | * | |
46 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 46 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
47 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 47 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
48 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 48 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
49 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 49 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
50 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 50 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
51 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 51 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
52 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 52 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
53 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 53 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
54 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 54 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
55 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 55 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
56 | * SUCH DAMAGE. | 56 | * SUCH DAMAGE. | |
57 | * | 57 | * | |
58 | * @(#)vm_extern.h 8.5 (Berkeley) 5/3/95 | 58 | * @(#)vm_extern.h 8.5 (Berkeley) 5/3/95 | |
59 | */ | 59 | */ | |
60 | 60 | |||
61 | #ifndef _UVM_UVM_EXTERN_H_ | 61 | #ifndef _UVM_UVM_EXTERN_H_ | |
62 | #define _UVM_UVM_EXTERN_H_ | 62 | #define _UVM_UVM_EXTERN_H_ | |
63 | 63 | |||
64 | /* | 64 | /* | |
65 | * uvm_extern.h: this file defines the external interface to the VM system. | 65 | * uvm_extern.h: this file defines the external interface to the VM system. | |
66 | * | 66 | * | |
67 | * this should be the only file included by non-VM parts of the kernel | 67 | * this should be the only file included by non-VM parts of the kernel | |
68 | * which need access to VM services. if you want to know the interface | 68 | * which need access to VM services. if you want to know the interface | |
69 | * to the MI VM layer without knowing the details, this is the file to | 69 | * to the MI VM layer without knowing the details, this is the file to | |
70 | * learn. | 70 | * learn. | |
71 | * | 71 | * | |
72 | * NOTE: vm system calls are prototyped in syscallargs.h | 72 | * NOTE: vm system calls are prototyped in syscallargs.h | |
73 | */ | 73 | */ | |
74 | 74 | |||
75 | /* | 75 | /* | |
76 | * typedefs, necessary for standard UVM headers. | 76 | * typedefs, necessary for standard UVM headers. | |
77 | */ | 77 | */ | |
78 | 78 | |||
79 | typedef unsigned int uvm_flag_t; | 79 | typedef unsigned int uvm_flag_t; | |
80 | 80 | |||
81 | typedef int vm_inherit_t; /* XXX: inheritance codes */ | 81 | typedef int vm_inherit_t; /* XXX: inheritance codes */ | |
82 | typedef off_t voff_t; /* XXX: offset within a uvm_object */ | 82 | typedef off_t voff_t; /* XXX: offset within a uvm_object */ | |
83 | typedef voff_t pgoff_t; /* XXX: number of pages within a uvm object */ | 83 | typedef voff_t pgoff_t; /* XXX: number of pages within a uvm object */ | |
84 | 84 | |||
85 | /* | 85 | /* | |
86 | * defines | 86 | * defines | |
87 | */ | 87 | */ | |
88 | 88 | |||
89 | /* | 89 | /* | |
90 | * the following defines are for uvm_map and functions which call it. | 90 | * the following defines are for uvm_map and functions which call it. | |
91 | */ | 91 | */ | |
92 | 92 | |||
93 | /* protections bits */ | 93 | /* protections bits */ | |
94 | #define UVM_PROT_MASK 0x07 /* protection mask */ | 94 | #define UVM_PROT_MASK 0x07 /* protection mask */ | |
95 | #define UVM_PROT_NONE 0x00 /* protection none */ | 95 | #define UVM_PROT_NONE 0x00 /* protection none */ | |
96 | #define UVM_PROT_ALL 0x07 /* everything */ | 96 | #define UVM_PROT_ALL 0x07 /* everything */ | |
97 | #define UVM_PROT_READ 0x01 /* read */ | 97 | #define UVM_PROT_READ 0x01 /* read */ | |
98 | #define UVM_PROT_WRITE 0x02 /* write */ | 98 | #define UVM_PROT_WRITE 0x02 /* write */ | |
99 | #define UVM_PROT_EXEC 0x04 /* exec */ | 99 | #define UVM_PROT_EXEC 0x04 /* exec */ | |
100 | 100 | |||
101 | /* protection short codes */ | 101 | /* protection short codes */ | |
102 | #define UVM_PROT_R 0x01 /* read */ | 102 | #define UVM_PROT_R 0x01 /* read */ | |
103 | #define UVM_PROT_W 0x02 /* write */ | 103 | #define UVM_PROT_W 0x02 /* write */ | |
104 | #define UVM_PROT_RW 0x03 /* read-write */ | 104 | #define UVM_PROT_RW 0x03 /* read-write */ | |
105 | #define UVM_PROT_X 0x04 /* exec */ | 105 | #define UVM_PROT_X 0x04 /* exec */ | |
106 | #define UVM_PROT_RX 0x05 /* read-exec */ | 106 | #define UVM_PROT_RX 0x05 /* read-exec */ | |
107 | #define UVM_PROT_WX 0x06 /* write-exec */ | 107 | #define UVM_PROT_WX 0x06 /* write-exec */ | |
108 | #define UVM_PROT_RWX 0x07 /* read-write-exec */ | 108 | #define UVM_PROT_RWX 0x07 /* read-write-exec */ | |
109 | 109 | |||
110 | /* 0x08: not used */ | 110 | /* 0x08: not used */ | |
111 | 111 | |||
112 | /* inherit codes */ | 112 | /* inherit codes */ | |
113 | #define UVM_INH_MASK 0x30 /* inherit mask */ | 113 | #define UVM_INH_MASK 0x30 /* inherit mask */ | |
114 | #define UVM_INH_SHARE 0x00 /* "share" */ | 114 | #define UVM_INH_SHARE 0x00 /* "share" */ | |
115 | #define UVM_INH_COPY 0x10 /* "copy" */ | 115 | #define UVM_INH_COPY 0x10 /* "copy" */ | |
116 | #define UVM_INH_NONE 0x20 /* "none" */ | 116 | #define UVM_INH_NONE 0x20 /* "none" */ | |
117 | #define UVM_INH_DONATE 0x30 /* "donate" << not used */ | 117 | #define UVM_INH_DONATE 0x30 /* "donate" << not used */ | |
118 | 118 | |||
119 | /* 0x40, 0x80: not used */ | 119 | /* 0x40, 0x80: not used */ | |
120 | 120 | |||
121 | /* bits 0x700: max protection, 0x800: not used */ | 121 | /* bits 0x700: max protection, 0x800: not used */ | |
122 | 122 | |||
123 | /* bits 0x7000: advice, 0x8000: not used */ | 123 | /* bits 0x7000: advice, 0x8000: not used */ | |
124 | /* advice: matches MADV_* from sys/mman.h and POSIX_FADV_* from sys/fcntl.h */ | 124 | /* advice: matches MADV_* from sys/mman.h and POSIX_FADV_* from sys/fcntl.h */ | |
125 | #define UVM_ADV_NORMAL 0x0 /* 'normal' */ | 125 | #define UVM_ADV_NORMAL 0x0 /* 'normal' */ | |
126 | #define UVM_ADV_RANDOM 0x1 /* 'random' */ | 126 | #define UVM_ADV_RANDOM 0x1 /* 'random' */ | |
127 | #define UVM_ADV_SEQUENTIAL 0x2 /* 'sequential' */ | 127 | #define UVM_ADV_SEQUENTIAL 0x2 /* 'sequential' */ | |
128 | #define UVM_ADV_WILLNEED 0x3 /* pages will be needed */ | 128 | #define UVM_ADV_WILLNEED 0x3 /* pages will be needed */ | |
129 | #define UVM_ADV_DONTNEED 0x4 /* pages won't be needed */ | 129 | #define UVM_ADV_DONTNEED 0x4 /* pages won't be needed */ | |
130 | #define UVM_ADV_NOREUSE 0x5 /* pages will be used only once */ | 130 | #define UVM_ADV_NOREUSE 0x5 /* pages will be used only once */ | |
131 | #define UVM_ADV_MASK 0x7 /* mask */ | 131 | #define UVM_ADV_MASK 0x7 /* mask */ | |
132 | 132 | |||
133 | /* bits 0xffff0000: mapping flags */ | 133 | /* bits 0xffff0000: mapping flags */ | |
134 | #define UVM_FLAG_FIXED 0x010000 /* find space */ | 134 | #define UVM_FLAG_FIXED 0x010000 /* find space */ | |
135 | #define UVM_FLAG_OVERLAY 0x020000 /* establish overlay */ | 135 | #define UVM_FLAG_OVERLAY 0x020000 /* establish overlay */ | |
136 | #define UVM_FLAG_NOMERGE 0x040000 /* don't merge map entries */ | 136 | #define UVM_FLAG_NOMERGE 0x040000 /* don't merge map entries */ | |
137 | #define UVM_FLAG_COPYONW 0x080000 /* set copy_on_write flag */ | 137 | #define UVM_FLAG_COPYONW 0x080000 /* set copy_on_write flag */ | |
138 | #define UVM_FLAG_AMAPPAD 0x100000 /* for bss: pad amap to reduce allocations */ | 138 | #define UVM_FLAG_AMAPPAD 0x100000 /* for bss: pad amap to reduce allocations */ | |
139 | #define UVM_FLAG_TRYLOCK 0x200000 /* fail if we can not lock map */ | 139 | #define UVM_FLAG_TRYLOCK 0x200000 /* fail if we can not lock map */ | |
140 | #define UVM_FLAG_NOWAIT 0x400000 /* not allowed to sleep */ | 140 | #define UVM_FLAG_NOWAIT 0x400000 /* not allowed to sleep */ | |
141 | #define UVM_FLAG_QUANTUM 0x800000 /* entry can never be split later */ | 141 | #define UVM_FLAG_QUANTUM 0x800000 /* entry can never be split later */ | |
142 | #define UVM_FLAG_WAITVA 0x1000000 /* wait for va */ | 142 | #define UVM_FLAG_WAITVA 0x1000000 /* wait for va */ | |
143 | #define UVM_FLAG_VAONLY 0x2000000 /* unmap: no pages are mapped */ | 143 | #define UVM_FLAG_VAONLY 0x2000000 /* unmap: no pages are mapped */ | |
144 | #define UVM_FLAG_COLORMATCH 0x4000000 /* match color given in off */ | 144 | #define UVM_FLAG_COLORMATCH 0x4000000 /* match color given in off */ | |
145 | 145 | |||
146 | /* macros to extract info */ | 146 | /* macros to extract info */ | |
147 | #define UVM_PROTECTION(X) ((X) & UVM_PROT_MASK) | 147 | #define UVM_PROTECTION(X) ((X) & UVM_PROT_MASK) | |
148 | #define UVM_INHERIT(X) (((X) & UVM_INH_MASK) >> 4) | 148 | #define UVM_INHERIT(X) (((X) & UVM_INH_MASK) >> 4) | |
149 | #define UVM_MAXPROTECTION(X) (((X) >> 8) & UVM_PROT_MASK) | 149 | #define UVM_MAXPROTECTION(X) (((X) >> 8) & UVM_PROT_MASK) | |
150 | #define UVM_ADVICE(X) (((X) >> 12) & UVM_ADV_MASK) | 150 | #define UVM_ADVICE(X) (((X) >> 12) & UVM_ADV_MASK) | |
151 | 151 | |||
152 | #define UVM_MAPFLAG(PROT,MAXPROT,INH,ADVICE,FLAGS) \ | 152 | #define UVM_MAPFLAG(PROT,MAXPROT,INH,ADVICE,FLAGS) \ | |
153 | (((MAXPROT) << 8)|(PROT)|(INH)|((ADVICE) << 12)|(FLAGS)) | 153 | (((MAXPROT) << 8)|(PROT)|(INH)|((ADVICE) << 12)|(FLAGS)) | |
154 | 154 | |||
155 | /* magic offset value: offset not known(obj) or don't care(!obj) */ | 155 | /* magic offset value: offset not known(obj) or don't care(!obj) */ | |
156 | #define UVM_UNKNOWN_OFFSET ((voff_t) -1) | 156 | #define UVM_UNKNOWN_OFFSET ((voff_t) -1) | |
157 | 157 | |||
158 | /* | 158 | /* | |
159 | * the following defines are for uvm_km_alloc/free's flags | 159 | * the following defines are for uvm_km_alloc/free's flags | |
160 | */ | 160 | */ | |
161 | #define UVM_KMF_WIRED 0x1 /* allocation type: wired */ | 161 | #define UVM_KMF_WIRED 0x1 /* allocation type: wired */ | |
162 | #define UVM_KMF_PAGEABLE 0x2 /* allocation type: pageable */ | 162 | #define UVM_KMF_PAGEABLE 0x2 /* allocation type: pageable */ | |
163 | #define UVM_KMF_VAONLY 0x4 /* allocation type: VA only */ | 163 | #define UVM_KMF_VAONLY 0x4 /* allocation type: VA only */ | |
164 | #define UVM_KMF_TYPEMASK (UVM_KMF_VAONLY | UVM_KMF_PAGEABLE | UVM_KMF_WIRED) | 164 | #define UVM_KMF_TYPEMASK (UVM_KMF_VAONLY | UVM_KMF_PAGEABLE | UVM_KMF_WIRED) | |
165 | #define UVM_KMF_CANFAIL 0x8 /* caller handles failure */ | 165 | #define UVM_KMF_CANFAIL 0x8 /* caller handles failure */ | |
166 | #define UVM_KMF_ZERO 0x10 /* want zero filled memory */ | 166 | #define UVM_KMF_ZERO 0x10 /* want zero filled memory */ | |
167 | #define UVM_KMF_EXEC 0x20 /* need executable mapping */ | 167 | #define UVM_KMF_EXEC 0x20 /* need executable mapping */ | |
168 | #define UVM_KMF_TRYLOCK UVM_FLAG_TRYLOCK /* try locking only */ | 168 | #define UVM_KMF_TRYLOCK UVM_FLAG_TRYLOCK /* try locking only */ | |
169 | #define UVM_KMF_NOWAIT UVM_FLAG_NOWAIT /* not allowed to sleep */ | 169 | #define UVM_KMF_NOWAIT UVM_FLAG_NOWAIT /* not allowed to sleep */ | |
170 | #define UVM_KMF_WAITVA UVM_FLAG_WAITVA /* sleep for va */ | 170 | #define UVM_KMF_WAITVA UVM_FLAG_WAITVA /* sleep for va */ | |
171 | 171 | |||
172 | /* | 172 | /* | |
173 | * the following defines the strategies for uvm_pagealloc_strat() | 173 | * the following defines the strategies for uvm_pagealloc_strat() | |
174 | */ | 174 | */ | |
175 | #define UVM_PGA_STRAT_NORMAL 0 /* priority (low id to high) walk */ | 175 | #define UVM_PGA_STRAT_NORMAL 0 /* priority (low id to high) walk */ | |
176 | #define UVM_PGA_STRAT_ONLY 1 /* only specified free list */ | 176 | #define UVM_PGA_STRAT_ONLY 1 /* only specified free list */ | |
177 | #define UVM_PGA_STRAT_FALLBACK 2 /* ONLY falls back on NORMAL */ | 177 | #define UVM_PGA_STRAT_FALLBACK 2 /* ONLY falls back on NORMAL */ | |
178 | 178 | |||
179 | /* | 179 | /* | |
180 | * flags for uvm_pagealloc_strat() | 180 | * flags for uvm_pagealloc_strat() | |
181 | */ | 181 | */ | |
182 | #define UVM_PGA_USERESERVE 0x0001 /* ok to use reserve pages */ | 182 | #define UVM_PGA_USERESERVE 0x0001 /* ok to use reserve pages */ | |
183 | #define UVM_PGA_ZERO 0x0002 /* returned page must be zero'd */ | 183 | #define UVM_PGA_ZERO 0x0002 /* returned page must be zero'd */ | |
184 | 184 | |||
185 | /* | 185 | /* | |
186 | * flags for ubc_alloc() | 186 | * flags for ubc_alloc() | |
187 | */ | 187 | */ | |
188 | #define UBC_READ 0x001 | 188 | #define UBC_READ 0x001 | |
189 | #define UBC_WRITE 0x002 | 189 | #define UBC_WRITE 0x002 | |
190 | #define UBC_FAULTBUSY 0x004 | 190 | #define UBC_FAULTBUSY 0x004 | |
191 | 191 | |||
192 | /* | 192 | /* | |
193 | * flags for ubc_release() | 193 | * flags for ubc_release() | |
194 | */ | 194 | */ | |
195 | #define UBC_UNMAP 0x010 | 195 | #define UBC_UNMAP 0x010 | |
196 | 196 | |||
197 | /* | 197 | /* | |
198 | * flags for ubc_uiomve() | 198 | * flags for ubc_uiomve() | |
199 | */ | 199 | */ | |
200 | #define UBC_PARTIALOK 0x100 | 200 | #define UBC_PARTIALOK 0x100 | |
201 | 201 | |||
202 | /* | 202 | /* | |
203 | * flags for uvn_findpages(). | 203 | * flags for uvn_findpages(). | |
204 | */ | 204 | */ | |
205 | #define UFP_ALL 0x00 | 205 | #define UFP_ALL 0x00 | |
206 | #define UFP_NOWAIT 0x01 | 206 | #define UFP_NOWAIT 0x01 | |
207 | #define UFP_NOALLOC 0x02 | 207 | #define UFP_NOALLOC 0x02 | |
208 | #define UFP_NOCACHE 0x04 | 208 | #define UFP_NOCACHE 0x04 | |
209 | #define UFP_NORDONLY 0x08 | 209 | #define UFP_NORDONLY 0x08 | |
210 | #define UFP_DIRTYONLY 0x10 | 210 | #define UFP_DIRTYONLY 0x10 | |
211 | #define UFP_BACKWARD 0x20 | 211 | #define UFP_BACKWARD 0x20 | |
212 | 212 | |||
213 | /* | 213 | /* | |
214 | * lockflags that control the locking behavior of various functions. | 214 | * lockflags that control the locking behavior of various functions. | |
215 | */ | 215 | */ | |
216 | #define UVM_LK_ENTER 0x00000001 /* map locked on entry */ | 216 | #define UVM_LK_ENTER 0x00000001 /* map locked on entry */ | |
217 | #define UVM_LK_EXIT 0x00000002 /* leave map locked on exit */ | 217 | #define UVM_LK_EXIT 0x00000002 /* leave map locked on exit */ | |
218 | 218 | |||
219 | /* | 219 | /* | |
220 | * Default number of pages to allocate on the stack | 220 | * Default number of pages to allocate on the stack | |
221 | */ | 221 | */ | |
222 | #define UBC_MAX_PAGES 8 | 222 | #define UBC_MAX_PAGES 8 | |
223 | 223 | |||
224 | /* | 224 | /* | |
225 | * Value representing inactive emap. | 225 | * Value representing inactive emap. | |
226 | */ | 226 | */ | |
227 | #define UVM_EMAP_INACTIVE (0) | 227 | #define UVM_EMAP_INACTIVE (0) | |
228 | 228 | |||
229 | /* | 229 | /* | |
230 | * structures | 230 | * structures | |
231 | */ | 231 | */ | |
232 | 232 | |||
233 | struct buf; | 233 | struct buf; | |
234 | struct core; | 234 | struct core; | |
235 | struct loadavg; | 235 | struct loadavg; | |
236 | struct mount; | 236 | struct mount; | |
237 | struct pglist; | 237 | struct pglist; | |
238 | struct proc; | 238 | struct proc; | |
239 | struct uio; | 239 | struct uio; | |
240 | struct uvm_object; | 240 | struct uvm_object; | |
241 | struct vm_anon; | 241 | struct vm_anon; | |
242 | struct vmspace; | 242 | struct vmspace; | |
243 | struct pmap; | 243 | struct pmap; | |
244 | struct vnode; | 244 | struct vnode; | |
245 | struct simplelock; | 245 | struct simplelock; | |
246 | struct vm_map_entry; | 246 | struct vm_map_entry; | |
247 | struct vm_map; | 247 | struct vm_map; | |
248 | struct vm_page; | 248 | struct vm_page; | |
249 | struct vmtotal; | 249 | struct vmtotal; | |
250 | 250 | |||
251 | /* | 251 | /* | |
252 | * uvm_pctparam: parameter to be shown as percentage to user. | 252 | * uvm_pctparam: parameter to be shown as percentage to user. | |
253 | */ | 253 | */ | |
254 | 254 | |||
255 | #define UVM_PCTPARAM_SHIFT 8 | 255 | #define UVM_PCTPARAM_SHIFT 8 | |
256 | #define UVM_PCTPARAM_SCALE (1 << UVM_PCTPARAM_SHIFT) | 256 | #define UVM_PCTPARAM_SCALE (1 << UVM_PCTPARAM_SHIFT) | |
257 | #define UVM_PCTPARAM_APPLY(pct, x) \ | 257 | #define UVM_PCTPARAM_APPLY(pct, x) \ | |
258 | (((x) * (pct)->pct_scaled) >> UVM_PCTPARAM_SHIFT) | 258 | (((x) * (pct)->pct_scaled) >> UVM_PCTPARAM_SHIFT) | |
259 | struct uvm_pctparam { | 259 | struct uvm_pctparam { | |
260 | int pct_pct; /* percent [0, 100] */ /* should be the first member */ | 260 | int pct_pct; /* percent [0, 100] */ /* should be the first member */ | |
261 | int pct_scaled; | 261 | int pct_scaled; | |
262 | int (*pct_check)(struct uvm_pctparam *, int); | 262 | int (*pct_check)(struct uvm_pctparam *, int); | |
263 | }; | 263 | }; | |
264 | 264 | |||
265 | /* | 265 | /* | |
266 | * uvmexp: global data structures that are exported to parts of the kernel | 266 | * uvmexp: global data structures that are exported to parts of the kernel | |
267 | * other than the vm system. | 267 | * other than the vm system. | |
268 | */ | 268 | */ | |
269 | 269 | |||
270 | struct uvmexp { | 270 | struct uvmexp { | |
271 | /* vm_page constants */ | 271 | /* vm_page constants */ | |
272 | int pagesize; /* size of a page (PAGE_SIZE): must be power of 2 */ | 272 | int pagesize; /* size of a page (PAGE_SIZE): must be power of 2 */ | |
273 | int pagemask; /* page mask */ | 273 | int pagemask; /* page mask */ | |
274 | int pageshift; /* page shift */ | 274 | int pageshift; /* page shift */ | |
275 | 275 | |||
276 | /* vm_page counters */ | 276 | /* vm_page counters */ | |
277 | int npages; /* number of pages we manage */ | 277 | int npages; /* number of pages we manage */ | |
278 | int free; /* number of free pages */ | 278 | int free; /* number of free pages */ | |
279 | int paging; /* number of pages in the process of being paged out */ | 279 | int paging; /* number of pages in the process of being paged out */ | |
280 | int wired; /* number of wired pages */ | 280 | int wired; /* number of wired pages */ | |
281 | 281 | |||
282 | /* | 282 | /* | |
283 | * Adding anything before this line will break binary compatibility | 283 | * Adding anything before this line will break binary compatibility | |
284 | * with top(1) on NetBSD 1.5. | 284 | * with top(1) on NetBSD 1.5. | |
285 | */ | 285 | */ | |
286 | 286 | |||
287 | int ncolors; /* number of page color buckets: must be p-o-2 */ | 287 | int ncolors; /* number of page color buckets: must be p-o-2 */ | |
288 | int colormask; /* color bucket mask */ | 288 | int colormask; /* color bucket mask */ | |
289 | 289 | |||
290 | int zeropages; /* number of zero'd pages */ | 290 | int zeropages; /* number of zero'd pages */ | |
291 | int reserve_pagedaemon; /* number of pages reserved for pagedaemon */ | 291 | int reserve_pagedaemon; /* number of pages reserved for pagedaemon */ | |
292 | int reserve_kernel; /* number of pages reserved for kernel */ | 292 | int reserve_kernel; /* number of pages reserved for kernel */ | |
293 | unsigned anonpages; /* number of pages used by anon mappings */ | 293 | unsigned anonpages; /* number of pages used by anon mappings */ | |
294 | unsigned filepages; /* number of pages used by cached file data */ | 294 | unsigned filepages; /* number of pages used by cached file data */ | |
295 | unsigned execpages; /* number of pages used by cached exec data */ | 295 | unsigned execpages; /* number of pages used by cached exec data */ | |
296 | 296 | |||
297 | /* pageout params */ | 297 | /* pageout params */ | |
298 | int freemin; /* min number of free pages */ | 298 | int freemin; /* min number of free pages */ | |
299 | int freetarg; /* target number of free pages */ | 299 | int freetarg; /* target number of free pages */ | |
300 | int wiredmax; /* max number of wired pages */ | 300 | int wiredmax; /* max number of wired pages */ | |
301 | 301 | |||
302 | /* swap */ | 302 | /* swap */ | |
303 | int nswapdev; /* number of configured swap devices in system */ | 303 | int nswapdev; /* number of configured swap devices in system */ | |
304 | int swpages; /* number of PAGE_SIZE'ed swap pages */ | 304 | int swpages; /* number of PAGE_SIZE'ed swap pages */ | |
305 | int swpgavail; /* number of swap pages currently available */ | 305 | int swpgavail; /* number of swap pages currently available */ | |
306 | int swpginuse; /* number of swap pages in use */ | 306 | int swpginuse; /* number of swap pages in use */ | |
307 | int swpgonly; /* number of swap pages in use, not also in RAM */ | 307 | int swpgonly; /* number of swap pages in use, not also in RAM */ | |
308 | int nswget; /* number of times fault calls uvm_swap_get() */ | 308 | int nswget; /* number of times fault calls uvm_swap_get() */ | |
309 | 309 | |||
310 | /* stat counters. XXX: should be 64-bit counters */ | 310 | /* stat counters. XXX: should be 64-bit counters */ | |
311 | int _unused_faults; /* page fault count */ | 311 | int _unused_faults; /* page fault count */ | |
312 | int _unused_traps; /* trap count */ | 312 | int _unused_traps; /* trap count */ | |
313 | int _unused_intrs; /* interrupt count */ | 313 | int _unused_intrs; /* interrupt count */ | |
314 | int _unused_swtch; /* context switch count */ | 314 | int _unused_swtch; /* context switch count */ | |
315 | int _unused_softs; /* software interrupt count */ | 315 | int _unused_softs; /* software interrupt count */ | |
316 | int _unused_syscalls; /* system calls */ | 316 | int _unused_syscalls; /* system calls */ | |
317 | int pageins; /* pagein operation count */ | 317 | int pageins; /* pagein operation count */ | |
318 | /* pageouts are in pdpageouts below */ | 318 | /* pageouts are in pdpageouts below */ | |
319 | int _unused1; | 319 | int _unused1; | |
320 | int _unused2; | 320 | int _unused2; | |
321 | int pgswapin; /* pages swapped in */ | 321 | int pgswapin; /* pages swapped in */ | |
322 | int pgswapout; /* pages swapped out */ | 322 | int pgswapout; /* pages swapped out */ | |
323 | int forks; /* forks */ | 323 | int forks; /* forks */ | |
324 | int forks_ppwait; /* forks where parent waits */ | 324 | int forks_ppwait; /* forks where parent waits */ | |
325 | int forks_sharevm; /* forks where vmspace is shared */ | 325 | int forks_sharevm; /* forks where vmspace is shared */ | |
326 | int pga_zerohit; /* pagealloc where zero wanted and zero | 326 | int pga_zerohit; /* pagealloc where zero wanted and zero | |
327 | was available */ | 327 | was available */ | |
328 | int pga_zeromiss; /* pagealloc where zero wanted and zero | 328 | int pga_zeromiss; /* pagealloc where zero wanted and zero | |
329 | not available */ | 329 | not available */ | |
330 | int zeroaborts; /* number of times page zeroing was | 330 | int zeroaborts; /* number of times page zeroing was | |
331 | aborted */ | 331 | aborted */ | |
332 | int colorhit; /* pagealloc where we got optimal color */ | 332 | int colorhit; /* pagealloc where we got optimal color */ | |
333 | int colormiss; /* pagealloc where we didn't */ | 333 | int colormiss; /* pagealloc where we didn't */ | |
334 | int cpuhit; /* pagealloc where we allocated locally */ | 334 | int cpuhit; /* pagealloc where we allocated locally */ | |
335 | int cpumiss; /* pagealloc where we didn't */ | 335 | int cpumiss; /* pagealloc where we didn't */ | |
336 | 336 | |||
337 | /* fault subcounters. XXX: should be 64-bit counters */ | 337 | /* fault subcounters. XXX: should be 64-bit counters */ | |
338 | int fltnoram; /* number of times fault was out of ram */ | 338 | int fltnoram; /* number of times fault was out of ram */ | |
339 | int fltnoanon; /* number of times fault was out of anons */ | 339 | int fltnoanon; /* number of times fault was out of anons */ | |
340 | int fltpgwait; /* number of times fault had to wait on a page */ | 340 | int fltpgwait; /* number of times fault had to wait on a page */ | |
341 | int fltpgrele; /* number of times fault found a released page */ | 341 | int fltpgrele; /* number of times fault found a released page */ | |
342 | int fltrelck; /* number of times fault relock called */ | 342 | int fltrelck; /* number of times fault relock called */ | |
343 | int fltrelckok; /* number of times fault relock is a success */ | 343 | int fltrelckok; /* number of times fault relock is a success */ | |
344 | int fltanget; /* number of times fault gets anon page */ | 344 | int fltanget; /* number of times fault gets anon page */ | |
345 | int fltanretry; /* number of times fault retrys an anon get */ | 345 | int fltanretry; /* number of times fault retrys an anon get */ | |
346 | int fltamcopy; /* number of times fault clears "needs copy" */ | 346 | int fltamcopy; /* number of times fault clears "needs copy" */ | |
347 | int fltnamap; /* number of times fault maps a neighbor anon page */ | 347 | int fltnamap; /* number of times fault maps a neighbor anon page */ | |
348 | int fltnomap; /* number of times fault maps a neighbor obj page */ | 348 | int fltnomap; /* number of times fault maps a neighbor obj page */ | |
349 | int fltlget; /* number of times fault does a locked pgo_get */ | 349 | int fltlget; /* number of times fault does a locked pgo_get */ | |
350 | int fltget; /* number of times fault does an unlocked get */ | 350 | int fltget; /* number of times fault does an unlocked get */ | |
351 | int flt_anon; /* number of times fault anon (case 1a) */ | 351 | int flt_anon; /* number of times fault anon (case 1a) */ | |
352 | int flt_acow; /* number of times fault anon cow (case 1b) */ | 352 | int flt_acow; /* number of times fault anon cow (case 1b) */ | |
353 | int flt_obj; /* number of times fault is on object page (2a) */ | 353 | int flt_obj; /* number of times fault is on object page (2a) */ | |
354 | int flt_prcopy; /* number of times fault promotes with copy (2b) */ | 354 | int flt_prcopy; /* number of times fault promotes with copy (2b) */ | |
355 | int flt_przero; /* number of times fault promotes with zerofill (2b) */ | 355 | int flt_przero; /* number of times fault promotes with zerofill (2b) */ | |
356 | 356 | |||
357 | /* daemon counters. XXX: should be 64-bit counters */ | 357 | /* daemon counters. XXX: should be 64-bit counters */ | |
358 | int pdwoke; /* number of times daemon woke up */ | 358 | int pdwoke; /* number of times daemon woke up */ | |
359 | int pdrevs; /* number of times daemon rev'd clock hand */ | 359 | int pdrevs; /* number of times daemon rev'd clock hand */ | |
360 | int _unused3; | 360 | int _unused3; | |
361 | int pdfreed; /* number of pages daemon freed since boot */ | 361 | int pdfreed; /* number of pages daemon freed since boot */ | |
362 | int pdscans; /* number of pages daemon scanned since boot */ | 362 | int pdscans; /* number of pages daemon scanned since boot */ | |
363 | int pdanscan; /* number of anonymous pages scanned by daemon */ | 363 | int pdanscan; /* number of anonymous pages scanned by daemon */ | |
364 | int pdobscan; /* number of object pages scanned by daemon */ | 364 | int pdobscan; /* number of object pages scanned by daemon */ | |
365 | int pdreact; /* number of pages daemon reactivated since boot */ | 365 | int pdreact; /* number of pages daemon reactivated since boot */ | |
366 | int pdbusy; /* number of times daemon found a busy page */ | 366 | int pdbusy; /* number of times daemon found a busy page */ | |
367 | int pdpageouts; /* number of times daemon started a pageout */ | 367 | int pdpageouts; /* number of times daemon started a pageout */ | |
368 | int pdpending; /* number of times daemon got a pending pagout */ | 368 | int pdpending; /* number of times daemon got a pending pagout */ | |
369 | int pddeact; /* number of pages daemon deactivates */ | 369 | int pddeact; /* number of pages daemon deactivates */ | |
370 | int pdreanon; /* anon pages reactivated due to thresholds */ | 370 | int pdreanon; /* anon pages reactivated due to thresholds */ | |
371 | int pdrefile; /* file pages reactivated due to thresholds */ | 371 | int pdrefile; /* file pages reactivated due to thresholds */ | |
372 | int pdreexec; /* executable pages reactivated due to thresholds */ | 372 | int pdreexec; /* executable pages reactivated due to thresholds */ | |
373 | }; | 373 | }; | |
374 | 374 | |||
375 | /* | 375 | /* | |
376 | * The following structure is 64-bit alignment safe. New elements | 376 | * The following structure is 64-bit alignment safe. New elements | |
377 | * should only be added to the end of this structure so binary | 377 | * should only be added to the end of this structure so binary | |
378 | * compatibility can be preserved. | 378 | * compatibility can be preserved. | |
379 | */ | 379 | */ | |
380 | struct uvmexp_sysctl { | 380 | struct uvmexp_sysctl { | |
381 | int64_t pagesize; | 381 | int64_t pagesize; | |
382 | int64_t pagemask; | 382 | int64_t pagemask; | |
383 | int64_t pageshift; | 383 | int64_t pageshift; | |
384 | int64_t npages; | 384 | int64_t npages; | |
385 | int64_t free; | 385 | int64_t free; | |
386 | int64_t active; | 386 | int64_t active; | |
387 | int64_t inactive; | 387 | int64_t inactive; | |
388 | int64_t paging; | 388 | int64_t paging; | |
389 | int64_t wired; | 389 | int64_t wired; | |
390 | int64_t zeropages; | 390 | int64_t zeropages; | |
391 | int64_t reserve_pagedaemon; | 391 | int64_t reserve_pagedaemon; | |
392 | int64_t reserve_kernel; | 392 | int64_t reserve_kernel; | |
393 | int64_t freemin; | 393 | int64_t freemin; | |
394 | int64_t freetarg; | 394 | int64_t freetarg; | |
395 | int64_t inactarg; /* unused */ | 395 | int64_t inactarg; /* unused */ | |
396 | int64_t wiredmax; | 396 | int64_t wiredmax; | |
397 | int64_t nswapdev; | 397 | int64_t nswapdev; | |
398 | int64_t swpages; | 398 | int64_t swpages; | |
399 | int64_t swpginuse; | 399 | int64_t swpginuse; | |
400 | int64_t swpgonly; | 400 | int64_t swpgonly; | |
401 | int64_t nswget; | 401 | int64_t nswget; | |
402 | int64_t unused1; /* unused; was nanon */ | 402 | int64_t unused1; /* unused; was nanon */ | |
403 | int64_t cpuhit; | 403 | int64_t cpuhit; | |
404 | int64_t cpumiss; | 404 | int64_t cpumiss; | |
405 | int64_t faults; | 405 | int64_t faults; | |
406 | int64_t traps; | 406 | int64_t traps; | |
407 | int64_t intrs; | 407 | int64_t intrs; | |
408 | int64_t swtch; | 408 | int64_t swtch; | |
409 | int64_t softs; | 409 | int64_t softs; | |
410 | int64_t syscalls; | 410 | int64_t syscalls; | |
411 | int64_t pageins; | 411 | int64_t pageins; | |
412 | int64_t swapins; /* unused */ | 412 | int64_t swapins; /* unused */ | |
413 | int64_t swapouts; /* unused */ | 413 | int64_t swapouts; /* unused */ | |
414 | int64_t pgswapin; | 414 | int64_t pgswapin; | |
415 | int64_t pgswapout; | 415 | int64_t pgswapout; | |
416 | int64_t forks; | 416 | int64_t forks; | |
417 | int64_t forks_ppwait; | 417 | int64_t forks_ppwait; | |
418 | int64_t forks_sharevm; | 418 | int64_t forks_sharevm; | |
419 | int64_t pga_zerohit; | 419 | int64_t pga_zerohit; | |
420 | int64_t pga_zeromiss; | 420 | int64_t pga_zeromiss; | |
421 | int64_t zeroaborts; | 421 | int64_t zeroaborts; | |
422 | int64_t fltnoram; | 422 | int64_t fltnoram; | |
423 | int64_t fltnoanon; | 423 | int64_t fltnoanon; | |
424 | int64_t fltpgwait; | 424 | int64_t fltpgwait; | |
425 | int64_t fltpgrele; | 425 | int64_t fltpgrele; | |
426 | int64_t fltrelck; | 426 | int64_t fltrelck; | |
427 | int64_t fltrelckok; | 427 | int64_t fltrelckok; | |
428 | int64_t fltanget; | 428 | int64_t fltanget; | |
429 | int64_t fltanretry; | 429 | int64_t fltanretry; | |
430 | int64_t fltamcopy; | 430 | int64_t fltamcopy; | |
431 | int64_t fltnamap; | 431 | int64_t fltnamap; | |
432 | int64_t fltnomap; | 432 | int64_t fltnomap; | |
433 | int64_t fltlget; | 433 | int64_t fltlget; | |
434 | int64_t fltget; | 434 | int64_t fltget; | |
435 | int64_t flt_anon; | 435 | int64_t flt_anon; | |
436 | int64_t flt_acow; | 436 | int64_t flt_acow; | |
437 | int64_t flt_obj; | 437 | int64_t flt_obj; | |
438 | int64_t flt_prcopy; | 438 | int64_t flt_prcopy; | |
439 | int64_t flt_przero; | 439 | int64_t flt_przero; | |
440 | int64_t pdwoke; | 440 | int64_t pdwoke; | |
441 | int64_t pdrevs; | 441 | int64_t pdrevs; | |
442 | int64_t unused4; | 442 | int64_t unused4; | |
443 | int64_t pdfreed; | 443 | int64_t pdfreed; | |
444 | int64_t pdscans; | 444 | int64_t pdscans; | |
445 | int64_t pdanscan; | 445 | int64_t pdanscan; | |
446 | int64_t pdobscan; | 446 | int64_t pdobscan; | |
447 | int64_t pdreact; | 447 | int64_t pdreact; | |
448 | int64_t pdbusy; | 448 | int64_t pdbusy; | |
449 | int64_t pdpageouts; | 449 | int64_t pdpageouts; | |
450 | int64_t pdpending; | 450 | int64_t pdpending; | |
451 | int64_t pddeact; | 451 | int64_t pddeact; | |
452 | int64_t anonpages; | 452 | int64_t anonpages; | |
453 | int64_t filepages; | 453 | int64_t filepages; | |
454 | int64_t execpages; | 454 | int64_t execpages; | |
455 | int64_t colorhit; | 455 | int64_t colorhit; | |
456 | int64_t colormiss; | 456 | int64_t colormiss; | |
457 | int64_t ncolors; | 457 | int64_t ncolors; | |
458 | }; | 458 | }; | |
459 | 459 | |||
460 | #ifdef _KERNEL | 460 | #ifdef _KERNEL | |
461 | /* we need this before including uvm_page.h on some platforms */ | 461 | /* we need this before including uvm_page.h on some platforms */ | |
462 | extern struct uvmexp uvmexp; | 462 | extern struct uvmexp uvmexp; | |
463 | /* MD code needs this without including <uvm/uvm.h> */ | 463 | /* MD code needs this without including <uvm/uvm.h> */ | |
464 | extern bool vm_page_zero_enable; | 464 | extern bool vm_page_zero_enable; | |
465 | #endif | 465 | #endif | |
466 | 466 | |||
467 | /* | 467 | /* | |
468 | * Finally, bring in standard UVM headers. | 468 | * Finally, bring in standard UVM headers. | |
469 | */ | 469 | */ | |
470 | #include <sys/vmmeter.h> | 470 | #include <sys/vmmeter.h> | |
471 | #include <sys/queue.h> | 471 | #include <sys/queue.h> | |
472 | #include <sys/lock.h> | 472 | #include <sys/lock.h> | |
473 | #include <uvm/uvm_param.h> | 473 | #include <uvm/uvm_param.h> | |
474 | #include <uvm/uvm_prot.h> | 474 | #include <uvm/uvm_prot.h> | |
475 | #include <uvm/uvm_pmap.h> | 475 | #include <uvm/uvm_pmap.h> | |
476 | #include <uvm/uvm_map.h> | 476 | #include <uvm/uvm_map.h> | |
477 | #include <uvm/uvm_pager.h> | 477 | #include <uvm/uvm_pager.h> | |
478 | 478 | |||
479 | /* | 479 | /* | |
480 | * helpers for calling ubc_release() | 480 | * helpers for calling ubc_release() | |
481 | */ | 481 | */ | |
482 | #ifdef PMAP_CACHE_VIVT | 482 | #ifdef PMAP_CACHE_VIVT | |
483 | #define UBC_WANT_UNMAP(vp) (((vp)->v_iflag & VI_TEXT) != 0) | 483 | #define UBC_WANT_UNMAP(vp) (((vp)->v_iflag & VI_TEXT) != 0) | |
484 | #else | 484 | #else | |
485 | #define UBC_WANT_UNMAP(vp) false | 485 | #define UBC_WANT_UNMAP(vp) false | |
486 | #endif | 486 | #endif | |
487 | #define UBC_UNMAP_FLAG(vp) (UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0) | 487 | #define UBC_UNMAP_FLAG(vp) (UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0) | |
488 | 488 | |||
489 | /* | 489 | /* | |
490 | * Shareable process virtual address space. | 490 | * Shareable process virtual address space. | |
491 | * May eventually be merged with vm_map. | 491 | * May eventually be merged with vm_map. | |
492 | * Several fields are temporary (text, data stuff). | 492 | * Several fields are temporary (text, data stuff). | |
493 | */ | 493 | */ | |
494 | struct vmspace { | 494 | struct vmspace { | |
495 | struct vm_map vm_map; /* VM address map */ | 495 | struct vm_map vm_map; /* VM address map */ | |
496 | int vm_refcnt; /* number of references * | 496 | int vm_refcnt; /* number of references * | |
497 | * note: protected by vm_map.ref_lock */ | 497 | * note: protected by vm_map.ref_lock */ | |
498 | void * vm_shm; /* SYS5 shared memory private data XXX */ | 498 | void * vm_shm; /* SYS5 shared memory private data XXX */ | |
499 | /* we copy from vm_startcopy to the end of the structure on fork */ | 499 | /* we copy from vm_startcopy to the end of the structure on fork */ | |
500 | #define vm_startcopy vm_rssize | 500 | #define vm_startcopy vm_rssize | |
501 | segsz_t vm_rssize; /* current resident set size in pages */ | 501 | segsz_t vm_rssize; /* current resident set size in pages */ | |
502 | segsz_t vm_swrss; /* resident set size before last swap */ | 502 | segsz_t vm_swrss; /* resident set size before last swap */ | |
503 | segsz_t vm_tsize; /* text size (pages) XXX */ | 503 | segsz_t vm_tsize; /* text size (pages) XXX */ | |
504 | segsz_t vm_dsize; /* data size (pages) XXX */ | 504 | segsz_t vm_dsize; /* data size (pages) XXX */ | |
505 | segsz_t vm_ssize; /* stack size (pages) */ | 505 | segsz_t vm_ssize; /* stack size (pages) */ | |
506 | segsz_t vm_issize; /* initial unmapped stack size (pages) */ | 506 | segsz_t vm_issize; /* initial unmapped stack size (pages) */ | |
507 | void * vm_taddr; /* user virtual address of text XXX */ | 507 | void * vm_taddr; /* user virtual address of text XXX */ | |
508 | void * vm_daddr; /* user virtual address of data XXX */ | 508 | void * vm_daddr; /* user virtual address of data XXX */ | |
509 | void *vm_maxsaddr; /* user VA at max stack growth */ | 509 | void *vm_maxsaddr; /* user VA at max stack growth */ | |
510 | void *vm_minsaddr; /* user VA at top of stack */ | 510 | void *vm_minsaddr; /* user VA at top of stack */ | |
511 | size_t vm_aslr_delta_mmap; /* mmap() random delta for ASLR */ | 511 | size_t vm_aslr_delta_mmap; /* mmap() random delta for ASLR */ | |
512 | }; | 512 | }; | |
513 | #define VMSPACE_IS_KERNEL_P(vm) VM_MAP_IS_KERNEL(&(vm)->vm_map) | 513 | #define VMSPACE_IS_KERNEL_P(vm) VM_MAP_IS_KERNEL(&(vm)->vm_map) | |
514 | 514 | |||
515 | #ifdef _KERNEL | 515 | #ifdef _KERNEL | |
516 | 516 | |||
517 | /* | 517 | /* | |
518 | * used to keep state while iterating over the map for a core dump. | 518 | * used to keep state while iterating over the map for a core dump. | |
519 | */ | 519 | */ | |
520 | struct uvm_coredump_state { | 520 | struct uvm_coredump_state { | |
521 | void *cookie; /* opaque for the caller */ | 521 | void *cookie; /* opaque for the caller */ | |
522 | vaddr_t start; /* start of region */ | 522 | vaddr_t start; /* start of region */ | |
523 | vaddr_t realend; /* real end of region */ | 523 | vaddr_t realend; /* real end of region */ | |
524 | vaddr_t end; /* virtual end of region */ | 524 | vaddr_t end; /* virtual end of region */ | |
525 | vm_prot_t prot; /* protection of region */ | 525 | vm_prot_t prot; /* protection of region */ | |
526 | int flags; /* flags; see below */ | 526 | int flags; /* flags; see below */ | |
527 | }; | 527 | }; | |
528 | 528 | |||
529 | #define UVM_COREDUMP_STACK 0x01 /* region is user stack */ | 529 | #define UVM_COREDUMP_STACK 0x01 /* region is user stack */ | |
530 | 530 | |||
531 | /* | 531 | /* | |
532 | * Structure containig uvm reclaim hooks, uvm_reclaim_list is guarded by | 532 | * Structure containig uvm reclaim hooks, uvm_reclaim_list is guarded by | |
533 | * uvm_reclaim_lock. | 533 | * uvm_reclaim_lock. | |
534 | */ | 534 | */ | |
535 | struct uvm_reclaim_hook { | 535 | struct uvm_reclaim_hook { | |
536 | void (*uvm_reclaim_hook)(void); | 536 | void (*uvm_reclaim_hook)(void); | |
537 | SLIST_ENTRY(uvm_reclaim_hook) uvm_reclaim_next; | 537 | SLIST_ENTRY(uvm_reclaim_hook) uvm_reclaim_next; | |
538 | }; | 538 | }; | |
539 | 539 | |||
540 | void uvm_reclaim_init(void); | 540 | void uvm_reclaim_init(void); | |
541 | void uvm_reclaim_hook_add(struct uvm_reclaim_hook *); | 541 | void uvm_reclaim_hook_add(struct uvm_reclaim_hook *); | |
542 | void uvm_reclaim_hook_del(struct uvm_reclaim_hook *); | 542 | void uvm_reclaim_hook_del(struct uvm_reclaim_hook *); | |
543 | 543 | |||
544 | /* | 544 | /* | |
545 | * the various kernel maps, owned by MD code | 545 | * the various kernel maps, owned by MD code | |
546 | */ | 546 | */ | |
547 | extern struct vm_map *kernel_map; | 547 | extern struct vm_map *kernel_map; | |
548 | extern struct vm_map *kmem_map; | 548 | extern struct vm_map *kmem_map; | |
549 | extern struct vm_map *phys_map; | 549 | extern struct vm_map *phys_map; | |
550 | 550 | |||
551 | /* | 551 | /* | |
552 | * macros | 552 | * macros | |
553 | */ | 553 | */ | |
554 | 554 | |||
555 | #define vm_resident_count(vm) (pmap_resident_count((vm)->vm_map.pmap)) | 555 | #define vm_resident_count(vm) (pmap_resident_count((vm)->vm_map.pmap)) | |
556 | 556 | |||
557 | #include <sys/mallocvar.h> | 557 | #include <sys/mallocvar.h> | |
558 | MALLOC_DECLARE(M_VMMAP); | 558 | MALLOC_DECLARE(M_VMMAP); | |
559 | MALLOC_DECLARE(M_VMPMAP); | 559 | MALLOC_DECLARE(M_VMPMAP); | |
560 | 560 | |||
561 | /* vm_machdep.c */ | 561 | /* vm_machdep.c */ | |
562 | int vmapbuf(struct buf *, vsize_t); | 562 | int vmapbuf(struct buf *, vsize_t); | |
563 | void vunmapbuf(struct buf *, vsize_t); | 563 | void vunmapbuf(struct buf *, vsize_t); | |
564 | 564 | |||
565 | /* uvm_aobj.c */ | 565 | /* uvm_aobj.c */ | |
566 | struct uvm_object *uao_create(vsize_t, int); | 566 | struct uvm_object *uao_create(vsize_t, int); | |
567 | void uao_detach(struct uvm_object *); | 567 | void uao_detach(struct uvm_object *); | |
568 | void uao_reference(struct uvm_object *); | 568 | void uao_reference(struct uvm_object *); | |
569 | 569 | |||
570 | /* uvm_bio.c */ | 570 | /* uvm_bio.c */ | |
571 | void ubc_init(void); | 571 | void ubc_init(void); | |
572 | void * ubc_alloc(struct uvm_object *, voff_t, vsize_t *, int, | 572 | void * ubc_alloc(struct uvm_object *, voff_t, vsize_t *, int, | |
573 | int); | 573 | int); | |
574 | void ubc_release(void *, int); | 574 | void ubc_release(void *, int); | |
575 | int ubc_uiomove(struct uvm_object *, struct uio *, vsize_t, | 575 | int ubc_uiomove(struct uvm_object *, struct uio *, vsize_t, | |
576 | int, int); | 576 | int, int); | |
577 | void ubc_zerorange(struct uvm_object *, off_t, size_t, int); | 577 | void ubc_zerorange(struct uvm_object *, off_t, size_t, int); | |
578 | void ubc_purge(struct uvm_object *); | 578 | void ubc_purge(struct uvm_object *); | |
579 | 579 | |||
580 | /* uvm_emap.c */ | 580 | /* uvm_emap.c */ | |
581 | void uvm_emap_sysinit(void); | 581 | void uvm_emap_sysinit(void); | |
582 | #ifdef __HAVE_PMAP_EMAP | 582 | #ifdef __HAVE_PMAP_EMAP | |
583 | void uvm_emap_switch(lwp_t *); | 583 | void uvm_emap_switch(lwp_t *); | |
584 | #else | 584 | #else | |
585 | #define uvm_emap_switch(l) | 585 | #define uvm_emap_switch(l) | |
586 | #endif | 586 | #endif | |
587 | 587 | |||
588 | u_int uvm_emap_gen_return(void); | 588 | u_int uvm_emap_gen_return(void); | |
589 | void uvm_emap_update(u_int); | 589 | void uvm_emap_update(u_int); | |
590 | 590 | |||
591 | vaddr_t uvm_emap_alloc(vsize_t, bool); | 591 | vaddr_t uvm_emap_alloc(vsize_t, bool); | |
592 | void uvm_emap_free(vaddr_t, size_t); | 592 | void uvm_emap_free(vaddr_t, size_t); | |
593 | 593 | |||
594 | void uvm_emap_enter(vaddr_t, struct vm_page **, u_int); | 594 | void uvm_emap_enter(vaddr_t, struct vm_page **, u_int); | |
595 | void uvm_emap_remove(vaddr_t, vsize_t); | 595 | void uvm_emap_remove(vaddr_t, vsize_t); | |
596 | 596 | |||
597 | #ifdef __HAVE_PMAP_EMAP | 597 | #ifdef __HAVE_PMAP_EMAP | |
598 | void uvm_emap_consume(u_int); | 598 | void uvm_emap_consume(u_int); | |
599 | u_int uvm_emap_produce(void); | 599 | u_int uvm_emap_produce(void); | |
600 | #else | 600 | #else | |
601 | #define uvm_emap_consume(x) | 601 | #define uvm_emap_consume(x) | |
602 | #define uvm_emap_produce() UVM_EMAP_INACTIVE | 602 | #define uvm_emap_produce() UVM_EMAP_INACTIVE | |
603 | #endif | 603 | #endif | |
604 | 604 | |||
605 | /* uvm_fault.c */ | 605 | /* uvm_fault.c */ | |
606 | #define uvm_fault(m, a, p) uvm_fault_internal(m, a, p, 0) | 606 | #define uvm_fault(m, a, p) uvm_fault_internal(m, a, p, 0) | |
607 | int uvm_fault_internal(struct vm_map *, vaddr_t, vm_prot_t, int); | 607 | int uvm_fault_internal(struct vm_map *, vaddr_t, vm_prot_t, int); | |
608 | /* handle a page fault */ | 608 | /* handle a page fault */ | |
609 | 609 | |||
610 | /* uvm_glue.c */ | 610 | /* uvm_glue.c */ | |
611 | #if defined(KGDB) | 611 | #if defined(KGDB) | |
612 | void uvm_chgkprot(void *, size_t, int); | 612 | void uvm_chgkprot(void *, size_t, int); | |
613 | #endif | 613 | #endif | |
614 | void uvm_proc_fork(struct proc *, struct proc *, bool); | 614 | void uvm_proc_fork(struct proc *, struct proc *, bool); | |
615 | void uvm_lwp_fork(struct lwp *, struct lwp *, | 615 | void uvm_lwp_fork(struct lwp *, struct lwp *, | |
616 | void *, size_t, void (*)(void *), void *); | 616 | void *, size_t, void (*)(void *), void *); | |
617 | int uvm_coredump_walkmap(struct proc *, | 617 | int uvm_coredump_walkmap(struct proc *, | |
618 | void *, | 618 | void *, | |
619 | int (*)(struct proc *, void *, | 619 | int (*)(struct proc *, void *, | |
620 | struct uvm_coredump_state *), void *); | 620 | struct uvm_coredump_state *), void *); | |
621 | void uvm_proc_exit(struct proc *); | 621 | void uvm_proc_exit(struct proc *); | |
622 | void uvm_lwp_exit(struct lwp *); | 622 | void uvm_lwp_exit(struct lwp *); | |
623 | void uvm_init_limits(struct proc *); | 623 | void uvm_init_limits(struct proc *); | |
624 | bool uvm_kernacc(void *, size_t, vm_prot_t); | 624 | bool uvm_kernacc(void *, size_t, vm_prot_t); | |
625 | __dead void uvm_scheduler(void); | 625 | __dead void uvm_scheduler(void); | |
626 | vaddr_t uvm_uarea_alloc(void); | 626 | vaddr_t uvm_uarea_alloc(void); | |
627 | void uvm_uarea_free(vaddr_t); | 627 | void uvm_uarea_free(vaddr_t); | |
628 | vaddr_t uvm_uarea_system_alloc(void); | 628 | vaddr_t uvm_uarea_system_alloc(void); | |
629 | void uvm_uarea_system_free(vaddr_t); | 629 | void uvm_uarea_system_free(vaddr_t); | |
630 | vaddr_t uvm_lwp_getuarea(lwp_t *); | 630 | vaddr_t uvm_lwp_getuarea(lwp_t *); | |
631 | void uvm_lwp_setuarea(lwp_t *, vaddr_t); | 631 | void uvm_lwp_setuarea(lwp_t *, vaddr_t); | |
632 | int uvm_vslock(struct vmspace *, void *, size_t, vm_prot_t); | 632 | int uvm_vslock(struct vmspace *, void *, size_t, vm_prot_t); | |
633 | void uvm_vsunlock(struct vmspace *, void *, size_t); | 633 | void uvm_vsunlock(struct vmspace *, void *, size_t); | |
634 | void uvm_cpu_attach(struct cpu_info *); | 634 | void uvm_cpu_attach(struct cpu_info *); | |
635 | 635 | |||
636 | 636 | |||
637 | /* uvm_init.c */ | 637 | /* uvm_init.c */ | |
638 | void uvm_init(void); | 638 | void uvm_init(void); | |
639 | 639 | |||
640 | /* uvm_io.c */ | 640 | /* uvm_io.c */ | |
641 | int uvm_io(struct vm_map *, struct uio *); | 641 | int uvm_io(struct vm_map *, struct uio *); | |
642 | 642 | |||
643 | /* uvm_km.c */ | 643 | /* uvm_km.c */ | |
644 | vaddr_t uvm_km_alloc(struct vm_map *, vsize_t, vsize_t, | 644 | vaddr_t uvm_km_alloc(struct vm_map *, vsize_t, vsize_t, | |
645 | uvm_flag_t); | 645 | uvm_flag_t); | |
646 | void uvm_km_free(struct vm_map *, vaddr_t, vsize_t, | 646 | void uvm_km_free(struct vm_map *, vaddr_t, vsize_t, | |
647 | uvm_flag_t); | 647 | uvm_flag_t); | |
648 | 648 | |||
649 | struct vm_map *uvm_km_suballoc(struct vm_map *, vaddr_t *, | 649 | struct vm_map *uvm_km_suballoc(struct vm_map *, vaddr_t *, | |
650 | vaddr_t *, vsize_t, int, bool, | 650 | vaddr_t *, vsize_t, int, bool, | |
651 | struct vm_map_kernel *); | 651 | struct vm_map_kernel *); | |
652 | vaddr_t uvm_km_alloc_poolpage(struct vm_map *, bool); | 652 | vaddr_t uvm_km_alloc_poolpage(struct vm_map *, bool); | |
653 | void uvm_km_free_poolpage(struct vm_map *, vaddr_t); | 653 | void uvm_km_free_poolpage(struct vm_map *, vaddr_t); | |
654 | vaddr_t uvm_km_alloc_poolpage_cache(struct vm_map *, bool); | 654 | vaddr_t uvm_km_alloc_poolpage_cache(struct vm_map *, bool); | |
655 | void uvm_km_free_poolpage_cache(struct vm_map *, vaddr_t); | 655 | void uvm_km_free_poolpage_cache(struct vm_map *, vaddr_t); | |
656 | void uvm_km_vacache_init(struct vm_map *, | 656 | void uvm_km_vacache_init(struct vm_map *, | |
657 | const char *, size_t); | 657 | const char *, size_t); | |
658 | 658 | |||
659 | /* uvm_map.c */ | 659 | /* uvm_map.c */ | |
660 | int uvm_map(struct vm_map *, vaddr_t *, vsize_t, | 660 | int uvm_map(struct vm_map *, vaddr_t *, vsize_t, | |
661 | struct uvm_object *, voff_t, vsize_t, | 661 | struct uvm_object *, voff_t, vsize_t, | |
662 | uvm_flag_t); | 662 | uvm_flag_t); | |
663 | int uvm_map_pageable(struct vm_map *, vaddr_t, | 663 | int uvm_map_pageable(struct vm_map *, vaddr_t, | |
664 | vaddr_t, bool, int); | 664 | vaddr_t, bool, int); | |
665 | int uvm_map_pageable_all(struct vm_map *, int, vsize_t); | 665 | int uvm_map_pageable_all(struct vm_map *, int, vsize_t); | |
666 | bool uvm_map_checkprot(struct vm_map *, vaddr_t, | 666 | bool uvm_map_checkprot(struct vm_map *, vaddr_t, | |
667 | vaddr_t, vm_prot_t); | 667 | vaddr_t, vm_prot_t); | |
668 | int uvm_map_protect(struct vm_map *, vaddr_t, | 668 | int uvm_map_protect(struct vm_map *, vaddr_t, | |
669 | vaddr_t, vm_prot_t, bool); | 669 | vaddr_t, vm_prot_t, bool); | |
670 | struct vmspace *uvmspace_alloc(vaddr_t, vaddr_t); | 670 | struct vmspace *uvmspace_alloc(vaddr_t, vaddr_t); | |
671 | void uvmspace_init(struct vmspace *, struct pmap *, | 671 | void uvmspace_init(struct vmspace *, struct pmap *, | |
672 | vaddr_t, vaddr_t); | 672 | vaddr_t, vaddr_t); | |
673 | void uvmspace_exec(struct lwp *, vaddr_t, vaddr_t); | 673 | void uvmspace_exec(struct lwp *, vaddr_t, vaddr_t); | |
674 | struct vmspace *uvmspace_fork(struct vmspace *); | 674 | struct vmspace *uvmspace_fork(struct vmspace *); | |
675 | void uvmspace_addref(struct vmspace *); | 675 | void uvmspace_addref(struct vmspace *); | |
676 | void uvmspace_free(struct vmspace *); | 676 | void uvmspace_free(struct vmspace *); | |
677 | void uvmspace_share(struct proc *, struct proc *); | 677 | void uvmspace_share(struct proc *, struct proc *); | |
678 | void uvmspace_unshare(struct lwp *); | 678 | void uvmspace_unshare(struct lwp *); | |
679 | 679 | |||
680 | void uvm_whatis(uintptr_t, void (*)(const char *, ...)); | 680 | void uvm_whatis(uintptr_t, void (*)(const char *, ...)); | |
681 | 681 | |||
682 | /* uvm_meter.c */ | 682 | /* uvm_meter.c */ | |
683 | int uvm_sysctl(int *, u_int, void *, size_t *, | 683 | int uvm_sysctl(int *, u_int, void *, size_t *, | |
684 | void *, size_t, struct proc *); | 684 | void *, size_t, struct proc *); | |
685 | int uvm_pctparam_check(struct uvm_pctparam *, int); | 685 | int uvm_pctparam_check(struct uvm_pctparam *, int); | |
686 | void uvm_pctparam_set(struct uvm_pctparam *, int); | 686 | void uvm_pctparam_set(struct uvm_pctparam *, int); | |
687 | int uvm_pctparam_get(struct uvm_pctparam *); | 687 | int uvm_pctparam_get(struct uvm_pctparam *); | |
688 | void uvm_pctparam_init(struct uvm_pctparam *, int, | 688 | void uvm_pctparam_init(struct uvm_pctparam *, int, | |
689 | int (*)(struct uvm_pctparam *, int)); | 689 | int (*)(struct uvm_pctparam *, int)); | |
690 | int uvm_pctparam_createsysctlnode(struct uvm_pctparam *, | 690 | int uvm_pctparam_createsysctlnode(struct uvm_pctparam *, | |
691 | const char *, const char *); | 691 | const char *, const char *); | |
692 | 692 | |||
693 | /* uvm_mmap.c */ | 693 | /* uvm_mmap.c */ | |
694 | int uvm_mmap(struct vm_map *, vaddr_t *, vsize_t, | 694 | int uvm_mmap(struct vm_map *, vaddr_t *, vsize_t, | |
695 | vm_prot_t, vm_prot_t, int, | 695 | vm_prot_t, vm_prot_t, int, | |
696 | void *, voff_t, vsize_t); | 696 | void *, voff_t, vsize_t); | |
697 | vaddr_t uvm_default_mapaddr(struct proc *, vaddr_t, vsize_t); | 697 | vaddr_t uvm_default_mapaddr(struct proc *, vaddr_t, vsize_t); | |
698 | 698 | |||
699 | /* uvm_mremap.c */ | 699 | /* uvm_mremap.c */ | |
700 | int uvm_mremap(struct vm_map *, vaddr_t, vsize_t, | 700 | int uvm_mremap(struct vm_map *, vaddr_t, vsize_t, | |
701 | struct vm_map *, vaddr_t *, vsize_t, | 701 | struct vm_map *, vaddr_t *, vsize_t, | |
702 | struct proc *, int); | 702 | struct proc *, int); | |
703 | 703 | |||
704 | /* uvm_object.c */ | 704 | /* uvm_object.c */ | |
705 | void uvm_obj_init(struct uvm_object *, | 705 | void uvm_obj_init(struct uvm_object *, | |
706 | const struct uvm_pagerops *, bool, u_int); | 706 | const struct uvm_pagerops *, bool, u_int); | |
707 | void uvm_obj_setlock(struct uvm_object *, kmutex_t *); | 707 | void uvm_obj_setlock(struct uvm_object *, kmutex_t *); | |
708 | void uvm_obj_destroy(struct uvm_object *, bool); | 708 | void uvm_obj_destroy(struct uvm_object *, bool); | |
709 | int uvm_obj_wirepages(struct uvm_object *, off_t, off_t); | 709 | int uvm_obj_wirepages(struct uvm_object *, off_t, off_t, | |
710 | struct pglist *); | |||
710 | void uvm_obj_unwirepages(struct uvm_object *, off_t, off_t); | 711 | void uvm_obj_unwirepages(struct uvm_object *, off_t, off_t); | |
711 | 712 | |||
712 | /* uvm_page.c */ | 713 | /* uvm_page.c */ | |
713 | struct vm_page *uvm_pagealloc_strat(struct uvm_object *, | 714 | struct vm_page *uvm_pagealloc_strat(struct uvm_object *, | |
714 | voff_t, struct vm_anon *, int, int, int); | 715 | voff_t, struct vm_anon *, int, int, int); | |
715 | #define uvm_pagealloc(obj, off, anon, flags) \ | 716 | #define uvm_pagealloc(obj, off, anon, flags) \ | |
716 | uvm_pagealloc_strat((obj), (off), (anon), (flags), \ | 717 | uvm_pagealloc_strat((obj), (off), (anon), (flags), \ | |
717 | UVM_PGA_STRAT_NORMAL, 0) | 718 | UVM_PGA_STRAT_NORMAL, 0) | |
718 | void uvm_pagereplace(struct vm_page *, | 719 | void uvm_pagereplace(struct vm_page *, | |
719 | struct vm_page *); | 720 | struct vm_page *); | |
720 | void uvm_pagerealloc(struct vm_page *, | 721 | void uvm_pagerealloc(struct vm_page *, | |
721 | struct uvm_object *, voff_t); | 722 | struct uvm_object *, voff_t); | |
722 | /* Actually, uvm_page_physload takes PF#s which need their own type */ | 723 | /* Actually, uvm_page_physload takes PF#s which need their own type */ | |
723 | void uvm_page_physload(paddr_t, paddr_t, paddr_t, | 724 | void uvm_page_physload(paddr_t, paddr_t, paddr_t, | |
724 | paddr_t, int); | 725 | paddr_t, int); | |
725 | void uvm_setpagesize(void); | 726 | void uvm_setpagesize(void); | |
726 | 727 | |||
727 | /* uvm_pager.c */ | 728 | /* uvm_pager.c */ | |
728 | void uvm_aio_biodone(struct buf *); | 729 | void uvm_aio_biodone(struct buf *); | |
729 | void uvm_aio_aiodone(struct buf *); | 730 | void uvm_aio_aiodone(struct buf *); | |
730 | void uvm_aio_aiodone_pages(struct vm_page **, int, bool, | 731 | void uvm_aio_aiodone_pages(struct vm_page **, int, bool, | |
731 | int); | 732 | int); | |
732 | 733 | |||
733 | /* uvm_pdaemon.c */ | 734 | /* uvm_pdaemon.c */ | |
734 | void uvm_pageout(void *); | 735 | void uvm_pageout(void *); | |
735 | struct work; | 736 | struct work; | |
736 | void uvm_aiodone_worker(struct work *, void *); | 737 | void uvm_aiodone_worker(struct work *, void *); | |
737 | void uvm_pageout_start(int); | 738 | void uvm_pageout_start(int); | |
738 | void uvm_pageout_done(int); | 739 | void uvm_pageout_done(int); | |
739 | void uvm_estimatepageable(int *, int *); | 740 | void uvm_estimatepageable(int *, int *); | |
740 | 741 | |||
741 | /* uvm_pglist.c */ | 742 | /* uvm_pglist.c */ | |
742 | int uvm_pglistalloc(psize_t, paddr_t, paddr_t, | 743 | int uvm_pglistalloc(psize_t, paddr_t, paddr_t, | |
743 | paddr_t, paddr_t, struct pglist *, int, int); | 744 | paddr_t, paddr_t, struct pglist *, int, int); | |
744 | void uvm_pglistfree(struct pglist *); | 745 | void uvm_pglistfree(struct pglist *); | |
745 | 746 | |||
746 | /* uvm_swap.c */ | 747 | /* uvm_swap.c */ | |
747 | void uvm_swap_init(void); | 748 | void uvm_swap_init(void); | |
748 | 749 | |||
749 | /* uvm_unix.c */ | 750 | /* uvm_unix.c */ | |
750 | int uvm_grow(struct proc *, vaddr_t); | 751 | int uvm_grow(struct proc *, vaddr_t); | |
751 | 752 | |||
752 | /* uvm_user.c */ | 753 | /* uvm_user.c */ | |
753 | void uvm_deallocate(struct vm_map *, vaddr_t, vsize_t); | 754 | void uvm_deallocate(struct vm_map *, vaddr_t, vsize_t); | |
754 | 755 | |||
755 | /* uvm_vnode.c */ | 756 | /* uvm_vnode.c */ | |
756 | void uvm_vnp_setsize(struct vnode *, voff_t); | 757 | void uvm_vnp_setsize(struct vnode *, voff_t); | |
757 | void uvm_vnp_setwritesize(struct vnode *, voff_t); | 758 | void uvm_vnp_setwritesize(struct vnode *, voff_t); | |
758 | int uvn_findpages(struct uvm_object *, voff_t, | 759 | int uvn_findpages(struct uvm_object *, voff_t, | |
759 | int *, struct vm_page **, int); | 760 | int *, struct vm_page **, int); | |
760 | bool uvn_text_p(struct uvm_object *); | 761 | bool uvn_text_p(struct uvm_object *); | |
761 | bool uvn_clean_p(struct uvm_object *); | 762 | bool uvn_clean_p(struct uvm_object *); | |
762 | bool uvn_needs_writefault_p(struct uvm_object *); | 763 | bool uvn_needs_writefault_p(struct uvm_object *); | |
763 | 764 | |||
764 | /* kern_malloc.c */ | 765 | /* kern_malloc.c */ | |
765 | void kmeminit_nkmempages(void); | 766 | void kmeminit_nkmempages(void); | |
766 | void kmeminit(void); | 767 | void kmeminit(void); | |
767 | extern int nkmempages; | 768 | extern int nkmempages; | |
768 | 769 | |||
769 | #endif /* _KERNEL */ | 770 | #endif /* _KERNEL */ | |
770 | 771 | |||
771 | #endif /* _UVM_UVM_EXTERN_H_ */ | 772 | #endif /* _UVM_UVM_EXTERN_H_ */ |
--- src/sys/uvm/uvm_object.c 2011/06/18 21:14:43 1.10
+++ src/sys/uvm/uvm_object.c 2011/08/27 09:11:53 1.11
@@ -1,262 +1,265 @@ | @@ -1,262 +1,265 @@ | |||
1 | /* $NetBSD: uvm_object.c,v 1.10 2011/06/18 21:14:43 rmind Exp $ */ | 1 | /* $NetBSD: uvm_object.c,v 1.11 2011/08/27 09:11:53 christos Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2006, 2010 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2006, 2010 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Mindaugas Rasiukevicius. | 8 | * by Mindaugas Rasiukevicius. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * uvm_object.c: operate with memory objects | 33 | * uvm_object.c: operate with memory objects | |
34 | * | 34 | * | |
35 | * TODO: | 35 | * TODO: | |
36 | * 1. Support PG_RELEASED-using objects | 36 | * 1. Support PG_RELEASED-using objects | |
37 | */ | 37 | */ | |
38 | 38 | |||
39 | #include <sys/cdefs.h> | 39 | #include <sys/cdefs.h> | |
40 | __KERNEL_RCSID(0, "$NetBSD: uvm_object.c,v 1.10 2011/06/18 21:14:43 rmind Exp $"); | 40 | __KERNEL_RCSID(0, "$NetBSD: uvm_object.c,v 1.11 2011/08/27 09:11:53 christos Exp $"); | |
41 | 41 | |||
42 | #include "opt_ddb.h" | 42 | #include "opt_ddb.h" | |
43 | 43 | |||
44 | #include <sys/param.h> | 44 | #include <sys/param.h> | |
45 | #include <sys/mutex.h> | 45 | #include <sys/mutex.h> | |
46 | #include <sys/queue.h> | 46 | #include <sys/queue.h> | |
47 | #include <sys/rbtree.h> | 47 | #include <sys/rbtree.h> | |
48 | 48 | |||
49 | #include <uvm/uvm.h> | 49 | #include <uvm/uvm.h> | |
50 | #include <uvm/uvm_ddb.h> | 50 | #include <uvm/uvm_ddb.h> | |
51 | 51 | |||
52 | /* Page count to fetch per single step. */ | 52 | /* Page count to fetch per single step. */ | |
53 | #define FETCH_PAGECOUNT 16 | 53 | #define FETCH_PAGECOUNT 16 | |
54 | 54 | |||
55 | /* | 55 | /* | |
56 | * uvm_obj_init: initialize UVM memory object. | 56 | * uvm_obj_init: initialize UVM memory object. | |
57 | */ | 57 | */ | |
58 | void | 58 | void | |
59 | uvm_obj_init(struct uvm_object *uo, const struct uvm_pagerops *ops, | 59 | uvm_obj_init(struct uvm_object *uo, const struct uvm_pagerops *ops, | |
60 | bool alock, u_int refs) | 60 | bool alock, u_int refs) | |
61 | { | 61 | { | |
62 | 62 | |||
63 | if (alock) { | 63 | if (alock) { | |
64 | /* Allocate and assign a lock. */ | 64 | /* Allocate and assign a lock. */ | |
65 | uo->vmobjlock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); | 65 | uo->vmobjlock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); | |
66 | } else { | 66 | } else { | |
67 | /* The lock will need to be set via uvm_obj_setlock(). */ | 67 | /* The lock will need to be set via uvm_obj_setlock(). */ | |
68 | uo->vmobjlock = NULL; | 68 | uo->vmobjlock = NULL; | |
69 | } | 69 | } | |
70 | uo->pgops = ops; | 70 | uo->pgops = ops; | |
71 | TAILQ_INIT(&uo->memq); | 71 | TAILQ_INIT(&uo->memq); | |
72 | LIST_INIT(&uo->uo_ubc); | 72 | LIST_INIT(&uo->uo_ubc); | |
73 | uo->uo_npages = 0; | 73 | uo->uo_npages = 0; | |
74 | uo->uo_refs = refs; | 74 | uo->uo_refs = refs; | |
75 | rb_tree_init(&uo->rb_tree, &uvm_page_tree_ops); | 75 | rb_tree_init(&uo->rb_tree, &uvm_page_tree_ops); | |
76 | } | 76 | } | |
77 | 77 | |||
78 | /* | 78 | /* | |
79 | * uvm_obj_destroy: destroy UVM memory object. | 79 | * uvm_obj_destroy: destroy UVM memory object. | |
80 | */ | 80 | */ | |
81 | void | 81 | void | |
82 | uvm_obj_destroy(struct uvm_object *uo, bool dlock) | 82 | uvm_obj_destroy(struct uvm_object *uo, bool dlock) | |
83 | { | 83 | { | |
84 | 84 | |||
85 | KASSERT(rb_tree_iterate(&uo->rb_tree, NULL, RB_DIR_LEFT) == NULL); | 85 | KASSERT(rb_tree_iterate(&uo->rb_tree, NULL, RB_DIR_LEFT) == NULL); | |
86 | 86 | |||
87 | /* Purge any UBC entries associated with this object. */ | 87 | /* Purge any UBC entries associated with this object. */ | |
88 | ubc_purge(uo); | 88 | ubc_purge(uo); | |
89 | 89 | |||
90 | /* Destroy the lock, if requested. */ | 90 | /* Destroy the lock, if requested. */ | |
91 | if (dlock) { | 91 | if (dlock) { | |
92 | mutex_obj_free(uo->vmobjlock); | 92 | mutex_obj_free(uo->vmobjlock); | |
93 | } | 93 | } | |
94 | } | 94 | } | |
95 | 95 | |||
96 | /* | 96 | /* | |
97 | * uvm_obj_setlock: assign a vmobjlock to the UVM object. | 97 | * uvm_obj_setlock: assign a vmobjlock to the UVM object. | |
98 | * | 98 | * | |
99 | * => Caller is responsible to ensure that UVM objects is not use. | 99 | * => Caller is responsible to ensure that UVM objects is not use. | |
100 | * => Only dynamic lock may be previously set. We drop the reference then. | 100 | * => Only dynamic lock may be previously set. We drop the reference then. | |
101 | */ | 101 | */ | |
102 | void | 102 | void | |
103 | uvm_obj_setlock(struct uvm_object *uo, kmutex_t *lockptr) | 103 | uvm_obj_setlock(struct uvm_object *uo, kmutex_t *lockptr) | |
104 | { | 104 | { | |
105 | kmutex_t *olockptr = uo->vmobjlock; | 105 | kmutex_t *olockptr = uo->vmobjlock; | |
106 | 106 | |||
107 | if (olockptr) { | 107 | if (olockptr) { | |
108 | /* Drop the reference on the old lock. */ | 108 | /* Drop the reference on the old lock. */ | |
109 | mutex_obj_free(olockptr); | 109 | mutex_obj_free(olockptr); | |
110 | } | 110 | } | |
111 | if (lockptr == NULL) { | 111 | if (lockptr == NULL) { | |
112 | /* If new lock is not passed - allocate default one. */ | 112 | /* If new lock is not passed - allocate default one. */ | |
113 | lockptr = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); | 113 | lockptr = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); | |
114 | } | 114 | } | |
115 | uo->vmobjlock = lockptr; | 115 | uo->vmobjlock = lockptr; | |
116 | } | 116 | } | |
117 | 117 | |||
118 | /* | 118 | /* | |
119 | * uvm_obj_wirepages: wire the pages of entire UVM object. | 119 | * uvm_obj_wirepages: wire the pages of entire UVM object. | |
120 | * | 120 | * | |
121 | * => NOTE: this function should only be used for types of objects | 121 | * => NOTE: this function should only be used for types of objects | |
122 | * where PG_RELEASED flag is never set (aobj objects) | 122 | * where PG_RELEASED flag is never set (aobj objects) | |
123 | * => caller must pass page-aligned start and end values | 123 | * => caller must pass page-aligned start and end values | |
124 | */ | 124 | */ | |
125 | int | 125 | int | |
126 | uvm_obj_wirepages(struct uvm_object *uobj, off_t start, off_t end) | 126 | uvm_obj_wirepages(struct uvm_object *uobj, off_t start, off_t end, | |
127 | struct pglist *list) | |||
127 | { | 128 | { | |
128 | int i, npages, error; | 129 | int i, npages, error; | |
129 | struct vm_page *pgs[FETCH_PAGECOUNT], *pg = NULL; | 130 | struct vm_page *pgs[FETCH_PAGECOUNT], *pg = NULL; | |
130 | off_t offset = start, left; | 131 | off_t offset = start, left; | |
131 | 132 | |||
132 | left = (end - start) >> PAGE_SHIFT; | 133 | left = (end - start) >> PAGE_SHIFT; | |
133 | 134 | |||
134 | mutex_enter(uobj->vmobjlock); | 135 | mutex_enter(uobj->vmobjlock); | |
135 | while (left) { | 136 | while (left) { | |
136 | 137 | |||
137 | npages = MIN(FETCH_PAGECOUNT, left); | 138 | npages = MIN(FETCH_PAGECOUNT, left); | |
138 | 139 | |||
139 | /* Get the pages */ | 140 | /* Get the pages */ | |
140 | memset(pgs, 0, sizeof(pgs)); | 141 | memset(pgs, 0, sizeof(pgs)); | |
141 | error = (*uobj->pgops->pgo_get)(uobj, offset, pgs, &npages, 0, | 142 | error = (*uobj->pgops->pgo_get)(uobj, offset, pgs, &npages, 0, | |
142 | VM_PROT_READ | VM_PROT_WRITE, UVM_ADV_SEQUENTIAL, | 143 | VM_PROT_READ | VM_PROT_WRITE, UVM_ADV_SEQUENTIAL, | |
143 | PGO_ALLPAGES | PGO_SYNCIO); | 144 | PGO_ALLPAGES | PGO_SYNCIO); | |
144 | 145 | |||
145 | if (error) | 146 | if (error) | |
146 | goto error; | 147 | goto error; | |
147 | 148 | |||
148 | mutex_enter(uobj->vmobjlock); | 149 | mutex_enter(uobj->vmobjlock); | |
149 | for (i = 0; i < npages; i++) { | 150 | for (i = 0; i < npages; i++) { | |
150 | 151 | |||
151 | KASSERT(pgs[i] != NULL); | 152 | KASSERT(pgs[i] != NULL); | |
152 | KASSERT(!(pgs[i]->flags & PG_RELEASED)); | 153 | KASSERT(!(pgs[i]->flags & PG_RELEASED)); | |
153 | 154 | |||
154 | /* | 155 | /* | |
155 | * Loan break | 156 | * Loan break | |
156 | */ | 157 | */ | |
157 | if (pgs[i]->loan_count) { | 158 | if (pgs[i]->loan_count) { | |
158 | while (pgs[i]->loan_count) { | 159 | while (pgs[i]->loan_count) { | |
159 | pg = uvm_loanbreak(pgs[i]); | 160 | pg = uvm_loanbreak(pgs[i]); | |
160 | if (!pg) { | 161 | if (!pg) { | |
161 | mutex_exit(uobj->vmobjlock); | 162 | mutex_exit(uobj->vmobjlock); | |
162 | uvm_wait("uobjwirepg"); | 163 | uvm_wait("uobjwirepg"); | |
163 | mutex_enter(uobj->vmobjlock); | 164 | mutex_enter(uobj->vmobjlock); | |
164 | continue; | 165 | continue; | |
165 | } | 166 | } | |
166 | } | 167 | } | |
167 | pgs[i] = pg; | 168 | pgs[i] = pg; | |
168 | } | 169 | } | |
169 | 170 | |||
170 | if (pgs[i]->pqflags & PQ_AOBJ) { | 171 | if (pgs[i]->pqflags & PQ_AOBJ) { | |
171 | pgs[i]->flags &= ~(PG_CLEAN); | 172 | pgs[i]->flags &= ~(PG_CLEAN); | |
172 | uao_dropswap(uobj, i); | 173 | uao_dropswap(uobj, i); | |
173 | } | 174 | } | |
174 | } | 175 | } | |
175 | 176 | |||
176 | /* Wire the pages */ | 177 | /* Wire the pages */ | |
177 | mutex_enter(&uvm_pageqlock); | 178 | mutex_enter(&uvm_pageqlock); | |
178 | for (i = 0; i < npages; i++) { | 179 | for (i = 0; i < npages; i++) { | |
179 | uvm_pagewire(pgs[i]); | 180 | uvm_pagewire(pgs[i]); | |
181 | if (list != NULL) | |||
182 | TAILQ_INSERT_TAIL(list, pgs[i], pageq.queue); | |||
180 | } | 183 | } | |
181 | mutex_exit(&uvm_pageqlock); | 184 | mutex_exit(&uvm_pageqlock); | |
182 | 185 | |||
183 | /* Unbusy the pages */ | 186 | /* Unbusy the pages */ | |
184 | uvm_page_unbusy(pgs, npages); | 187 | uvm_page_unbusy(pgs, npages); | |
185 | 188 | |||
186 | left -= npages; | 189 | left -= npages; | |
187 | offset += npages << PAGE_SHIFT; | 190 | offset += npages << PAGE_SHIFT; | |
188 | } | 191 | } | |
189 | mutex_exit(uobj->vmobjlock); | 192 | mutex_exit(uobj->vmobjlock); | |
190 | 193 | |||
191 | return 0; | 194 | return 0; | |
192 | 195 | |||
193 | error: | 196 | error: | |
194 | /* Unwire the pages which has been wired */ | 197 | /* Unwire the pages which has been wired */ | |
195 | uvm_obj_unwirepages(uobj, start, offset); | 198 | uvm_obj_unwirepages(uobj, start, offset); | |
196 | 199 | |||
197 | return error; | 200 | return error; | |
198 | } | 201 | } | |
199 | 202 | |||
200 | /* | 203 | /* | |
201 | * uvm_obj_unwirepages: unwire the pages of entire UVM object. | 204 | * uvm_obj_unwirepages: unwire the pages of entire UVM object. | |
202 | * | 205 | * | |
203 | * => NOTE: this function should only be used for types of objects | 206 | * => NOTE: this function should only be used for types of objects | |
204 | * where PG_RELEASED flag is never set | 207 | * where PG_RELEASED flag is never set | |
205 | * => caller must pass page-aligned start and end values | 208 | * => caller must pass page-aligned start and end values | |
206 | */ | 209 | */ | |
207 | void | 210 | void | |
208 | uvm_obj_unwirepages(struct uvm_object *uobj, off_t start, off_t end) | 211 | uvm_obj_unwirepages(struct uvm_object *uobj, off_t start, off_t end) | |
209 | { | 212 | { | |
210 | struct vm_page *pg; | 213 | struct vm_page *pg; | |
211 | off_t offset; | 214 | off_t offset; | |
212 | 215 | |||
213 | mutex_enter(uobj->vmobjlock); | 216 | mutex_enter(uobj->vmobjlock); | |
214 | mutex_enter(&uvm_pageqlock); | 217 | mutex_enter(&uvm_pageqlock); | |
215 | for (offset = start; offset < end; offset += PAGE_SIZE) { | 218 | for (offset = start; offset < end; offset += PAGE_SIZE) { | |
216 | pg = uvm_pagelookup(uobj, offset); | 219 | pg = uvm_pagelookup(uobj, offset); | |
217 | 220 | |||
218 | KASSERT(pg != NULL); | 221 | KASSERT(pg != NULL); | |
219 | KASSERT(!(pg->flags & PG_RELEASED)); | 222 | KASSERT(!(pg->flags & PG_RELEASED)); | |
220 | 223 | |||
221 | uvm_pageunwire(pg); | 224 | uvm_pageunwire(pg); | |
222 | } | 225 | } | |
223 | mutex_exit(&uvm_pageqlock); | 226 | mutex_exit(&uvm_pageqlock); | |
224 | mutex_exit(uobj->vmobjlock); | 227 | mutex_exit(uobj->vmobjlock); | |
225 | } | 228 | } | |
226 | 229 | |||
227 | #if (defined(DDB) || defined(DEBUGPRINT)) && !defined(_RUMPKERNEL) | 230 | #if (defined(DDB) || defined(DEBUGPRINT)) && !defined(_RUMPKERNEL) | |
228 | 231 | |||
229 | /* | 232 | /* | |
230 | * uvm_object_printit: actually prints the object | 233 | * uvm_object_printit: actually prints the object | |
231 | */ | 234 | */ | |
232 | void | 235 | void | |
233 | uvm_object_printit(struct uvm_object *uobj, bool full, | 236 | uvm_object_printit(struct uvm_object *uobj, bool full, | |
234 | void (*pr)(const char *, ...)) | 237 | void (*pr)(const char *, ...)) | |
235 | { | 238 | { | |
236 | struct vm_page *pg; | 239 | struct vm_page *pg; | |
237 | int cnt = 0; | 240 | int cnt = 0; | |
238 | 241 | |||
239 | (*pr)("OBJECT %p: locked=%d, pgops=%p, npages=%d, ", | 242 | (*pr)("OBJECT %p: locked=%d, pgops=%p, npages=%d, ", | |
240 | uobj, mutex_owned(uobj->vmobjlock), uobj->pgops, uobj->uo_npages); | 243 | uobj, mutex_owned(uobj->vmobjlock), uobj->pgops, uobj->uo_npages); | |
241 | if (UVM_OBJ_IS_KERN_OBJECT(uobj)) | 244 | if (UVM_OBJ_IS_KERN_OBJECT(uobj)) | |
242 | (*pr)("refs=<SYSTEM>\n"); | 245 | (*pr)("refs=<SYSTEM>\n"); | |
243 | else | 246 | else | |
244 | (*pr)("refs=%d\n", uobj->uo_refs); | 247 | (*pr)("refs=%d\n", uobj->uo_refs); | |
245 | 248 | |||
246 | if (!full) { | 249 | if (!full) { | |
247 | return; | 250 | return; | |
248 | } | 251 | } | |
249 | (*pr)(" PAGES <pg,offset>:\n "); | 252 | (*pr)(" PAGES <pg,offset>:\n "); | |
250 | TAILQ_FOREACH(pg, &uobj->memq, listq.queue) { | 253 | TAILQ_FOREACH(pg, &uobj->memq, listq.queue) { | |
251 | cnt++; | 254 | cnt++; | |
252 | (*pr)("<%p,0x%llx> ", pg, (long long)pg->offset); | 255 | (*pr)("<%p,0x%llx> ", pg, (long long)pg->offset); | |
253 | if ((cnt % 3) == 0) { | 256 | if ((cnt % 3) == 0) { | |
254 | (*pr)("\n "); | 257 | (*pr)("\n "); | |
255 | } | 258 | } | |
256 | } | 259 | } | |
257 | if ((cnt % 3) != 0) { | 260 | if ((cnt % 3) != 0) { | |
258 | (*pr)("\n"); | 261 | (*pr)("\n"); | |
259 | } | 262 | } | |
260 | } | 263 | } | |
261 | 264 | |||
262 | #endif /* DDB || DEBUGPRINT */ | 265 | #endif /* DDB || DEBUGPRINT */ |