Sat Aug 27 09:11:53 2011 UTC ()
Add an optional pglist argument to uvm_obj_wirepages, to be
filled with the list of pages that were wired.


(christos)
diff -r1.121 -r1.122 src/sys/kern/sysv_shm.c
diff -r1.174 -r1.175 src/sys/uvm/uvm_extern.h
diff -r1.10 -r1.11 src/sys/uvm/uvm_object.c

cvs diff -r1.121 -r1.122 src/sys/kern/sysv_shm.c (switch to unified diff)

--- 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
84struct shmmap_entry { 84struct 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
90int shm_nused __cacheline_aligned; 90int shm_nused __cacheline_aligned;
91struct shmid_ds * shmsegs __read_mostly; 91struct shmid_ds * shmsegs __read_mostly;
92 92
93static kmutex_t shm_lock __cacheline_aligned; 93static kmutex_t shm_lock __cacheline_aligned;
94static kcondvar_t * shm_cv __cacheline_aligned; 94static kcondvar_t * shm_cv __cacheline_aligned;
95static int shm_last_free __cacheline_aligned; 95static int shm_last_free __cacheline_aligned;
96static size_t shm_committed __cacheline_aligned; 96static size_t shm_committed __cacheline_aligned;
97static int shm_use_phys __read_mostly; 97static int shm_use_phys __read_mostly;
98 98
99static kcondvar_t shm_realloc_cv; 99static kcondvar_t shm_realloc_cv;
100static bool shm_realloc_state; 100static bool shm_realloc_state;
101static u_int shm_realloc_disable; 101static u_int shm_realloc_disable;
102 102
103struct shmmap_state { 103struct 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
115static int shmrealloc(int); 115static 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 */
121static struct shmid_ds * 121static struct shmid_ds *
122shm_find_segment_by_shmid(int shmid) 122shm_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 */
148static void 148static void
149shm_free_segment(int segnum) 149shm_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 */
177static struct uvm_object * 177static struct uvm_object *
178shm_delete_mapping(struct shmmap_state *shmmap_s, 178shm_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 */
205static struct shmmap_state * 205static struct shmmap_state *
206shmmap_getprivate(struct proc *p) 206shmmap_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 */
248static inline int 248static inline int
249shm_memlock(struct lwp *l, struct shmid_ds *shmseg, int shmid, int cmd) 249shm_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 */
303int 303int
304sys_shmdt(struct lwp *l, const struct sys_shmdt_args *uap, register_t *retval) 304sys_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 */
369int 369int
370sys_shmat(struct lwp *l, const struct sys_shmat_args *uap, register_t *retval) 370sys_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));
477err: 477err:
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
485err_detach: 485err_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 */
502int 502int
503sys___shmctl50(struct lwp *l, const struct sys___shmctl50_args *uap, 503sys___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
530int 530int
531shmctl1(struct lwp *l, int shmid, int cmd, struct shmid_ds *shmbuf) 531shmctl1(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 */
597static inline int 597static inline int
598shmget_existing(struct lwp *l, const struct sys_shmget_args *uap, int mode, 598shmget_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;
604again: 604again:
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
650int 650int
651sys_shmget(struct lwp *l, const struct sys_shmget_args *uap, register_t *retval) 651sys_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
784void 784void
785shmfork(struct vmspace *vm1, struct vmspace *vm2) 785shmfork(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
802void 802void
803shmexit(struct vmspace *vm) 803shmexit(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
865static int 865static int
866shmrealloc(int newshmni) 866shmrealloc(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
945void 945void
946shminit(void) 946shminit(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
984static int 984static int
985sysctl_ipc_shmmni(SYSCTLFN_ARGS) 985sysctl_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
1003static int 1003static int
1004sysctl_ipc_shmmaxpgs(SYSCTLFN_ARGS) 1004sysctl_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
1026static int 1026static int
1027sysctl_ipc_shmmax(SYSCTLFN_ARGS) 1027sysctl_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
1049SYSCTL_SETUP(sysctl_ipc_shm_setup, "sysctl kern.ipc subtree setup") 1049SYSCTL_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}

cvs diff -r1.174 -r1.175 src/sys/uvm/uvm_extern.h (switch to unified diff)

--- 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
79typedef unsigned int uvm_flag_t; 79typedef unsigned int uvm_flag_t;
80 80
81typedef int vm_inherit_t; /* XXX: inheritance codes */ 81typedef int vm_inherit_t; /* XXX: inheritance codes */
82typedef off_t voff_t; /* XXX: offset within a uvm_object */ 82typedef off_t voff_t; /* XXX: offset within a uvm_object */
83typedef voff_t pgoff_t; /* XXX: number of pages within a uvm object */ 83typedef 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
233struct buf; 233struct buf;
234struct core; 234struct core;
235struct loadavg; 235struct loadavg;
236struct mount; 236struct mount;
237struct pglist; 237struct pglist;
238struct proc; 238struct proc;
239struct uio; 239struct uio;
240struct uvm_object; 240struct uvm_object;
241struct vm_anon; 241struct vm_anon;
242struct vmspace; 242struct vmspace;
243struct pmap; 243struct pmap;
244struct vnode; 244struct vnode;
245struct simplelock; 245struct simplelock;
246struct vm_map_entry; 246struct vm_map_entry;
247struct vm_map; 247struct vm_map;
248struct vm_page; 248struct vm_page;
249struct vmtotal; 249struct 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)
259struct uvm_pctparam { 259struct 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
270struct uvmexp { 270struct 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 */
380struct uvmexp_sysctl { 380struct 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 */
462extern struct uvmexp uvmexp; 462extern struct uvmexp uvmexp;
463/* MD code needs this without including <uvm/uvm.h> */ 463/* MD code needs this without including <uvm/uvm.h> */
464extern bool vm_page_zero_enable; 464extern 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 */
494struct vmspace { 494struct 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 */
520struct uvm_coredump_state { 520struct 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 */
535struct uvm_reclaim_hook { 535struct 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
540void uvm_reclaim_init(void); 540void uvm_reclaim_init(void);
541void uvm_reclaim_hook_add(struct uvm_reclaim_hook *); 541void uvm_reclaim_hook_add(struct uvm_reclaim_hook *);
542void uvm_reclaim_hook_del(struct uvm_reclaim_hook *); 542void 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 */
547extern struct vm_map *kernel_map; 547extern struct vm_map *kernel_map;
548extern struct vm_map *kmem_map; 548extern struct vm_map *kmem_map;
549extern struct vm_map *phys_map; 549extern 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>
558MALLOC_DECLARE(M_VMMAP); 558MALLOC_DECLARE(M_VMMAP);
559MALLOC_DECLARE(M_VMPMAP); 559MALLOC_DECLARE(M_VMPMAP);
560 560
561/* vm_machdep.c */ 561/* vm_machdep.c */
562int vmapbuf(struct buf *, vsize_t); 562int vmapbuf(struct buf *, vsize_t);
563void vunmapbuf(struct buf *, vsize_t); 563void vunmapbuf(struct buf *, vsize_t);
564 564
565/* uvm_aobj.c */ 565/* uvm_aobj.c */
566struct uvm_object *uao_create(vsize_t, int); 566struct uvm_object *uao_create(vsize_t, int);
567void uao_detach(struct uvm_object *); 567void uao_detach(struct uvm_object *);
568void uao_reference(struct uvm_object *); 568void uao_reference(struct uvm_object *);
569 569
570/* uvm_bio.c */ 570/* uvm_bio.c */
571void ubc_init(void); 571void ubc_init(void);
572void * ubc_alloc(struct uvm_object *, voff_t, vsize_t *, int, 572void * ubc_alloc(struct uvm_object *, voff_t, vsize_t *, int,
573 int); 573 int);
574void ubc_release(void *, int); 574void ubc_release(void *, int);
575int ubc_uiomove(struct uvm_object *, struct uio *, vsize_t, 575int ubc_uiomove(struct uvm_object *, struct uio *, vsize_t,
576 int, int); 576 int, int);
577void ubc_zerorange(struct uvm_object *, off_t, size_t, int); 577void ubc_zerorange(struct uvm_object *, off_t, size_t, int);
578void ubc_purge(struct uvm_object *); 578void ubc_purge(struct uvm_object *);
579 579
580/* uvm_emap.c */ 580/* uvm_emap.c */
581void uvm_emap_sysinit(void); 581void uvm_emap_sysinit(void);
582#ifdef __HAVE_PMAP_EMAP 582#ifdef __HAVE_PMAP_EMAP
583void uvm_emap_switch(lwp_t *); 583void 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
588u_int uvm_emap_gen_return(void); 588u_int uvm_emap_gen_return(void);
589void uvm_emap_update(u_int); 589void uvm_emap_update(u_int);
590 590
591vaddr_t uvm_emap_alloc(vsize_t, bool); 591vaddr_t uvm_emap_alloc(vsize_t, bool);
592void uvm_emap_free(vaddr_t, size_t); 592void uvm_emap_free(vaddr_t, size_t);
593 593
594void uvm_emap_enter(vaddr_t, struct vm_page **, u_int); 594void uvm_emap_enter(vaddr_t, struct vm_page **, u_int);
595void uvm_emap_remove(vaddr_t, vsize_t); 595void uvm_emap_remove(vaddr_t, vsize_t);
596 596
597#ifdef __HAVE_PMAP_EMAP 597#ifdef __HAVE_PMAP_EMAP
598void uvm_emap_consume(u_int); 598void uvm_emap_consume(u_int);
599u_int uvm_emap_produce(void); 599u_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)
607int uvm_fault_internal(struct vm_map *, vaddr_t, vm_prot_t, int); 607int 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)
612void uvm_chgkprot(void *, size_t, int); 612void uvm_chgkprot(void *, size_t, int);
613#endif 613#endif
614void uvm_proc_fork(struct proc *, struct proc *, bool); 614void uvm_proc_fork(struct proc *, struct proc *, bool);
615void uvm_lwp_fork(struct lwp *, struct lwp *, 615void uvm_lwp_fork(struct lwp *, struct lwp *,
616 void *, size_t, void (*)(void *), void *); 616 void *, size_t, void (*)(void *), void *);
617int uvm_coredump_walkmap(struct proc *, 617int 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 *);
621void uvm_proc_exit(struct proc *); 621void uvm_proc_exit(struct proc *);
622void uvm_lwp_exit(struct lwp *); 622void uvm_lwp_exit(struct lwp *);
623void uvm_init_limits(struct proc *); 623void uvm_init_limits(struct proc *);
624bool uvm_kernacc(void *, size_t, vm_prot_t); 624bool uvm_kernacc(void *, size_t, vm_prot_t);
625__dead void uvm_scheduler(void); 625__dead void uvm_scheduler(void);
626vaddr_t uvm_uarea_alloc(void); 626vaddr_t uvm_uarea_alloc(void);
627void uvm_uarea_free(vaddr_t); 627void uvm_uarea_free(vaddr_t);
628vaddr_t uvm_uarea_system_alloc(void); 628vaddr_t uvm_uarea_system_alloc(void);
629void uvm_uarea_system_free(vaddr_t); 629void uvm_uarea_system_free(vaddr_t);
630vaddr_t uvm_lwp_getuarea(lwp_t *); 630vaddr_t uvm_lwp_getuarea(lwp_t *);
631void uvm_lwp_setuarea(lwp_t *, vaddr_t); 631void uvm_lwp_setuarea(lwp_t *, vaddr_t);
632int uvm_vslock(struct vmspace *, void *, size_t, vm_prot_t); 632int uvm_vslock(struct vmspace *, void *, size_t, vm_prot_t);
633void uvm_vsunlock(struct vmspace *, void *, size_t); 633void uvm_vsunlock(struct vmspace *, void *, size_t);
634void uvm_cpu_attach(struct cpu_info *); 634void uvm_cpu_attach(struct cpu_info *);
635 635
636 636
637/* uvm_init.c */ 637/* uvm_init.c */
638void uvm_init(void); 638void uvm_init(void);
639 639
640/* uvm_io.c */ 640/* uvm_io.c */
641int uvm_io(struct vm_map *, struct uio *); 641int uvm_io(struct vm_map *, struct uio *);
642 642
643/* uvm_km.c */ 643/* uvm_km.c */
644vaddr_t uvm_km_alloc(struct vm_map *, vsize_t, vsize_t, 644vaddr_t uvm_km_alloc(struct vm_map *, vsize_t, vsize_t,
645 uvm_flag_t); 645 uvm_flag_t);
646void uvm_km_free(struct vm_map *, vaddr_t, vsize_t, 646void uvm_km_free(struct vm_map *, vaddr_t, vsize_t,
647 uvm_flag_t); 647 uvm_flag_t);
648 648
649struct vm_map *uvm_km_suballoc(struct vm_map *, vaddr_t *, 649struct 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 *);
652vaddr_t uvm_km_alloc_poolpage(struct vm_map *, bool); 652vaddr_t uvm_km_alloc_poolpage(struct vm_map *, bool);
653void uvm_km_free_poolpage(struct vm_map *, vaddr_t); 653void uvm_km_free_poolpage(struct vm_map *, vaddr_t);
654vaddr_t uvm_km_alloc_poolpage_cache(struct vm_map *, bool); 654vaddr_t uvm_km_alloc_poolpage_cache(struct vm_map *, bool);
655void uvm_km_free_poolpage_cache(struct vm_map *, vaddr_t); 655void uvm_km_free_poolpage_cache(struct vm_map *, vaddr_t);
656void uvm_km_vacache_init(struct vm_map *, 656void 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 */
660int uvm_map(struct vm_map *, vaddr_t *, vsize_t, 660int 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);
663int uvm_map_pageable(struct vm_map *, vaddr_t, 663int uvm_map_pageable(struct vm_map *, vaddr_t,
664 vaddr_t, bool, int); 664 vaddr_t, bool, int);
665int uvm_map_pageable_all(struct vm_map *, int, vsize_t); 665int uvm_map_pageable_all(struct vm_map *, int, vsize_t);
666bool uvm_map_checkprot(struct vm_map *, vaddr_t, 666bool uvm_map_checkprot(struct vm_map *, vaddr_t,
667 vaddr_t, vm_prot_t); 667 vaddr_t, vm_prot_t);
668int uvm_map_protect(struct vm_map *, vaddr_t, 668int uvm_map_protect(struct vm_map *, vaddr_t,
669 vaddr_t, vm_prot_t, bool); 669 vaddr_t, vm_prot_t, bool);
670struct vmspace *uvmspace_alloc(vaddr_t, vaddr_t); 670struct vmspace *uvmspace_alloc(vaddr_t, vaddr_t);
671void uvmspace_init(struct vmspace *, struct pmap *, 671void uvmspace_init(struct vmspace *, struct pmap *,
672 vaddr_t, vaddr_t); 672 vaddr_t, vaddr_t);
673void uvmspace_exec(struct lwp *, vaddr_t, vaddr_t); 673void uvmspace_exec(struct lwp *, vaddr_t, vaddr_t);
674struct vmspace *uvmspace_fork(struct vmspace *); 674struct vmspace *uvmspace_fork(struct vmspace *);
675void uvmspace_addref(struct vmspace *); 675void uvmspace_addref(struct vmspace *);
676void uvmspace_free(struct vmspace *); 676void uvmspace_free(struct vmspace *);
677void uvmspace_share(struct proc *, struct proc *); 677void uvmspace_share(struct proc *, struct proc *);
678void uvmspace_unshare(struct lwp *); 678void uvmspace_unshare(struct lwp *);
679 679
680void uvm_whatis(uintptr_t, void (*)(const char *, ...)); 680void uvm_whatis(uintptr_t, void (*)(const char *, ...));
681 681
682/* uvm_meter.c */ 682/* uvm_meter.c */
683int uvm_sysctl(int *, u_int, void *, size_t *, 683int uvm_sysctl(int *, u_int, void *, size_t *,
684 void *, size_t, struct proc *); 684 void *, size_t, struct proc *);
685int uvm_pctparam_check(struct uvm_pctparam *, int); 685int uvm_pctparam_check(struct uvm_pctparam *, int);
686void uvm_pctparam_set(struct uvm_pctparam *, int); 686void uvm_pctparam_set(struct uvm_pctparam *, int);
687int uvm_pctparam_get(struct uvm_pctparam *); 687int uvm_pctparam_get(struct uvm_pctparam *);
688void uvm_pctparam_init(struct uvm_pctparam *, int, 688void uvm_pctparam_init(struct uvm_pctparam *, int,
689 int (*)(struct uvm_pctparam *, int)); 689 int (*)(struct uvm_pctparam *, int));
690int uvm_pctparam_createsysctlnode(struct uvm_pctparam *, 690int 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 */
694int uvm_mmap(struct vm_map *, vaddr_t *, vsize_t, 694int 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);
697vaddr_t uvm_default_mapaddr(struct proc *, vaddr_t, vsize_t); 697vaddr_t uvm_default_mapaddr(struct proc *, vaddr_t, vsize_t);
698 698
699/* uvm_mremap.c */ 699/* uvm_mremap.c */
700int uvm_mremap(struct vm_map *, vaddr_t, vsize_t, 700int 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 */
705void uvm_obj_init(struct uvm_object *, 705void uvm_obj_init(struct uvm_object *,
706 const struct uvm_pagerops *, bool, u_int); 706 const struct uvm_pagerops *, bool, u_int);
707void uvm_obj_setlock(struct uvm_object *, kmutex_t *); 707void uvm_obj_setlock(struct uvm_object *, kmutex_t *);
708void uvm_obj_destroy(struct uvm_object *, bool); 708void uvm_obj_destroy(struct uvm_object *, bool);
709int uvm_obj_wirepages(struct uvm_object *, off_t, off_t); 709int uvm_obj_wirepages(struct uvm_object *, off_t, off_t,
 710 struct pglist *);
710void uvm_obj_unwirepages(struct uvm_object *, off_t, off_t); 711void uvm_obj_unwirepages(struct uvm_object *, off_t, off_t);
711 712
712/* uvm_page.c */ 713/* uvm_page.c */
713struct vm_page *uvm_pagealloc_strat(struct uvm_object *, 714struct 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)
718void uvm_pagereplace(struct vm_page *, 719void uvm_pagereplace(struct vm_page *,
719 struct vm_page *); 720 struct vm_page *);
720void uvm_pagerealloc(struct vm_page *, 721void 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 */
723void uvm_page_physload(paddr_t, paddr_t, paddr_t, 724void uvm_page_physload(paddr_t, paddr_t, paddr_t,
724 paddr_t, int); 725 paddr_t, int);
725void uvm_setpagesize(void); 726void uvm_setpagesize(void);
726 727
727/* uvm_pager.c */ 728/* uvm_pager.c */
728void uvm_aio_biodone(struct buf *); 729void uvm_aio_biodone(struct buf *);
729void uvm_aio_aiodone(struct buf *); 730void uvm_aio_aiodone(struct buf *);
730void uvm_aio_aiodone_pages(struct vm_page **, int, bool, 731void uvm_aio_aiodone_pages(struct vm_page **, int, bool,
731 int); 732 int);
732 733
733/* uvm_pdaemon.c */ 734/* uvm_pdaemon.c */
734void uvm_pageout(void *); 735void uvm_pageout(void *);
735struct work; 736struct work;
736void uvm_aiodone_worker(struct work *, void *); 737void uvm_aiodone_worker(struct work *, void *);
737void uvm_pageout_start(int); 738void uvm_pageout_start(int);
738void uvm_pageout_done(int); 739void uvm_pageout_done(int);
739void uvm_estimatepageable(int *, int *); 740void uvm_estimatepageable(int *, int *);
740 741
741/* uvm_pglist.c */ 742/* uvm_pglist.c */
742int uvm_pglistalloc(psize_t, paddr_t, paddr_t, 743int 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);
744void uvm_pglistfree(struct pglist *); 745void uvm_pglistfree(struct pglist *);
745 746
746/* uvm_swap.c */ 747/* uvm_swap.c */
747void uvm_swap_init(void); 748void uvm_swap_init(void);
748 749
749/* uvm_unix.c */ 750/* uvm_unix.c */
750int uvm_grow(struct proc *, vaddr_t); 751int uvm_grow(struct proc *, vaddr_t);
751 752
752/* uvm_user.c */ 753/* uvm_user.c */
753void uvm_deallocate(struct vm_map *, vaddr_t, vsize_t); 754void uvm_deallocate(struct vm_map *, vaddr_t, vsize_t);
754 755
755/* uvm_vnode.c */ 756/* uvm_vnode.c */
756void uvm_vnp_setsize(struct vnode *, voff_t); 757void uvm_vnp_setsize(struct vnode *, voff_t);
757void uvm_vnp_setwritesize(struct vnode *, voff_t); 758void uvm_vnp_setwritesize(struct vnode *, voff_t);
758int uvn_findpages(struct uvm_object *, voff_t, 759int uvn_findpages(struct uvm_object *, voff_t,
759 int *, struct vm_page **, int); 760 int *, struct vm_page **, int);
760bool uvn_text_p(struct uvm_object *); 761bool uvn_text_p(struct uvm_object *);
761bool uvn_clean_p(struct uvm_object *); 762bool uvn_clean_p(struct uvm_object *);
762bool uvn_needs_writefault_p(struct uvm_object *); 763bool uvn_needs_writefault_p(struct uvm_object *);
763 764
764/* kern_malloc.c */ 765/* kern_malloc.c */
765void kmeminit_nkmempages(void); 766void kmeminit_nkmempages(void);
766void kmeminit(void); 767void kmeminit(void);
767extern int nkmempages; 768extern int nkmempages;
768 769
769#endif /* _KERNEL */ 770#endif /* _KERNEL */
770 771
771#endif /* _UVM_UVM_EXTERN_H_ */ 772#endif /* _UVM_UVM_EXTERN_H_ */

cvs diff -r1.10 -r1.11 src/sys/uvm/uvm_object.c (switch to unified diff)

--- 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 */
58void 58void
59uvm_obj_init(struct uvm_object *uo, const struct uvm_pagerops *ops, 59uvm_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 */
81void 81void
82uvm_obj_destroy(struct uvm_object *uo, bool dlock) 82uvm_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 */
102void 102void
103uvm_obj_setlock(struct uvm_object *uo, kmutex_t *lockptr) 103uvm_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 */
125int 125int
126uvm_obj_wirepages(struct uvm_object *uobj, off_t start, off_t end) 126uvm_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
193error: 196error:
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 */
207void 210void
208uvm_obj_unwirepages(struct uvm_object *uobj, off_t start, off_t end) 211uvm_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 */
232void 235void
233uvm_object_printit(struct uvm_object *uobj, bool full, 236uvm_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 */