subr_extent.c revision 1.31 1 /* $NetBSD: subr_extent.c,v 1.31 2000/06/06 17:32:50 thorpej 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, 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 * For N allocated regions, we must make (N + 1)
609 * checks for unallocated space. The first chunk we
610 * check is the area from the beginning of the subregion
611 * to the first allocated region after that point.
612 */
613 newstart = EXTENT_ALIGN(substart, alignment, skew);
614 if (newstart < ex->ex_start) {
615 #ifdef DIAGNOSTIC
616 printf(
617 "extent_alloc_subregion: extent `%s' (0x%lx - 0x%lx), alignment 0x%lx\n",
618 ex->ex_name, ex->ex_start, ex->ex_end, alignment);
619 simple_unlock(&ex->ex_slock);
620 panic("extent_alloc_subregion: overflow after alignment");
621 #else
622 extent_free_region_descriptor(ex, myrp);
623 simple_unlock(&ex->ex_slock);
624 return (EINVAL);
625 #endif
626 }
627
628 /*
629 * Find the first allocated region that begins on or after
630 * the subregion start, advancing the "last" pointer along
631 * the way.
632 */
633 for (rp = ex->ex_regions.lh_first; rp != NULL;
634 rp = rp->er_link.le_next) {
635 if (rp->er_start >= newstart)
636 break;
637 last = rp;
638 }
639
640 /*
641 * Relocate the start of our candidate region to the end of
642 * the last allocated region (if there was one overlapping
643 * our subrange).
644 */
645 if (last != NULL && last->er_end >= newstart)
646 newstart = EXTENT_ALIGN((last->er_end + 1), alignment, skew);
647
648 for (; rp != NULL; rp = rp->er_link.le_next) {
649 /*
650 * Check the chunk before "rp". Note that our
651 * comparison is safe from overflow conditions.
652 */
653 if (LE_OV(newstart, size, rp->er_start)) {
654 /*
655 * Do a boundary check, if necessary. Note
656 * that a region may *begin* on the boundary,
657 * but it must end before the boundary.
658 */
659 if (boundary) {
660 newend = newstart + (size - 1);
661
662 /*
663 * Calculate the next boundary after the start
664 * of this region.
665 */
666 dontcross = EXTENT_ALIGN(newstart+1, boundary,
667 (flags & EX_BOUNDZERO) ? 0 : ex->ex_start)
668 - 1;
669
670 #if 0
671 printf("newstart=%x newend=%x ex_start=%x ex_end=%x boundary=%x dontcross=%x\n",
672 newstart, newend, ex->ex_start, ex->ex_end,
673 boundary, dontcross);
674 #endif
675
676 if (newend > dontcross) {
677 /*
678 * Candidate region crosses boundary.
679 * Throw away the leading part and see
680 * if we still fit.
681 */
682 newstart = dontcross + 1;
683 newend = newstart + (size - 1);
684 dontcross += boundary;
685 if (!LE_OV(newstart, size, rp->er_start))
686 continue;
687 }
688
689 /*
690 * If we run past the end of
691 * the extent or the boundary
692 * overflows, then the request
693 * can't fit.
694 */
695 if (dontcross > ex->ex_end ||
696 dontcross < newstart)
697 goto fail;
698 }
699
700 /*
701 * We would fit into this space. Calculate
702 * the overhead (wasted space). If we exactly
703 * fit, or we're taking the first fit, insert
704 * ourselves into the region list.
705 */
706 ovh = rp->er_start - newstart - size;
707 if ((flags & EX_FAST) || (ovh == 0))
708 goto found;
709
710 /*
711 * Don't exactly fit, but check to see
712 * if we're better than any current choice.
713 */
714 if ((bestovh == 0) || (ovh < bestovh)) {
715 bestovh = ovh;
716 beststart = newstart;
717 bestlast = last;
718 }
719 }
720
721 /*
722 * Skip past the current region and check again.
723 */
724 newstart = EXTENT_ALIGN((rp->er_end + 1), alignment, skew);
725 if (newstart < rp->er_end) {
726 /*
727 * Overflow condition. Don't error out, since
728 * we might have a chunk of space that we can
729 * use.
730 */
731 goto fail;
732 }
733
734 last = rp;
735 }
736
737 /*
738 * The final check is from the current starting point to the
739 * end of the subregion. If there were no allocated regions,
740 * "newstart" is set to the beginning of the subregion, or
741 * just past the end of the last allocated region, adjusted
742 * for alignment in either case.
743 */
744 if (LE_OV(newstart, (size - 1), subend)) {
745 /*
746 * Do a boundary check, if necessary. Note
747 * that a region may *begin* on the boundary,
748 * but it must end before the boundary.
749 */
750 if (boundary) {
751 newend = newstart + (size - 1);
752
753 /*
754 * Calculate the next boundary after the start
755 * of this region.
756 */
757 dontcross = EXTENT_ALIGN(newstart+1, boundary,
758 (flags & EX_BOUNDZERO) ? 0 : ex->ex_start)
759 - 1;
760
761 #if 0
762 printf("newstart=%x newend=%x ex_start=%x ex_end=%x boundary=%x dontcross=%x\n",
763 newstart, newend, ex->ex_start, ex->ex_end,
764 boundary, dontcross);
765 #endif
766
767 if (newend > dontcross) {
768 /*
769 * Candidate region crosses boundary.
770 * Throw away the leading part and see
771 * if we still fit.
772 */
773 newstart = dontcross + 1;
774 newend = newstart + (size - 1);
775 dontcross += boundary;
776 if (!LE_OV(newstart, (size - 1), subend))
777 goto fail;
778 }
779
780 /*
781 * If we run past the end of
782 * the extent or the boundary
783 * overflows, then the request
784 * can't fit.
785 */
786 if (dontcross > ex->ex_end ||
787 dontcross < newstart)
788 goto fail;
789 }
790
791 /*
792 * We would fit into this space. Calculate
793 * the overhead (wasted space). If we exactly
794 * fit, or we're taking the first fit, insert
795 * ourselves into the region list.
796 */
797 ovh = ex->ex_end - newstart - (size - 1);
798 if ((flags & EX_FAST) || (ovh == 0))
799 goto found;
800
801 /*
802 * Don't exactly fit, but check to see
803 * if we're better than any current choice.
804 */
805 if ((bestovh == 0) || (ovh < bestovh)) {
806 bestovh = ovh;
807 beststart = newstart;
808 bestlast = last;
809 }
810 }
811
812 fail:
813 /*
814 * One of the following two conditions have
815 * occurred:
816 *
817 * There is no chunk large enough to hold the request.
818 *
819 * If EX_FAST was not specified, there is not an
820 * exact match for the request.
821 *
822 * Note that if we reach this point and EX_FAST is
823 * set, then we know there is no space in the extent for
824 * the request.
825 */
826 if (((flags & EX_FAST) == 0) && (bestovh != 0)) {
827 /*
828 * We have a match that's "good enough".
829 */
830 newstart = beststart;
831 last = bestlast;
832 goto found;
833 }
834
835 /*
836 * No space currently available. Wait for it to free up,
837 * if possible.
838 */
839 if (flags & EX_WAITSPACE) {
840 ex->ex_flags |= EXF_WANTED;
841 simple_unlock(&ex->ex_slock);
842 error = tsleep(ex,
843 PRIBIO | ((flags & EX_CATCH) ? PCATCH : 0), "extnt", 0);
844 if (error)
845 return (error);
846 goto alloc_start;
847 }
848
849 extent_free_region_descriptor(ex, myrp);
850 simple_unlock(&ex->ex_slock);
851 return (EAGAIN);
852
853 found:
854 /*
855 * Insert ourselves into the region list.
856 */
857 extent_insert_and_optimize(ex, newstart, size, flags, last, myrp);
858 simple_unlock(&ex->ex_slock);
859 *result = newstart;
860 return (0);
861 }
862
863 int
864 extent_free(ex, start, size, flags)
865 struct extent *ex;
866 u_long start, size;
867 int flags;
868 {
869 struct extent_region *rp, *nrp = NULL;
870 u_long end = start + (size - 1);
871 int exflags;
872
873 #ifdef DIAGNOSTIC
874 /*
875 * Check arguments.
876 *
877 * We don't lock to check these, because these values
878 * are never modified, and if another thread deletes the
879 * extent, we're screwed anyway.
880 */
881 if (ex == NULL)
882 panic("extent_free: NULL extent");
883 if ((start < ex->ex_start) || (start > ex->ex_end)) {
884 extent_print(ex);
885 printf("extent_free: extent `%s', start 0x%lx, size 0x%lx\n",
886 ex->ex_name, start, size);
887 panic("extent_free: extent `%s', region not within extent",
888 ex->ex_name);
889 }
890 /* Check for an overflow. */
891 if (end < start) {
892 extent_print(ex);
893 printf("extent_free: extent `%s', start 0x%lx, size 0x%lx\n",
894 ex->ex_name, start, size);
895 panic("extent_free: overflow");
896 }
897 #endif
898
899 /*
900 * If we're allowing coalescing, we must allocate a region
901 * descriptor now, since it might block.
902 *
903 * XXX Make a static, create-time flags word, so we don't
904 * XXX have to lock to read it!
905 */
906 simple_lock(&ex->ex_slock);
907 exflags = ex->ex_flags;
908 simple_unlock(&ex->ex_slock);
909
910 if ((exflags & EXF_NOCOALESCE) == 0) {
911 /* Allocate a region descriptor. */
912 nrp = extent_alloc_region_descriptor(ex, flags);
913 if (nrp == NULL)
914 return (ENOMEM);
915 }
916
917 simple_lock(&ex->ex_slock);
918
919 /*
920 * Find region and deallocate. Several possibilities:
921 *
922 * 1. (start == er_start) && (end == er_end):
923 * Free descriptor.
924 *
925 * 2. (start == er_start) && (end < er_end):
926 * Adjust er_start.
927 *
928 * 3. (start > er_start) && (end == er_end):
929 * Adjust er_end.
930 *
931 * 4. (start > er_start) && (end < er_end):
932 * Fragment region. Requires descriptor alloc.
933 *
934 * Cases 2, 3, and 4 require that the EXF_NOCOALESCE flag
935 * is not set.
936 */
937 for (rp = ex->ex_regions.lh_first; rp != NULL;
938 rp = rp->er_link.le_next) {
939 /*
940 * Save ourselves some comparisons; does the current
941 * region end before chunk to be freed begins? If so,
942 * then we haven't found the appropriate region descriptor.
943 */
944 if (rp->er_end < start)
945 continue;
946
947 /*
948 * Save ourselves some traversal; does the current
949 * region begin after the chunk to be freed ends? If so,
950 * then we've already passed any possible region descriptors
951 * that might have contained the chunk to be freed.
952 */
953 if (rp->er_start > end)
954 break;
955
956 /* Case 1. */
957 if ((start == rp->er_start) && (end == rp->er_end)) {
958 LIST_REMOVE(rp, er_link);
959 extent_free_region_descriptor(ex, rp);
960 goto done;
961 }
962
963 /*
964 * The following cases all require that EXF_NOCOALESCE
965 * is not set.
966 */
967 if (ex->ex_flags & EXF_NOCOALESCE)
968 continue;
969
970 /* Case 2. */
971 if ((start == rp->er_start) && (end < rp->er_end)) {
972 rp->er_start = (end + 1);
973 goto done;
974 }
975
976 /* Case 3. */
977 if ((start > rp->er_start) && (end == rp->er_end)) {
978 rp->er_end = (start - 1);
979 goto done;
980 }
981
982 /* Case 4. */
983 if ((start > rp->er_start) && (end < rp->er_end)) {
984 /* Fill in new descriptor. */
985 nrp->er_start = end + 1;
986 nrp->er_end = rp->er_end;
987
988 /* Adjust current descriptor. */
989 rp->er_end = start - 1;
990
991 /* Insert new descriptor after current. */
992 LIST_INSERT_AFTER(rp, nrp, er_link);
993
994 /* We used the new descriptor, so don't free it below */
995 nrp = NULL;
996 goto done;
997 }
998 }
999
1000 /* Region not found, or request otherwise invalid. */
1001 simple_unlock(&ex->ex_slock);
1002 extent_print(ex);
1003 printf("extent_free: start 0x%lx, end 0x%lx\n", start, end);
1004 panic("extent_free: region not found");
1005
1006 done:
1007 if (nrp != NULL)
1008 extent_free_region_descriptor(ex, nrp);
1009 if (ex->ex_flags & EXF_WANTED) {
1010 ex->ex_flags &= ~EXF_WANTED;
1011 wakeup(ex);
1012 }
1013 simple_unlock(&ex->ex_slock);
1014 return (0);
1015 }
1016
1017 /*
1018 * Allocate an extent region descriptor. EXTENT MUST NOT BE LOCKED,
1019 * AS THIS FUNCTION MAY BLOCK! We will handle any locking we may need.
1020 */
1021 static struct extent_region *
1022 extent_alloc_region_descriptor(ex, flags)
1023 struct extent *ex;
1024 int flags;
1025 {
1026 struct extent_region *rp;
1027 int exflags;
1028 int s;
1029
1030 /*
1031 * If the kernel memory allocator is not yet running, we can't
1032 * use it (obviously).
1033 */
1034 if (KMEM_IS_RUNNING == 0)
1035 flags &= ~EX_MALLOCOK;
1036
1037 /*
1038 * XXX Make a static, create-time flags word, so we don't
1039 * XXX have to lock to read it!
1040 */
1041 simple_lock(&ex->ex_slock);
1042 exflags = ex->ex_flags;
1043 simple_unlock(&ex->ex_slock);
1044
1045 if (exflags & EXF_FIXED) {
1046 struct extent_fixed *fex = (struct extent_fixed *)ex;
1047
1048 for (;;) {
1049 simple_lock(&ex->ex_slock);
1050 if ((rp = fex->fex_freelist.lh_first) != NULL) {
1051 /*
1052 * Don't muck with flags after pulling it off
1053 * the freelist; it may have been dynamically
1054 * allocated, and kindly given to us. We
1055 * need to remember that information.
1056 */
1057 LIST_REMOVE(rp, er_link);
1058 simple_unlock(&ex->ex_slock);
1059 return (rp);
1060 }
1061 if (flags & EX_MALLOCOK) {
1062 simple_unlock(&ex->ex_slock);
1063 goto alloc;
1064 }
1065 if ((flags & EX_WAITOK) == 0) {
1066 simple_unlock(&ex->ex_slock);
1067 return (NULL);
1068 }
1069 ex->ex_flags |= EXF_FLWANTED;
1070 simple_unlock(&ex->ex_slock);
1071 if (tsleep(&fex->fex_freelist,
1072 PRIBIO | ((flags & EX_CATCH) ? PCATCH : 0),
1073 "extnt", 0))
1074 return (NULL);
1075 }
1076 }
1077
1078 alloc:
1079 s = splhigh();
1080 if (expool == NULL && !expool_create()) {
1081 splx(s);
1082 return (NULL);
1083 }
1084
1085 rp = pool_get(expool, (flags & EX_WAITOK) ? PR_WAITOK : 0);
1086 splx(s);
1087
1088 if (rp != NULL)
1089 rp->er_flags = ER_ALLOC;
1090
1091 return (rp);
1092 }
1093
1094 /*
1095 * Free an extent region descriptor. EXTENT _MUST_ BE LOCKED! This
1096 * is safe as we do not block here.
1097 */
1098 static void
1099 extent_free_region_descriptor(ex, rp)
1100 struct extent *ex;
1101 struct extent_region *rp;
1102 {
1103 int s;
1104
1105 if (ex->ex_flags & EXF_FIXED) {
1106 struct extent_fixed *fex = (struct extent_fixed *)ex;
1107
1108 /*
1109 * If someone's waiting for a region descriptor,
1110 * be nice and give them this one, rather than
1111 * just free'ing it back to the system.
1112 */
1113 if (rp->er_flags & ER_ALLOC) {
1114 if (ex->ex_flags & EXF_FLWANTED) {
1115 /* Clear all but ER_ALLOC flag. */
1116 rp->er_flags = ER_ALLOC;
1117 LIST_INSERT_HEAD(&fex->fex_freelist, rp,
1118 er_link);
1119 goto wake_em_up;
1120 } else {
1121 s = splhigh();
1122 pool_put(expool, rp);
1123 splx(s);
1124 }
1125 } else {
1126 /* Clear all flags. */
1127 rp->er_flags = 0;
1128 LIST_INSERT_HEAD(&fex->fex_freelist, rp, er_link);
1129 }
1130
1131 if (ex->ex_flags & EXF_FLWANTED) {
1132 wake_em_up:
1133 ex->ex_flags &= ~EXF_FLWANTED;
1134 wakeup(&fex->fex_freelist);
1135 }
1136 return;
1137 }
1138
1139 /*
1140 * We know it's dynamically allocated if we get here.
1141 */
1142 s = splhigh();
1143 pool_put(expool, rp);
1144 splx(s);
1145 }
1146
1147 void
1148 extent_print(ex)
1149 struct extent *ex;
1150 {
1151 struct extent_region *rp;
1152
1153 if (ex == NULL)
1154 panic("extent_print: NULL extent");
1155
1156 simple_lock(&ex->ex_slock);
1157
1158 printf("extent `%s' (0x%lx - 0x%lx), flags = 0x%x\n", ex->ex_name,
1159 ex->ex_start, ex->ex_end, ex->ex_flags);
1160
1161 for (rp = ex->ex_regions.lh_first; rp != NULL;
1162 rp = rp->er_link.le_next)
1163 printf(" 0x%lx - 0x%lx\n", rp->er_start, rp->er_end);
1164
1165 simple_unlock(&ex->ex_slock);
1166 }
1167