subr_extent.c revision 1.32.2.3 1 /* $NetBSD: subr_extent.c,v 1.32.2.3 2002/02/10 14:12:10 he Exp $ */
2
3 /*-
4 * Copyright (c) 1996, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe and Matthias Drochner.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * General purpose extent manager.
41 */
42
43 #ifdef _KERNEL
44 #include <sys/param.h>
45 #include <sys/extent.h>
46 #include <sys/malloc.h>
47 #include <sys/pool.h>
48 #include <sys/time.h>
49 #include <sys/systm.h>
50 #include <sys/proc.h>
51 #include <sys/lock.h>
52
53 #include <vm/vm.h>
54 #include <vm/vm_kern.h>
55
56 #define KMEM_IS_RUNNING (kmem_map != NULL)
57 #elif defined(_EXTENT_TESTING)
58 /*
59 * user-land definitions, so it can fit into a testing harness.
60 */
61 #include <sys/param.h>
62 #include <sys/pool.h>
63 #include <sys/extent.h>
64 #include <errno.h>
65 #include <stdlib.h>
66 #include <stdio.h>
67 #include <string.h>
68
69 /*
70 * Use multi-line #defines to avoid screwing up the kernel tags file;
71 * without this, ctags produces a tags file where panic() shows up
72 * in subr_extent.c rather than subr_prf.c.
73 */
74 #define \
75 malloc(s, t, flags) malloc(s)
76 #define \
77 free(p, t) free(p)
78 #define \
79 tsleep(chan, pri, str, timo) (EWOULDBLOCK)
80 #define \
81 wakeup(chan) ((void)0)
82 #define \
83 pool_get(pool, flags) malloc(pool->pr_size,0,0)
84 #define \
85 pool_put(pool, rp) free(rp,0)
86 #define \
87 panic(a) printf(a)
88 #define \
89 splhigh() (1)
90 #define \
91 splx(s) ((void)(s))
92
93 #define \
94 simple_lock_init(l) ((void)(l))
95 #define \
96 simple_lock(l) ((void)(l))
97 #define \
98 simple_unlock(l) ((void)(l))
99 #define KMEM_IS_RUNNING (1)
100 #endif
101
102 static pool_handle_t expool_create __P((void));
103 static void extent_insert_and_optimize __P((struct extent *, u_long, u_long,
104 int, struct extent_region *, struct extent_region *));
105 static struct extent_region *extent_alloc_region_descriptor
106 __P((struct extent *, int));
107 static void extent_free_region_descriptor __P((struct extent *,
108 struct extent_region *));
109
110 static pool_handle_t expool;
111
112 /*
113 * Macro to align to an arbitrary power-of-two boundary.
114 */
115 #define EXTENT_ALIGN(_start, _align, _skew) \
116 (((((_start) - (_skew)) + ((_align) - 1)) & (-(_align))) + (_skew))
117
118 /*
119 * Create the extent_region pool.
120 * (This is deferred until one of our callers thinks we can malloc()).
121 */
122
123 static pool_handle_t expool_create()
124 {
125 #if defined(_KERNEL)
126 expool = pool_create(sizeof(struct extent_region), 0, 0,
127 0, "extent", 0, 0, 0, 0);
128 #else
129 expool = (pool_handle_t)malloc(sizeof(*expool),0,0);
130 expool->pr_size = sizeof(struct extent_region);
131 #endif
132 return (expool);
133 }
134
135 /*
136 * Allocate and initialize an extent map.
137 */
138 struct extent *
139 extent_create(name, start, end, mtype, storage, storagesize, flags)
140 const char *name;
141 u_long start, end;
142 int mtype;
143 caddr_t storage;
144 size_t storagesize;
145 int flags;
146 {
147 struct extent *ex;
148 caddr_t cp = storage;
149 size_t sz = storagesize;
150 struct extent_region *rp;
151 int fixed_extent = (storage != NULL);
152 int s;
153
154 #ifdef DIAGNOSTIC
155 /* Check arguments. */
156 if (name == NULL)
157 panic("extent_create: name == NULL");
158 if (end < start) {
159 printf("extent_create: extent `%s', start 0x%lx, end 0x%lx\n",
160 name, start, end);
161 panic("extent_create: end < start");
162 }
163 if (fixed_extent && (storagesize < sizeof(struct extent_fixed)))
164 panic("extent_create: fixed extent, bad storagesize 0x%lx",
165 (u_long)storagesize);
166 if (fixed_extent == 0 && (storagesize != 0 || storage != NULL))
167 panic("extent_create: storage provided for non-fixed");
168 #endif
169
170 /* Allocate extent descriptor. */
171 if (fixed_extent) {
172 struct extent_fixed *fex;
173
174 memset(storage, 0, storagesize);
175
176 /*
177 * Align all descriptors on "long" boundaries.
178 */
179 fex = (struct extent_fixed *)cp;
180 ex = (struct extent *)fex;
181 cp += ALIGN(sizeof(struct extent_fixed));
182 sz -= ALIGN(sizeof(struct extent_fixed));
183 fex->fex_storage = storage;
184 fex->fex_storagesize = storagesize;
185
186 /*
187 * In a fixed extent, we have to pre-allocate region
188 * descriptors and place them in the extent's freelist.
189 */
190 LIST_INIT(&fex->fex_freelist);
191 while (sz >= ALIGN(sizeof(struct extent_region))) {
192 rp = (struct extent_region *)cp;
193 cp += ALIGN(sizeof(struct extent_region));
194 sz -= ALIGN(sizeof(struct extent_region));
195 LIST_INSERT_HEAD(&fex->fex_freelist, rp, er_link);
196 }
197 } else {
198 s = splhigh();
199 if (expool == NULL)
200 expool_create();
201 splx(s);
202 if (expool == NULL)
203 return (NULL);
204
205 ex = (struct extent *)malloc(sizeof(struct extent),
206 mtype, (flags & EX_WAITOK) ? M_WAITOK : M_NOWAIT);
207 if (ex == NULL)
208 return (NULL);
209 }
210
211 /* Fill in the extent descriptor and return it to the caller. */
212 simple_lock_init(&ex->ex_slock);
213 LIST_INIT(&ex->ex_regions);
214 ex->ex_name = name;
215 ex->ex_start = start;
216 ex->ex_end = end;
217 ex->ex_mtype = mtype;
218 ex->ex_flags = 0;
219 if (fixed_extent)
220 ex->ex_flags |= EXF_FIXED;
221 if (flags & EX_NOCOALESCE)
222 ex->ex_flags |= EXF_NOCOALESCE;
223 return (ex);
224 }
225
226 /*
227 * Destroy an extent map.
228 * Since we're freeing the data, there can't be any references
229 * so we don't need any locking.
230 */
231 void
232 extent_destroy(ex)
233 struct extent *ex;
234 {
235 struct extent_region *rp, *orp;
236
237 #ifdef DIAGNOSTIC
238 /* Check arguments. */
239 if (ex == NULL)
240 panic("extent_destroy: NULL extent");
241 #endif
242
243 /* Free all region descriptors in extent. */
244 for (rp = ex->ex_regions.lh_first; rp != NULL; ) {
245 orp = rp;
246 rp = rp->er_link.le_next;
247 LIST_REMOVE(orp, er_link);
248 extent_free_region_descriptor(ex, orp);
249 }
250
251 /* If we're not a fixed extent, free the extent descriptor itself. */
252 if ((ex->ex_flags & EXF_FIXED) == 0)
253 free(ex, ex->ex_mtype);
254 }
255
256 /*
257 * Insert a region descriptor into the sorted region list after the
258 * entry "after" or at the head of the list (if "after" is NULL).
259 * The region descriptor we insert is passed in "rp". We must
260 * allocate the region descriptor before calling this function!
261 * If we don't need the region descriptor, it will be freed here.
262 */
263 static void
264 extent_insert_and_optimize(ex, start, size, flags, after, rp)
265 struct extent *ex;
266 u_long start, size;
267 int flags;
268 struct extent_region *after, *rp;
269 {
270 struct extent_region *nextr;
271 int appended = 0;
272
273 if (after == NULL) {
274 /*
275 * We're the first in the region list. If there's
276 * a region after us, attempt to coalesce to save
277 * descriptor overhead.
278 */
279 if (((ex->ex_flags & EXF_NOCOALESCE) == 0) &&
280 (ex->ex_regions.lh_first != NULL) &&
281 ((start + size) == ex->ex_regions.lh_first->er_start)) {
282 /*
283 * We can coalesce. Prepend us to the first region.
284 */
285 ex->ex_regions.lh_first->er_start = start;
286 extent_free_region_descriptor(ex, rp);
287 return;
288 }
289
290 /*
291 * Can't coalesce. Fill in the region descriptor
292 * in, and insert us at the head of the region list.
293 */
294 rp->er_start = start;
295 rp->er_end = start + (size - 1);
296 LIST_INSERT_HEAD(&ex->ex_regions, rp, er_link);
297 return;
298 }
299
300 /*
301 * If EXF_NOCOALESCE is set, coalescing is disallowed.
302 */
303 if (ex->ex_flags & EXF_NOCOALESCE)
304 goto cant_coalesce;
305
306 /*
307 * Attempt to coalesce with the region before us.
308 */
309 if ((after->er_end + 1) == start) {
310 /*
311 * We can coalesce. Append ourselves and make
312 * note of it.
313 */
314 after->er_end = start + (size - 1);
315 appended = 1;
316 }
317
318 /*
319 * Attempt to coalesce with the region after us.
320 */
321 if ((after->er_link.le_next != NULL) &&
322 ((start + size) == after->er_link.le_next->er_start)) {
323 /*
324 * We can coalesce. Note that if we appended ourselves
325 * to the previous region, we exactly fit the gap, and
326 * can free the "next" region descriptor.
327 */
328 if (appended) {
329 /*
330 * Yup, we can free it up.
331 */
332 after->er_end = after->er_link.le_next->er_end;
333 nextr = after->er_link.le_next;
334 LIST_REMOVE(nextr, er_link);
335 extent_free_region_descriptor(ex, nextr);
336 } else {
337 /*
338 * Nope, just prepend us to the next region.
339 */
340 after->er_link.le_next->er_start = start;
341 }
342
343 extent_free_region_descriptor(ex, rp);
344 return;
345 }
346
347 /*
348 * We weren't able to coalesce with the next region, but
349 * we don't need to allocate a region descriptor if we
350 * appended ourselves to the previous region.
351 */
352 if (appended) {
353 extent_free_region_descriptor(ex, rp);
354 return;
355 }
356
357 cant_coalesce:
358
359 /*
360 * Fill in the region descriptor and insert ourselves
361 * into the region list.
362 */
363 rp->er_start = start;
364 rp->er_end = start + (size - 1);
365 LIST_INSERT_AFTER(after, rp, er_link);
366 }
367
368 /*
369 * Allocate a specific region in an extent map.
370 */
371 int
372 extent_alloc_region(ex, start, size, flags)
373 struct extent *ex;
374 u_long start, size;
375 int flags;
376 {
377 struct extent_region *rp, *last, *myrp;
378 u_long end = start + (size - 1);
379 int error;
380
381 #ifdef DIAGNOSTIC
382 /* Check arguments. */
383 if (ex == NULL)
384 panic("extent_alloc_region: NULL extent");
385 if (size < 1) {
386 printf("extent_alloc_region: extent `%s', size 0x%lx\n",
387 ex->ex_name, size);
388 panic("extent_alloc_region: bad size");
389 }
390 if (end < start) {
391 printf(
392 "extent_alloc_region: extent `%s', start 0x%lx, size 0x%lx\n",
393 ex->ex_name, start, size);
394 panic("extent_alloc_region: overflow");
395 }
396 #endif
397
398 /*
399 * Make sure the requested region lies within the
400 * extent.
401 *
402 * We don't lock to check the range, because those values
403 * are never modified, and if another thread deletes the
404 * extent, we're screwed anyway.
405 */
406 if ((start < ex->ex_start) || (end > ex->ex_end)) {
407 #ifdef DIAGNOSTIC
408 printf("extent_alloc_region: extent `%s' (0x%lx - 0x%lx)\n",
409 ex->ex_name, ex->ex_start, ex->ex_end);
410 printf("extent_alloc_region: start 0x%lx, end 0x%lx\n",
411 start, end);
412 panic("extent_alloc_region: region lies outside extent");
413 #else
414 return (EINVAL);
415 #endif
416 }
417
418 /*
419 * Allocate the region descriptor. It will be freed later
420 * if we can coalesce with another region. Don't lock before
421 * here! This could block.
422 */
423 myrp = extent_alloc_region_descriptor(ex, flags);
424 if (myrp == NULL) {
425 #ifdef DIAGNOSTIC
426 printf(
427 "extent_alloc_region: can't allocate region descriptor\n");
428 #endif
429 return (ENOMEM);
430 }
431
432 alloc_start:
433 simple_lock(&ex->ex_slock);
434
435 /*
436 * Attempt to place ourselves in the desired area of the
437 * extent. We save ourselves some work by keeping the list sorted.
438 * In other words, if the start of the current region is greater
439 * than the end of our region, we don't have to search any further.
440 */
441
442 /*
443 * Keep a pointer to the last region we looked at so
444 * that we don't have to traverse the list again when
445 * we insert ourselves. If "last" is NULL when we
446 * finally insert ourselves, we go at the head of the
447 * list. See extent_insert_and_optimize() for details.
448 */
449 last = NULL;
450
451 for (rp = ex->ex_regions.lh_first; rp != NULL;
452 rp = rp->er_link.le_next) {
453 if (rp->er_start > end) {
454 /*
455 * We lie before this region and don't
456 * conflict.
457 */
458 break;
459 }
460
461 /*
462 * The current region begins before we end.
463 * Check for a conflict.
464 */
465 if (rp->er_end >= start) {
466 /*
467 * We conflict. If we can (and want to) wait,
468 * do so.
469 */
470 if (flags & EX_WAITSPACE) {
471 ex->ex_flags |= EXF_WANTED;
472 simple_unlock(&ex->ex_slock);
473 error = tsleep(ex,
474 PRIBIO | ((flags & EX_CATCH) ? PCATCH : 0),
475 "extnt", 0);
476 if (error)
477 return (error);
478 goto alloc_start;
479 }
480 extent_free_region_descriptor(ex, myrp);
481 simple_unlock(&ex->ex_slock);
482 return (EAGAIN);
483 }
484 /*
485 * We don't conflict, but this region lies before
486 * us. Keep a pointer to this region, and keep
487 * trying.
488 */
489 last = rp;
490 }
491
492 /*
493 * We don't conflict with any regions. "last" points
494 * to the region we fall after, or is NULL if we belong
495 * at the beginning of the region list. Insert ourselves.
496 */
497 extent_insert_and_optimize(ex, start, size, flags, last, myrp);
498 simple_unlock(&ex->ex_slock);
499 return (0);
500 }
501
502 /*
503 * Macro to check (x + y) <= z. This check is designed to fail
504 * if an overflow occurs.
505 */
506 #define LE_OV(x, y, z) ((((x) + (y)) >= (x)) && (((x) + (y)) <= (z)))
507
508 /*
509 * Allocate a region in an extent map subregion.
510 *
511 * If EX_FAST is specified, we return the first fit in the map.
512 * Otherwise, we try to minimize fragmentation by finding the
513 * smallest gap that will hold the request.
514 *
515 * The allocated region is aligned to "alignment", which must be
516 * a power of 2.
517 */
518 int
519 extent_alloc_subregion1(ex, substart, subend, size, alignment, skew, boundary,
520 flags, result)
521 struct extent *ex;
522 u_long substart, subend, size, alignment, skew, boundary;
523 int flags;
524 u_long *result;
525 {
526 struct extent_region *rp, *myrp, *last, *bestlast;
527 u_long newstart, newend, exend, beststart, bestovh, ovh;
528 u_long dontcross;
529 int error;
530
531 #ifdef DIAGNOSTIC
532 /*
533 * Check arguments.
534 *
535 * We don't lock to check these, because these values
536 * are never modified, and if another thread deletes the
537 * extent, we're screwed anyway.
538 */
539 if (ex == NULL)
540 panic("extent_alloc_subregion: NULL extent");
541 if (result == NULL)
542 panic("extent_alloc_subregion: NULL result pointer");
543 if ((substart < ex->ex_start) || (substart > ex->ex_end) ||
544 (subend > ex->ex_end) || (subend < ex->ex_start)) {
545 printf("extent_alloc_subregion: extent `%s', ex_start 0x%lx, ex_end 0x%lx\n",
546 ex->ex_name, ex->ex_start, ex->ex_end);
547 printf("extent_alloc_subregion: substart 0x%lx, subend 0x%lx\n",
548 substart, subend);
549 panic("extent_alloc_subregion: bad subregion");
550 }
551 if ((size < 1) || ((size - 1) > (subend - substart))) {
552 printf("extent_alloc_subregion: extent `%s', size 0x%lx\n",
553 ex->ex_name, size);
554 panic("extent_alloc_subregion: bad size");
555 }
556 if (alignment == 0)
557 panic("extent_alloc_subregion: bad alignment");
558 if (boundary && (boundary < size)) {
559 printf(
560 "extent_alloc_subregion: extent `%s', size 0x%lx,
561 boundary 0x%lx\n", ex->ex_name, size, boundary);
562 panic("extent_alloc_subregion: bad boundary");
563 }
564 #endif
565
566 /*
567 * Allocate the region descriptor. It will be freed later
568 * if we can coalesce with another region. Don't lock before
569 * here! This could block.
570 */
571 myrp = extent_alloc_region_descriptor(ex, flags);
572 if (myrp == NULL) {
573 #ifdef DIAGNOSTIC
574 printf(
575 "extent_alloc_subregion: can't allocate region descriptor\n");
576 #endif
577 return (ENOMEM);
578 }
579
580 alloc_start:
581 simple_lock(&ex->ex_slock);
582
583 /*
584 * Keep a pointer to the last region we looked at so
585 * that we don't have to traverse the list again when
586 * we insert ourselves. If "last" is NULL when we
587 * finally insert ourselves, we go at the head of the
588 * list. See extent_insert_and_optimize() for deatails.
589 */
590 last = NULL;
591
592 /*
593 * Keep track of size and location of the smallest
594 * chunk we fit in.
595 *
596 * Since the extent can be as large as the numeric range
597 * of the CPU (0 - 0xffffffff for 32-bit systems), the
598 * best overhead value can be the maximum unsigned integer.
599 * Thus, we initialize "bestovh" to 0, since we insert ourselves
600 * into the region list immediately on an exact match (which
601 * is the only case where "bestovh" would be set to 0).
602 */
603 bestovh = 0;
604 beststart = 0;
605 bestlast = NULL;
606
607 /*
608 * Keep track of end of free region. This is either the end of extent
609 * or the start of a region past the subend.
610 */
611 exend = ex->ex_end;
612
613 /*
614 * For N allocated regions, we must make (N + 1)
615 * checks for unallocated space. The first chunk we
616 * check is the area from the beginning of the subregion
617 * to the first allocated region after that point.
618 */
619 newstart = EXTENT_ALIGN(substart, alignment, skew);
620 if (newstart < ex->ex_start) {
621 #ifdef DIAGNOSTIC
622 printf(
623 "extent_alloc_subregion: extent `%s' (0x%lx - 0x%lx), alignment 0x%lx\n",
624 ex->ex_name, ex->ex_start, ex->ex_end, alignment);
625 simple_unlock(&ex->ex_slock);
626 panic("extent_alloc_subregion: overflow after alignment");
627 #else
628 extent_free_region_descriptor(ex, myrp);
629 simple_unlock(&ex->ex_slock);
630 return (EINVAL);
631 #endif
632 }
633
634 /*
635 * Find the first allocated region that begins on or after
636 * the subregion start, advancing the "last" pointer along
637 * the way.
638 */
639 for (rp = ex->ex_regions.lh_first; rp != NULL;
640 rp = rp->er_link.le_next) {
641 if (rp->er_start >= newstart)
642 break;
643 last = rp;
644 }
645
646 /*
647 * Relocate the start of our candidate region to the end of
648 * the last allocated region (if there was one overlapping
649 * our subrange).
650 */
651 if (last != NULL && last->er_end >= newstart)
652 newstart = EXTENT_ALIGN((last->er_end + 1), alignment, skew);
653
654 for (; rp != NULL; rp = rp->er_link.le_next) {
655 /*
656 * If the region pasts the subend, bail out and see
657 * if we fit against the subend.
658 */
659 if (rp->er_start >= subend) {
660 exend = rp->er_start;
661 break;
662 }
663
664 /*
665 * Check the chunk before "rp". Note that our
666 * comparison is safe from overflow conditions.
667 */
668 if (LE_OV(newstart, size, rp->er_start)) {
669 /*
670 * Do a boundary check, if necessary. Note
671 * that a region may *begin* on the boundary,
672 * but it must end before the boundary.
673 */
674 if (boundary) {
675 newend = newstart + (size - 1);
676
677 /*
678 * Calculate the next boundary after the start
679 * of this region.
680 */
681 dontcross = EXTENT_ALIGN(newstart+1, boundary,
682 (flags & EX_BOUNDZERO) ? 0 : ex->ex_start)
683 - 1;
684
685 #if 0
686 printf("newstart=%lx newend=%lx ex_start=%lx ex_end=%lx boundary=%lx dontcross=%lx\n",
687 newstart, newend, ex->ex_start, ex->ex_end,
688 boundary, dontcross);
689 #endif
690
691 /* Check for overflow */
692 if (dontcross < ex->ex_start)
693 dontcross = ex->ex_end;
694 else if (newend > dontcross) {
695 /*
696 * Candidate region crosses boundary.
697 * Throw away the leading part and see
698 * if we still fit.
699 */
700 newstart = dontcross + 1;
701 newend = newstart + (size - 1);
702 dontcross += boundary;
703 if (!LE_OV(newstart, size, rp->er_start))
704 goto skip;
705 }
706
707 /*
708 * If we run past the end of
709 * the extent or the boundary
710 * overflows, then the request
711 * can't fit.
712 */
713 if (newstart + size - 1 > ex->ex_end ||
714 dontcross < newstart)
715 goto fail;
716 }
717
718 /*
719 * We would fit into this space. Calculate
720 * the overhead (wasted space). If we exactly
721 * fit, or we're taking the first fit, insert
722 * ourselves into the region list.
723 */
724 ovh = rp->er_start - newstart - size;
725 if ((flags & EX_FAST) || (ovh == 0))
726 goto found;
727
728 /*
729 * Don't exactly fit, but check to see
730 * if we're better than any current choice.
731 */
732 if ((bestovh == 0) || (ovh < bestovh)) {
733 bestovh = ovh;
734 beststart = newstart;
735 bestlast = last;
736 }
737 }
738
739 skip:
740 /*
741 * Skip past the current region and check again.
742 */
743 newstart = EXTENT_ALIGN((rp->er_end + 1), alignment, skew);
744 if (newstart < rp->er_end) {
745 /*
746 * Overflow condition. Don't error out, since
747 * we might have a chunk of space that we can
748 * use.
749 */
750 goto fail;
751 }
752
753 last = rp;
754 }
755
756 /*
757 * The final check is from the current starting point to the
758 * end of the subregion. If there were no allocated regions,
759 * "newstart" is set to the beginning of the subregion, or
760 * just past the end of the last allocated region, adjusted
761 * for alignment in either case.
762 */
763 if (LE_OV(newstart, (size - 1), subend)) {
764 /*
765 * Do a boundary check, if necessary. Note
766 * that a region may *begin* on the boundary,
767 * but it must end before the boundary.
768 */
769 if (boundary) {
770 newend = newstart + (size - 1);
771
772 /*
773 * Calculate the next boundary after the start
774 * of this region.
775 */
776 dontcross = EXTENT_ALIGN(newstart+1, boundary,
777 (flags & EX_BOUNDZERO) ? 0 : ex->ex_start)
778 - 1;
779
780 #if 0
781 printf("newstart=%lx newend=%lx ex_start=%lx ex_end=%lx boundary=%lx dontcross=%lx\n",
782 newstart, newend, ex->ex_start, ex->ex_end,
783 boundary, dontcross);
784 #endif
785
786 /* Check for overflow */
787 if (dontcross < ex->ex_start)
788 dontcross = ex->ex_end;
789 else if (newend > dontcross) {
790 /*
791 * Candidate region crosses boundary.
792 * Throw away the leading part and see
793 * if we still fit.
794 */
795 newstart = dontcross + 1;
796 newend = newstart + (size - 1);
797 dontcross += boundary;
798 if (!LE_OV(newstart, (size - 1), subend))
799 goto fail;
800 }
801
802 /*
803 * If we run past the end of
804 * the extent or the boundary
805 * overflows, then the request
806 * can't fit.
807 */
808 if (newstart + size - 1 > ex->ex_end ||
809 dontcross < newstart)
810 goto fail;
811 }
812
813 /*
814 * We would fit into this space. Calculate
815 * the overhead (wasted space). If we exactly
816 * fit, or we're taking the first fit, insert
817 * ourselves into the region list.
818 */
819 ovh = exend - newstart - (size - 1);
820 if ((flags & EX_FAST) || (ovh == 0))
821 goto found;
822
823 /*
824 * Don't exactly fit, but check to see
825 * if we're better than any current choice.
826 */
827 if ((bestovh == 0) || (ovh < bestovh)) {
828 bestovh = ovh;
829 beststart = newstart;
830 bestlast = last;
831 }
832 }
833
834 fail:
835 /*
836 * One of the following two conditions have
837 * occurred:
838 *
839 * There is no chunk large enough to hold the request.
840 *
841 * If EX_FAST was not specified, there is not an
842 * exact match for the request.
843 *
844 * Note that if we reach this point and EX_FAST is
845 * set, then we know there is no space in the extent for
846 * the request.
847 */
848 if (((flags & EX_FAST) == 0) && (bestovh != 0)) {
849 /*
850 * We have a match that's "good enough".
851 */
852 newstart = beststart;
853 last = bestlast;
854 goto found;
855 }
856
857 /*
858 * No space currently available. Wait for it to free up,
859 * if possible.
860 */
861 if (flags & EX_WAITSPACE) {
862 ex->ex_flags |= EXF_WANTED;
863 simple_unlock(&ex->ex_slock);
864 error = tsleep(ex,
865 PRIBIO | ((flags & EX_CATCH) ? PCATCH : 0), "extnt", 0);
866 if (error)
867 return (error);
868 goto alloc_start;
869 }
870
871 extent_free_region_descriptor(ex, myrp);
872 simple_unlock(&ex->ex_slock);
873 return (EAGAIN);
874
875 found:
876 /*
877 * Insert ourselves into the region list.
878 */
879 extent_insert_and_optimize(ex, newstart, size, flags, last, myrp);
880 simple_unlock(&ex->ex_slock);
881 *result = newstart;
882 return (0);
883 }
884
885 int
886 extent_free(ex, start, size, flags)
887 struct extent *ex;
888 u_long start, size;
889 int flags;
890 {
891 struct extent_region *rp, *nrp = NULL;
892 u_long end = start + (size - 1);
893 int exflags;
894
895 #ifdef DIAGNOSTIC
896 /*
897 * Check arguments.
898 *
899 * We don't lock to check these, because these values
900 * are never modified, and if another thread deletes the
901 * extent, we're screwed anyway.
902 */
903 if (ex == NULL)
904 panic("extent_free: NULL extent");
905 if ((start < ex->ex_start) || (start > ex->ex_end)) {
906 extent_print(ex);
907 printf("extent_free: extent `%s', start 0x%lx, size 0x%lx\n",
908 ex->ex_name, start, size);
909 panic("extent_free: extent `%s', region not within extent",
910 ex->ex_name);
911 }
912 /* Check for an overflow. */
913 if (end < start) {
914 extent_print(ex);
915 printf("extent_free: extent `%s', start 0x%lx, size 0x%lx\n",
916 ex->ex_name, start, size);
917 panic("extent_free: overflow");
918 }
919 #endif
920
921 /*
922 * If we're allowing coalescing, we must allocate a region
923 * descriptor now, since it might block.
924 *
925 * XXX Make a static, create-time flags word, so we don't
926 * XXX have to lock to read it!
927 */
928 simple_lock(&ex->ex_slock);
929 exflags = ex->ex_flags;
930 simple_unlock(&ex->ex_slock);
931
932 if ((exflags & EXF_NOCOALESCE) == 0) {
933 /* Allocate a region descriptor. */
934 nrp = extent_alloc_region_descriptor(ex, flags);
935 if (nrp == NULL)
936 return (ENOMEM);
937 }
938
939 simple_lock(&ex->ex_slock);
940
941 /*
942 * Find region and deallocate. Several possibilities:
943 *
944 * 1. (start == er_start) && (end == er_end):
945 * Free descriptor.
946 *
947 * 2. (start == er_start) && (end < er_end):
948 * Adjust er_start.
949 *
950 * 3. (start > er_start) && (end == er_end):
951 * Adjust er_end.
952 *
953 * 4. (start > er_start) && (end < er_end):
954 * Fragment region. Requires descriptor alloc.
955 *
956 * Cases 2, 3, and 4 require that the EXF_NOCOALESCE flag
957 * is not set.
958 */
959 for (rp = ex->ex_regions.lh_first; rp != NULL;
960 rp = rp->er_link.le_next) {
961 /*
962 * Save ourselves some comparisons; does the current
963 * region end before chunk to be freed begins? If so,
964 * then we haven't found the appropriate region descriptor.
965 */
966 if (rp->er_end < start)
967 continue;
968
969 /*
970 * Save ourselves some traversal; does the current
971 * region begin after the chunk to be freed ends? If so,
972 * then we've already passed any possible region descriptors
973 * that might have contained the chunk to be freed.
974 */
975 if (rp->er_start > end)
976 break;
977
978 /* Case 1. */
979 if ((start == rp->er_start) && (end == rp->er_end)) {
980 LIST_REMOVE(rp, er_link);
981 extent_free_region_descriptor(ex, rp);
982 goto done;
983 }
984
985 /*
986 * The following cases all require that EXF_NOCOALESCE
987 * is not set.
988 */
989 if (ex->ex_flags & EXF_NOCOALESCE)
990 continue;
991
992 /* Case 2. */
993 if ((start == rp->er_start) && (end < rp->er_end)) {
994 rp->er_start = (end + 1);
995 goto done;
996 }
997
998 /* Case 3. */
999 if ((start > rp->er_start) && (end == rp->er_end)) {
1000 rp->er_end = (start - 1);
1001 goto done;
1002 }
1003
1004 /* Case 4. */
1005 if ((start > rp->er_start) && (end < rp->er_end)) {
1006 /* Fill in new descriptor. */
1007 nrp->er_start = end + 1;
1008 nrp->er_end = rp->er_end;
1009
1010 /* Adjust current descriptor. */
1011 rp->er_end = start - 1;
1012
1013 /* Insert new descriptor after current. */
1014 LIST_INSERT_AFTER(rp, nrp, er_link);
1015
1016 /* We used the new descriptor, so don't free it below */
1017 nrp = NULL;
1018 goto done;
1019 }
1020 }
1021
1022 /* Region not found, or request otherwise invalid. */
1023 simple_unlock(&ex->ex_slock);
1024 extent_print(ex);
1025 printf("extent_free: start 0x%lx, end 0x%lx\n", start, end);
1026 panic("extent_free: region not found");
1027
1028 done:
1029 if (nrp != NULL)
1030 extent_free_region_descriptor(ex, nrp);
1031 if (ex->ex_flags & EXF_WANTED) {
1032 ex->ex_flags &= ~EXF_WANTED;
1033 wakeup(ex);
1034 }
1035 simple_unlock(&ex->ex_slock);
1036 return (0);
1037 }
1038
1039 /*
1040 * Allocate an extent region descriptor. EXTENT MUST NOT BE LOCKED,
1041 * AS THIS FUNCTION MAY BLOCK! We will handle any locking we may need.
1042 */
1043 static struct extent_region *
1044 extent_alloc_region_descriptor(ex, flags)
1045 struct extent *ex;
1046 int flags;
1047 {
1048 struct extent_region *rp;
1049 int exflags;
1050 int s;
1051
1052 /*
1053 * If the kernel memory allocator is not yet running, we can't
1054 * use it (obviously).
1055 */
1056 if (KMEM_IS_RUNNING == 0)
1057 flags &= ~EX_MALLOCOK;
1058
1059 /*
1060 * XXX Make a static, create-time flags word, so we don't
1061 * XXX have to lock to read it!
1062 */
1063 simple_lock(&ex->ex_slock);
1064 exflags = ex->ex_flags;
1065 simple_unlock(&ex->ex_slock);
1066
1067 if (exflags & EXF_FIXED) {
1068 struct extent_fixed *fex = (struct extent_fixed *)ex;
1069
1070 for (;;) {
1071 simple_lock(&ex->ex_slock);
1072 if ((rp = fex->fex_freelist.lh_first) != NULL) {
1073 /*
1074 * Don't muck with flags after pulling it off
1075 * the freelist; it may have been dynamically
1076 * allocated, and kindly given to us. We
1077 * need to remember that information.
1078 */
1079 LIST_REMOVE(rp, er_link);
1080 simple_unlock(&ex->ex_slock);
1081 return (rp);
1082 }
1083 if (flags & EX_MALLOCOK) {
1084 simple_unlock(&ex->ex_slock);
1085 goto alloc;
1086 }
1087 if ((flags & EX_WAITOK) == 0) {
1088 simple_unlock(&ex->ex_slock);
1089 return (NULL);
1090 }
1091 ex->ex_flags |= EXF_FLWANTED;
1092 simple_unlock(&ex->ex_slock);
1093 if (tsleep(&fex->fex_freelist,
1094 PRIBIO | ((flags & EX_CATCH) ? PCATCH : 0),
1095 "extnt", 0))
1096 return (NULL);
1097 }
1098 }
1099
1100 alloc:
1101 s = splhigh();
1102 if (expool == NULL && !expool_create()) {
1103 splx(s);
1104 return (NULL);
1105 }
1106
1107 rp = pool_get(expool, (flags & EX_WAITOK) ? PR_WAITOK : 0);
1108 splx(s);
1109
1110 if (rp != NULL)
1111 rp->er_flags = ER_ALLOC;
1112
1113 return (rp);
1114 }
1115
1116 /*
1117 * Free an extent region descriptor. EXTENT _MUST_ BE LOCKED! This
1118 * is safe as we do not block here.
1119 */
1120 static void
1121 extent_free_region_descriptor(ex, rp)
1122 struct extent *ex;
1123 struct extent_region *rp;
1124 {
1125 int s;
1126
1127 if (ex->ex_flags & EXF_FIXED) {
1128 struct extent_fixed *fex = (struct extent_fixed *)ex;
1129
1130 /*
1131 * If someone's waiting for a region descriptor,
1132 * be nice and give them this one, rather than
1133 * just free'ing it back to the system.
1134 */
1135 if (rp->er_flags & ER_ALLOC) {
1136 if (ex->ex_flags & EXF_FLWANTED) {
1137 /* Clear all but ER_ALLOC flag. */
1138 rp->er_flags = ER_ALLOC;
1139 LIST_INSERT_HEAD(&fex->fex_freelist, rp,
1140 er_link);
1141 goto wake_em_up;
1142 } else {
1143 s = splhigh();
1144 pool_put(expool, rp);
1145 splx(s);
1146 }
1147 } else {
1148 /* Clear all flags. */
1149 rp->er_flags = 0;
1150 LIST_INSERT_HEAD(&fex->fex_freelist, rp, er_link);
1151 }
1152
1153 if (ex->ex_flags & EXF_FLWANTED) {
1154 wake_em_up:
1155 ex->ex_flags &= ~EXF_FLWANTED;
1156 wakeup(&fex->fex_freelist);
1157 }
1158 return;
1159 }
1160
1161 /*
1162 * We know it's dynamically allocated if we get here.
1163 */
1164 s = splhigh();
1165 pool_put(expool, rp);
1166 splx(s);
1167 }
1168
1169 void
1170 extent_print(ex)
1171 struct extent *ex;
1172 {
1173 struct extent_region *rp;
1174
1175 if (ex == NULL)
1176 panic("extent_print: NULL extent");
1177
1178 simple_lock(&ex->ex_slock);
1179
1180 printf("extent `%s' (0x%lx - 0x%lx), flags = 0x%x\n", ex->ex_name,
1181 ex->ex_start, ex->ex_end, ex->ex_flags);
1182
1183 for (rp = ex->ex_regions.lh_first; rp != NULL;
1184 rp = rp->er_link.le_next)
1185 printf(" 0x%lx - 0x%lx\n", rp->er_start, rp->er_end);
1186
1187 simple_unlock(&ex->ex_slock);
1188 }
1189