uvm_pglist.c revision 1.38.28.2 1 1.38.28.2 ad /* $NetBSD: uvm_pglist.c,v 1.38.28.2 2007/07/21 19:21:56 ad Exp $ */
2 1.38.28.2 ad
3 1.38.28.2 ad /*-
4 1.38.28.2 ad * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 1.38.28.2 ad * All rights reserved.
6 1.38.28.2 ad *
7 1.38.28.2 ad * This code is derived from software contributed to The NetBSD Foundation
8 1.38.28.2 ad * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 1.38.28.2 ad * NASA Ames Research Center.
10 1.38.28.2 ad *
11 1.38.28.2 ad * Redistribution and use in source and binary forms, with or without
12 1.38.28.2 ad * modification, are permitted provided that the following conditions
13 1.38.28.2 ad * are met:
14 1.38.28.2 ad * 1. Redistributions of source code must retain the above copyright
15 1.38.28.2 ad * notice, this list of conditions and the following disclaimer.
16 1.38.28.2 ad * 2. Redistributions in binary form must reproduce the above copyright
17 1.38.28.2 ad * notice, this list of conditions and the following disclaimer in the
18 1.38.28.2 ad * documentation and/or other materials provided with the distribution.
19 1.38.28.2 ad * 3. All advertising materials mentioning features or use of this software
20 1.38.28.2 ad * must display the following acknowledgement:
21 1.38.28.2 ad * This product includes software developed by the NetBSD
22 1.38.28.2 ad * Foundation, Inc. and its contributors.
23 1.38.28.2 ad * 4. Neither the name of The NetBSD Foundation nor the names of its
24 1.38.28.2 ad * contributors may be used to endorse or promote products derived
25 1.38.28.2 ad * from this software without specific prior written permission.
26 1.38.28.2 ad *
27 1.38.28.2 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 1.38.28.2 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 1.38.28.2 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 1.38.28.2 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 1.38.28.2 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 1.38.28.2 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 1.38.28.2 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 1.38.28.2 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 1.38.28.2 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 1.38.28.2 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 1.38.28.2 ad * POSSIBILITY OF SUCH DAMAGE.
38 1.38.28.2 ad */
39 1.38.28.2 ad
40 1.38.28.2 ad /*
41 1.38.28.2 ad * uvm_pglist.c: pglist functions
42 1.38.28.2 ad */
43 1.38.28.2 ad
44 1.38.28.2 ad #include <sys/cdefs.h>
45 1.38.28.2 ad __KERNEL_RCSID(0, "$NetBSD: uvm_pglist.c,v 1.38.28.2 2007/07/21 19:21:56 ad Exp $");
46 1.38.28.2 ad
47 1.38.28.2 ad #include <sys/param.h>
48 1.38.28.2 ad #include <sys/systm.h>
49 1.38.28.2 ad #include <sys/malloc.h>
50 1.38.28.2 ad #include <sys/proc.h>
51 1.38.28.2 ad
52 1.38.28.2 ad #include <uvm/uvm.h>
53 1.38.28.2 ad #include <uvm/uvm_pdpolicy.h>
54 1.38.28.2 ad
55 1.38.28.2 ad #ifdef VM_PAGE_ALLOC_MEMORY_STATS
56 1.38.28.2 ad #define STAT_INCR(v) (v)++
57 1.38.28.2 ad #define STAT_DECR(v) do { \
58 1.38.28.2 ad if ((v) == 0) \
59 1.38.28.2 ad printf("%s:%d -- Already 0!\n", __FILE__, __LINE__); \
60 1.38.28.2 ad else \
61 1.38.28.2 ad (v)--; \
62 1.38.28.2 ad } while (/*CONSTCOND*/ 0)
63 1.38.28.2 ad u_long uvm_pglistalloc_npages;
64 1.38.28.2 ad #else
65 1.38.28.2 ad #define STAT_INCR(v)
66 1.38.28.2 ad #define STAT_DECR(v)
67 1.38.28.2 ad #endif
68 1.38.28.2 ad
69 1.38.28.2 ad /*
70 1.38.28.2 ad * uvm_pglistalloc: allocate a list of pages
71 1.38.28.2 ad *
72 1.38.28.2 ad * => allocated pages are placed onto an rlist. rlist is
73 1.38.28.2 ad * initialized by uvm_pglistalloc.
74 1.38.28.2 ad * => returns 0 on success or errno on failure
75 1.38.28.2 ad * => implementation allocates a single segment if any constraints are
76 1.38.28.2 ad * imposed by call arguments.
77 1.38.28.2 ad * => doesn't take into account clean non-busy pages on inactive list
78 1.38.28.2 ad * that could be used(?)
79 1.38.28.2 ad * => params:
80 1.38.28.2 ad * size the size of the allocation, rounded to page size.
81 1.38.28.2 ad * low the low address of the allowed allocation range.
82 1.38.28.2 ad * high the high address of the allowed allocation range.
83 1.38.28.2 ad * alignment memory must be aligned to this power-of-two boundary.
84 1.38.28.2 ad * boundary no segment in the allocation may cross this
85 1.38.28.2 ad * power-of-two boundary (relative to zero).
86 1.38.28.2 ad */
87 1.38.28.2 ad
88 1.38.28.2 ad static void
89 1.38.28.2 ad uvm_pglist_add(struct vm_page *pg, struct pglist *rlist)
90 1.38.28.2 ad {
91 1.38.28.2 ad int free_list, color, pgflidx;
92 1.38.28.2 ad #ifdef DEBUG
93 1.38.28.2 ad struct vm_page *tp;
94 1.38.28.2 ad #endif
95 1.38.28.2 ad
96 1.38.28.2 ad #if PGFL_NQUEUES != 2
97 1.38.28.2 ad #error uvm_pglistalloc needs to be updated
98 1.38.28.2 ad #endif
99 1.38.28.2 ad
100 1.38.28.2 ad free_list = uvm_page_lookup_freelist(pg);
101 1.38.28.2 ad color = VM_PGCOLOR_BUCKET(pg);
102 1.38.28.2 ad pgflidx = (pg->flags & PG_ZERO) ? PGFL_ZEROS : PGFL_UNKNOWN;
103 1.38.28.2 ad #ifdef DEBUG
104 1.38.28.2 ad for (tp = TAILQ_FIRST(&uvm.page_free[
105 1.38.28.2 ad free_list].pgfl_buckets[color].pgfl_queues[pgflidx]);
106 1.38.28.2 ad tp != NULL;
107 1.38.28.2 ad tp = TAILQ_NEXT(tp, pageq)) {
108 1.38.28.2 ad if (tp == pg)
109 1.38.28.2 ad break;
110 1.38.28.2 ad }
111 1.38.28.2 ad if (tp == NULL)
112 1.38.28.2 ad panic("uvm_pglistalloc: page not on freelist");
113 1.38.28.2 ad #endif
114 1.38.28.2 ad TAILQ_REMOVE(&uvm.page_free[free_list].pgfl_buckets[
115 1.38.28.2 ad color].pgfl_queues[pgflidx], pg, pageq);
116 1.38.28.2 ad uvmexp.free--;
117 1.38.28.2 ad if (pg->flags & PG_ZERO)
118 1.38.28.2 ad uvmexp.zeropages--;
119 1.38.28.2 ad pg->flags = PG_CLEAN;
120 1.38.28.2 ad pg->pqflags = 0;
121 1.38.28.2 ad pg->uobject = NULL;
122 1.38.28.2 ad pg->uanon = NULL;
123 1.38.28.2 ad TAILQ_INSERT_TAIL(rlist, pg, pageq);
124 1.38.28.2 ad STAT_INCR(uvm_pglistalloc_npages);
125 1.38.28.2 ad }
126 1.38.28.2 ad
127 1.38.28.2 ad static int
128 1.38.28.2 ad uvm_pglistalloc_c_ps(struct vm_physseg *ps, int num, paddr_t low, paddr_t high,
129 1.38.28.2 ad paddr_t alignment, paddr_t boundary, struct pglist *rlist)
130 1.38.28.2 ad {
131 1.38.28.2 ad int try, limit, tryidx, end, idx;
132 1.38.28.2 ad struct vm_page *pgs;
133 1.38.28.2 ad int pagemask;
134 1.38.28.2 ad #ifdef DEBUG
135 1.38.28.2 ad paddr_t idxpa, lastidxpa;
136 1.38.28.2 ad int cidx = 0; /* XXX: GCC */
137 1.38.28.2 ad #endif
138 1.38.28.2 ad #ifdef PGALLOC_VERBOSE
139 1.38.28.2 ad printf("pgalloc: contig %d pgs from psi %ld\n", num,
140 1.38.28.2 ad (long)(ps - vm_physmem));
141 1.38.28.2 ad #endif
142 1.38.28.2 ad
143 1.38.28.2 ad try = roundup(max(atop(low), ps->avail_start), atop(alignment));
144 1.38.28.2 ad limit = min(atop(high), ps->avail_end);
145 1.38.28.2 ad pagemask = ~((boundary >> PAGE_SHIFT) - 1);
146 1.38.28.2 ad
147 1.38.28.2 ad for (;;) {
148 1.38.28.2 ad if (try + num > limit) {
149 1.38.28.2 ad /*
150 1.38.28.2 ad * We've run past the allowable range.
151 1.38.28.2 ad */
152 1.38.28.2 ad return (0); /* FAIL */
153 1.38.28.2 ad }
154 1.38.28.2 ad if (boundary != 0 &&
155 1.38.28.2 ad ((try ^ (try + num - 1)) & pagemask) != 0) {
156 1.38.28.2 ad /*
157 1.38.28.2 ad * Region crosses boundary. Jump to the boundary
158 1.38.28.2 ad * just crossed and ensure alignment.
159 1.38.28.2 ad */
160 1.38.28.2 ad try = (try + num - 1) & pagemask;
161 1.38.28.2 ad try = roundup(try, atop(alignment));
162 1.38.28.2 ad continue;
163 1.38.28.2 ad }
164 1.38.28.2 ad #ifdef DEBUG
165 1.38.28.2 ad /*
166 1.38.28.2 ad * Make sure this is a managed physical page.
167 1.38.28.2 ad */
168 1.38.28.2 ad
169 1.38.28.2 ad if (vm_physseg_find(try, &cidx) != ps - vm_physmem)
170 1.38.28.2 ad panic("pgalloc contig: botch1");
171 1.38.28.2 ad if (cidx != try - ps->start)
172 1.38.28.2 ad panic("pgalloc contig: botch2");
173 1.38.28.2 ad if (vm_physseg_find(try + num - 1, &cidx) != ps - vm_physmem)
174 1.38.28.2 ad panic("pgalloc contig: botch3");
175 1.38.28.2 ad if (cidx != try - ps->start + num - 1)
176 1.38.28.2 ad panic("pgalloc contig: botch4");
177 1.38.28.2 ad #endif
178 1.38.28.2 ad tryidx = try - ps->start;
179 1.38.28.2 ad end = tryidx + num;
180 1.38.28.2 ad pgs = ps->pgs;
181 1.38.28.2 ad
182 1.38.28.2 ad /*
183 1.38.28.2 ad * Found a suitable starting page. See if the range is free.
184 1.38.28.2 ad */
185 1.38.28.2 ad for (idx = tryidx; idx < end; idx++) {
186 1.38.28.2 ad if (VM_PAGE_IS_FREE(&pgs[idx]) == 0)
187 1.38.28.2 ad break;
188 1.38.28.2 ad
189 1.38.28.2 ad #ifdef DEBUG
190 1.38.28.2 ad idxpa = VM_PAGE_TO_PHYS(&pgs[idx]);
191 1.38.28.2 ad if (idx > tryidx) {
192 1.38.28.2 ad lastidxpa = VM_PAGE_TO_PHYS(&pgs[idx - 1]);
193 1.38.28.2 ad if ((lastidxpa + PAGE_SIZE) != idxpa) {
194 1.38.28.2 ad /*
195 1.38.28.2 ad * Region not contiguous.
196 1.38.28.2 ad */
197 1.38.28.2 ad panic("pgalloc contig: botch5");
198 1.38.28.2 ad }
199 1.38.28.2 ad if (boundary != 0 &&
200 1.38.28.2 ad ((lastidxpa ^ idxpa) & ~(boundary - 1))
201 1.38.28.2 ad != 0) {
202 1.38.28.2 ad /*
203 1.38.28.2 ad * Region crosses boundary.
204 1.38.28.2 ad */
205 1.38.28.2 ad panic("pgalloc contig: botch6");
206 1.38.28.2 ad }
207 1.38.28.2 ad }
208 1.38.28.2 ad #endif
209 1.38.28.2 ad }
210 1.38.28.2 ad if (idx == end)
211 1.38.28.2 ad break;
212 1.38.28.2 ad
213 1.38.28.2 ad try += atop(alignment);
214 1.38.28.2 ad }
215 1.38.28.2 ad
216 1.38.28.2 ad /*
217 1.38.28.2 ad * we have a chunk of memory that conforms to the requested constraints.
218 1.38.28.2 ad */
219 1.38.28.2 ad idx = tryidx;
220 1.38.28.2 ad while (idx < end)
221 1.38.28.2 ad uvm_pglist_add(&pgs[idx++], rlist);
222 1.38.28.2 ad
223 1.38.28.2 ad #ifdef PGALLOC_VERBOSE
224 1.38.28.2 ad printf("got %d pgs\n", num);
225 1.38.28.2 ad #endif
226 1.38.28.2 ad return (num); /* number of pages allocated */
227 1.38.28.2 ad }
228 1.38.28.2 ad
229 1.38.28.2 ad static int
230 1.38.28.2 ad uvm_pglistalloc_contig(int num, paddr_t low, paddr_t high, paddr_t alignment,
231 1.38.28.2 ad paddr_t boundary, struct pglist *rlist)
232 1.38.28.2 ad {
233 1.38.28.2 ad int fl, psi;
234 1.38.28.2 ad struct vm_physseg *ps;
235 1.38.28.2 ad int error;
236 1.38.28.2 ad
237 1.38.28.2 ad /* Default to "lose". */
238 1.38.28.2 ad error = ENOMEM;
239 1.38.28.2 ad
240 1.38.28.2 ad /*
241 1.38.28.2 ad * Block all memory allocation and lock the free list.
242 1.38.28.2 ad */
243 1.38.28.2 ad mutex_spin_enter(&uvm_fpageqlock);
244 1.38.28.2 ad
245 1.38.28.2 ad /* Are there even any free pages? */
246 1.38.28.2 ad if (uvmexp.free <= (uvmexp.reserve_pagedaemon + uvmexp.reserve_kernel))
247 1.38.28.2 ad goto out;
248 1.38.28.2 ad
249 1.38.28.2 ad for (fl = 0; fl < VM_NFREELIST; fl++) {
250 1.38.28.2 ad #if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST)
251 1.38.28.2 ad for (psi = vm_nphysseg - 1 ; psi >= 0 ; psi--)
252 1.38.28.2 ad #else
253 1.38.28.2 ad for (psi = 0 ; psi < vm_nphysseg ; psi++)
254 1.38.28.2 ad #endif
255 1.38.28.2 ad {
256 1.38.28.2 ad ps = &vm_physmem[psi];
257 1.38.28.2 ad
258 1.38.28.2 ad if (ps->free_list != fl)
259 1.38.28.2 ad continue;
260 1.38.28.2 ad
261 1.38.28.2 ad num -= uvm_pglistalloc_c_ps(ps, num, low, high,
262 1.38.28.2 ad alignment, boundary, rlist);
263 1.38.28.2 ad if (num == 0) {
264 1.38.28.2 ad #ifdef PGALLOC_VERBOSE
265 1.38.28.2 ad printf("pgalloc: %lx-%lx\n",
266 1.38.28.2 ad VM_PAGE_TO_PHYS(TAILQ_FIRST(rlist)),
267 1.38.28.2 ad VM_PAGE_TO_PHYS(TAILQ_LAST(rlist)));
268 1.38.28.2 ad #endif
269 1.38.28.2 ad error = 0;
270 1.38.28.2 ad goto out;
271 1.38.28.2 ad }
272 1.38.28.2 ad }
273 1.38.28.2 ad }
274 1.38.28.2 ad
275 1.38.28.2 ad out:
276 1.38.28.2 ad /*
277 1.38.28.2 ad * check to see if we need to generate some free pages waking
278 1.38.28.2 ad * the pagedaemon.
279 1.38.28.2 ad */
280 1.38.28.2 ad
281 1.38.28.2 ad uvm_kick_pdaemon();
282 1.38.28.2 ad mutex_spin_exit(&uvm_fpageqlock);
283 1.38.28.2 ad return (error);
284 1.38.28.2 ad }
285 1.38.28.2 ad
286 1.38.28.2 ad static int
287 1.38.28.2 ad uvm_pglistalloc_s_ps(struct vm_physseg *ps, int num, paddr_t low, paddr_t high,
288 1.38.28.2 ad struct pglist *rlist)
289 1.38.28.2 ad {
290 1.38.28.2 ad int todo, limit, try;
291 1.38.28.2 ad struct vm_page *pg;
292 1.38.28.2 ad #ifdef DEBUG
293 1.38.28.2 ad int cidx = 0; /* XXX: GCC */
294 1.38.28.2 ad #endif
295 1.38.28.2 ad #ifdef PGALLOC_VERBOSE
296 1.38.28.2 ad printf("pgalloc: simple %d pgs from psi %ld\n", num,
297 1.38.28.2 ad (long)(ps - vm_physmem));
298 1.38.28.2 ad #endif
299 1.38.28.2 ad
300 1.38.28.2 ad todo = num;
301 1.38.28.2 ad limit = min(atop(high), ps->avail_end);
302 1.38.28.2 ad
303 1.38.28.2 ad for (try = max(atop(low), ps->avail_start);
304 1.38.28.2 ad try < limit; try ++) {
305 1.38.28.2 ad #ifdef DEBUG
306 1.38.28.2 ad if (vm_physseg_find(try, &cidx) != ps - vm_physmem)
307 1.38.28.2 ad panic("pgalloc simple: botch1");
308 1.38.28.2 ad if (cidx != (try - ps->start))
309 1.38.28.2 ad panic("pgalloc simple: botch2");
310 1.38.28.2 ad #endif
311 1.38.28.2 ad pg = &ps->pgs[try - ps->start];
312 1.38.28.2 ad if (VM_PAGE_IS_FREE(pg) == 0)
313 1.38.28.2 ad continue;
314 1.38.28.2 ad
315 1.38.28.2 ad uvm_pglist_add(pg, rlist);
316 1.38.28.2 ad if (--todo == 0)
317 1.38.28.2 ad break;
318 1.38.28.2 ad }
319 1.38.28.2 ad
320 1.38.28.2 ad #ifdef PGALLOC_VERBOSE
321 1.38.28.2 ad printf("got %d pgs\n", num - todo);
322 1.38.28.2 ad #endif
323 1.38.28.2 ad return (num - todo); /* number of pages allocated */
324 1.38.28.2 ad }
325 1.38.28.2 ad
326 1.38.28.2 ad static int
327 1.38.28.2 ad uvm_pglistalloc_simple(int num, paddr_t low, paddr_t high,
328 1.38.28.2 ad struct pglist *rlist, int waitok)
329 1.38.28.2 ad {
330 1.38.28.2 ad int fl, psi, error;
331 1.38.28.2 ad struct vm_physseg *ps;
332 1.38.28.2 ad
333 1.38.28.2 ad /* Default to "lose". */
334 1.38.28.2 ad error = ENOMEM;
335 1.38.28.2 ad
336 1.38.28.2 ad again:
337 1.38.28.2 ad /*
338 1.38.28.2 ad * Block all memory allocation and lock the free list.
339 1.38.28.2 ad */
340 1.38.28.2 ad mutex_spin_enter(&uvm_fpageqlock);
341 1.38.28.2 ad
342 1.38.28.2 ad /* Are there even any free pages? */
343 1.38.28.2 ad if (uvmexp.free <= (uvmexp.reserve_pagedaemon + uvmexp.reserve_kernel))
344 1.38.28.2 ad goto out;
345 1.38.28.2 ad
346 1.38.28.2 ad for (fl = 0; fl < VM_NFREELIST; fl++) {
347 1.38.28.2 ad #if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST)
348 1.38.28.2 ad for (psi = vm_nphysseg - 1 ; psi >= 0 ; psi--)
349 1.38.28.2 ad #else
350 1.38.28.2 ad for (psi = 0 ; psi < vm_nphysseg ; psi++)
351 1.38.28.2 ad #endif
352 1.38.28.2 ad {
353 1.38.28.2 ad ps = &vm_physmem[psi];
354 1.38.28.2 ad
355 1.38.28.2 ad if (ps->free_list != fl)
356 1.38.28.2 ad continue;
357 1.38.28.2 ad
358 1.38.28.2 ad num -= uvm_pglistalloc_s_ps(ps, num, low, high, rlist);
359 1.38.28.2 ad if (num == 0) {
360 1.38.28.2 ad error = 0;
361 1.38.28.2 ad goto out;
362 1.38.28.2 ad }
363 1.38.28.2 ad }
364 1.38.28.2 ad
365 1.38.28.2 ad }
366 1.38.28.2 ad
367 1.38.28.2 ad out:
368 1.38.28.2 ad /*
369 1.38.28.2 ad * check to see if we need to generate some free pages waking
370 1.38.28.2 ad * the pagedaemon.
371 1.38.28.2 ad */
372 1.38.28.2 ad
373 1.38.28.2 ad uvm_kick_pdaemon();
374 1.38.28.2 ad mutex_spin_exit(&uvm_fpageqlock);
375 1.38.28.2 ad
376 1.38.28.2 ad if (error) {
377 1.38.28.2 ad if (waitok) {
378 1.38.28.2 ad /* XXX perhaps some time limitation? */
379 1.38.28.2 ad #ifdef DEBUG
380 1.38.28.2 ad printf("pglistalloc waiting\n");
381 1.38.28.2 ad #endif
382 1.38.28.2 ad uvm_wait("pglalloc");
383 1.38.28.2 ad goto again;
384 1.38.28.2 ad } else
385 1.38.28.2 ad uvm_pglistfree(rlist);
386 1.38.28.2 ad }
387 1.38.28.2 ad #ifdef PGALLOC_VERBOSE
388 1.38.28.2 ad if (!error)
389 1.38.28.2 ad printf("pgalloc: %lx..%lx\n",
390 1.38.28.2 ad VM_PAGE_TO_PHYS(TAILQ_FIRST(rlist)),
391 1.38.28.2 ad VM_PAGE_TO_PHYS(TAILQ_LAST(rlist, pglist)));
392 1.38.28.2 ad #endif
393 1.38.28.2 ad return (error);
394 1.38.28.2 ad }
395 1.38.28.2 ad
396 1.38.28.2 ad int
397 1.38.28.2 ad uvm_pglistalloc(psize_t size, paddr_t low, paddr_t high, paddr_t alignment,
398 1.38.28.2 ad paddr_t boundary, struct pglist *rlist, int nsegs, int waitok)
399 1.38.28.2 ad {
400 1.38.28.2 ad int num, res;
401 1.38.28.2 ad
402 1.38.28.2 ad KASSERT((alignment & (alignment - 1)) == 0);
403 1.38.28.2 ad KASSERT((boundary & (boundary - 1)) == 0);
404 1.38.28.2 ad
405 1.38.28.2 ad /*
406 1.38.28.2 ad * Our allocations are always page granularity, so our alignment
407 1.38.28.2 ad * must be, too.
408 1.38.28.2 ad */
409 1.38.28.2 ad if (alignment < PAGE_SIZE)
410 1.38.28.2 ad alignment = PAGE_SIZE;
411 1.38.28.2 ad if (boundary != 0 && boundary < size)
412 1.38.28.2 ad return (EINVAL);
413 1.38.28.2 ad num = atop(round_page(size));
414 1.38.28.2 ad low = roundup(low, alignment);
415 1.38.28.2 ad
416 1.38.28.2 ad TAILQ_INIT(rlist);
417 1.38.28.2 ad
418 1.38.28.2 ad if ((nsegs < size >> PAGE_SHIFT) || (alignment != PAGE_SIZE) ||
419 1.38.28.2 ad (boundary != 0))
420 1.38.28.2 ad res = uvm_pglistalloc_contig(num, low, high, alignment,
421 1.38.28.2 ad boundary, rlist);
422 1.38.28.2 ad else
423 1.38.28.2 ad res = uvm_pglistalloc_simple(num, low, high, rlist, waitok);
424 1.38.28.2 ad
425 1.38.28.2 ad return (res);
426 1.38.28.2 ad }
427 1.38.28.2 ad
428 1.38.28.2 ad /*
429 1.38.28.2 ad * uvm_pglistfree: free a list of pages
430 1.38.28.2 ad *
431 1.38.28.2 ad * => pages should already be unmapped
432 1.38.28.2 ad */
433 1.38.28.2 ad
434 1.38.28.2 ad void
435 1.38.28.2 ad uvm_pglistfree(struct pglist *list)
436 1.38.28.2 ad {
437 1.38.28.2 ad struct vm_page *pg;
438 1.38.28.2 ad
439 1.38.28.2 ad /*
440 1.38.28.2 ad * Lock the free list and free each page.
441 1.38.28.2 ad */
442 1.38.28.2 ad
443 1.38.28.2 ad mutex_spin_enter(&uvm_fpageqlock);
444 1.38.28.2 ad while ((pg = TAILQ_FIRST(list)) != NULL) {
445 1.38.28.2 ad bool iszero;
446 1.38.28.2 ad
447 1.38.28.2 ad KASSERT(!uvmpdpol_pageisqueued_p(pg));
448 1.38.28.2 ad TAILQ_REMOVE(list, pg, pageq);
449 1.38.28.2 ad iszero = (pg->flags & PG_ZERO);
450 1.38.28.2 ad pg->pqflags = PQ_FREE;
451 1.38.28.2 ad #ifdef DEBUG
452 1.38.28.2 ad pg->uobject = (void *)0xdeadbeef;
453 1.38.28.2 ad pg->offset = 0xdeadbeef;
454 1.38.28.2 ad pg->uanon = (void *)0xdeadbeef;
455 1.38.28.2 ad #endif /* DEBUG */
456 1.38.28.2 ad #ifdef DEBUG
457 1.38.28.2 ad if (iszero)
458 1.38.28.2 ad uvm_pagezerocheck(pg);
459 1.38.28.2 ad #endif /* DEBUG */
460 1.38.28.2 ad TAILQ_INSERT_HEAD(&uvm.page_free[uvm_page_lookup_freelist(pg)].
461 1.38.28.2 ad pgfl_buckets[VM_PGCOLOR_BUCKET(pg)].
462 1.38.28.2 ad pgfl_queues[iszero ? PGFL_ZEROS : PGFL_UNKNOWN], pg, pageq);
463 1.38.28.2 ad uvmexp.free++;
464 1.38.28.2 ad if (iszero)
465 1.38.28.2 ad uvmexp.zeropages++;
466 1.38.28.2 ad if (uvmexp.zeropages < UVM_PAGEZERO_TARGET)
467 1.38.28.2 ad uvm.page_idle_zero = vm_page_zero_enable;
468 1.38.28.2 ad STAT_DECR(uvm_pglistalloc_npages);
469 1.38.28.2 ad }
470 1.38.28.2 ad mutex_spin_exit(&uvm_fpageqlock);
471 1.38.28.2 ad }
472