xref: /freebsd/sys/kern/subr_unit.c (revision 911f0260390e18cf85f3dbf2c719b593efdc1e3c)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2004 Poul-Henning Kamp
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  *
30  *
31  * Unit number allocation functions.
32  *
33  * These functions implement a mixed run-length/bitmap management of unit
34  * number spaces in a very memory efficient manner.
35  *
36  * Allocation policy is always lowest free number first.
37  *
38  * A return value of -1 signals that no more unit numbers are available.
39  *
40  * There is no cost associated with the range of unitnumbers, so unless
41  * the resource really is finite, specify INT_MAX to new_unrhdr() and
42  * forget about checking the return value.
43  *
44  * If a mutex is not provided when the unit number space is created, a
45  * default global mutex is used.  The advantage to passing a mutex in, is
46  * that the alloc_unrl() function can be called with the mutex already
47  * held (it will not be released by alloc_unrl()).
48  *
49  * The allocation function alloc_unr{l}() never sleeps (but it may block on
50  * the mutex of course).
51  *
52  * Freeing a unit number may require allocating memory, and can therefore
53  * sleep so the free_unr() function does not come in a pre-locked variant.
54  *
55  * A userland test program is included.
56  *
57  * Memory usage is a very complex function of the exact allocation
58  * pattern, but always very compact:
59  *    * For the very typical case where a single unbroken run of unit
60  *      numbers are allocated 44 bytes are used on i386.
61  *    * For a unit number space of 1000 units and the random pattern
62  *      in the usermode test program included, the worst case usage
63  *	was 252 bytes on i386 for 500 allocated and 500 free units.
64  *    * For a unit number space of 10000 units and the random pattern
65  *      in the usermode test program included, the worst case usage
66  *	was 798 bytes on i386 for 5000 allocated and 5000 free units.
67  *    * The worst case is where every other unit number is allocated and
68  *	the rest are free.  In that case 44 + N/4 bytes are used where
69  *	N is the number of the highest unit allocated.
70  */
71 
72 #include <sys/param.h>
73 #include <sys/types.h>
74 #include <sys/_unrhdr.h>
75 
76 #ifdef _KERNEL
77 
78 #include <sys/bitstring.h>
79 #include <sys/malloc.h>
80 #include <sys/kernel.h>
81 #include <sys/systm.h>
82 #include <sys/limits.h>
83 #include <sys/lock.h>
84 #include <sys/mutex.h>
85 
86 /*
87  * In theory it would be smarter to allocate the individual blocks
88  * with the zone allocator, but at this time the expectation is that
89  * there will typically not even be enough allocations to fill a single
90  * page, so we stick with malloc for now.
91  */
92 static MALLOC_DEFINE(M_UNIT, "Unitno", "Unit number allocation");
93 
94 #define Malloc(foo) malloc(foo, M_UNIT, M_WAITOK | M_ZERO)
95 #define Free(foo) free(foo, M_UNIT)
96 
97 static struct mtx unitmtx;
98 
99 MTX_SYSINIT(unit, &unitmtx, "unit# allocation", MTX_DEF);
100 
101 #else /* ...USERLAND */
102 
103 #include <bitstring.h>
104 #include <err.h>
105 #include <errno.h>
106 #include <getopt.h>
107 #include <stdbool.h>
108 #include <stdio.h>
109 #include <stdlib.h>
110 #include <string.h>
111 
112 #define KASSERT(cond, arg) \
113 	do { \
114 		if (!(cond)) { \
115 			printf arg; \
116 			abort(); \
117 		} \
118 	} while (0)
119 
120 static int no_alloc;
121 #define Malloc(foo) _Malloc(foo, __LINE__)
122 static void *
123 _Malloc(size_t foo, int line)
124 {
125 
126 	KASSERT(no_alloc == 0, ("malloc in wrong place() line %d", line));
127 	return (calloc(foo, 1));
128 }
129 #define Free(foo) free(foo)
130 
131 struct unrhdr;
132 
133 #define	UNR_NO_MTX	((void *)(uintptr_t)-1)
134 
135 struct mtx {
136 	int	state;
137 } unitmtx;
138 
139 static void
140 mtx_lock(struct mtx *mp)
141 {
142 	KASSERT(mp->state == 0, ("mutex already locked"));
143 	mp->state = 1;
144 }
145 
146 static void
147 mtx_unlock(struct mtx *mp)
148 {
149 	KASSERT(mp->state == 1, ("mutex not locked"));
150 	mp->state = 0;
151 }
152 
153 #define MA_OWNED	9
154 
155 static void
156 mtx_assert(struct mtx *mp, int flag)
157 {
158 	if (flag == MA_OWNED) {
159 		KASSERT(mp->state == 1, ("mtx_assert(MA_OWNED) not true"));
160 	}
161 }
162 
163 #define CTASSERT(foo)
164 #define WITNESS_WARN(flags, lock, fmt, ...)	(void)0
165 
166 #endif /* USERLAND */
167 
168 /*
169  * This is our basic building block.
170  *
171  * It can be used in three different ways depending on the value of the ptr
172  * element:
173  *     If ptr is NULL, it represents a run of free items.
174  *     If ptr points to the unrhdr it represents a run of allocated items.
175  *     Otherwise it points to a bitstring of allocated items.
176  *
177  * For runs the len field is the length of the run.
178  * For bitmaps the len field represents the number of allocated items.
179  *
180  * The bitmap is the same size as struct unr to optimize memory management.
181  *
182  * Two special ranges are not covered by unrs:
183  * - at the start of the allocator space, all elements in [low, low + first)
184  *   are allocated;
185  * - at the end of the allocator space, all elements in [high - last, high]
186  *   are free.
187  */
188 struct unr {
189 	TAILQ_ENTRY(unr)	list;
190 	u_int			len;
191 	void			*ptr;
192 };
193 
194 struct unrb {
195 	bitstr_t		map[sizeof(struct unr) / sizeof(bitstr_t)];
196 };
197 
198 CTASSERT((sizeof(struct unr) % sizeof(bitstr_t)) == 0);
199 
200 /* Number of bits we can store in the bitmap */
201 #define NBITS (NBBY * sizeof(((struct unrb *)NULL)->map))
202 
203 static inline bool
204 is_bitmap(struct unrhdr *uh, struct unr *up)
205 {
206 	return (up->ptr != uh && up->ptr != NULL);
207 }
208 
209 /* Is the unrb empty in at least the first len bits? */
210 static inline bool
211 ub_empty(struct unrb *ub, int len) {
212 	int first_set;
213 
214 	bit_ffs(ub->map, len, &first_set);
215 	return (first_set == -1);
216 }
217 
218 /* Is the unrb full?  That is, is the number of set elements equal to len? */
219 static inline bool
220 ub_full(struct unrb *ub, int len)
221 {
222 	int first_clear;
223 
224 	bit_ffc(ub->map, len, &first_clear);
225 	return (first_clear == -1);
226 }
227 
228 /*
229  * start: ipos = -1, upos = NULL;
230  * end:   ipos = -1, upos = uh
231  */
232 struct unrhdr_iter {
233 	struct unrhdr *uh;
234 	int ipos;
235 	int upos_first_item;
236 	void *upos;
237 };
238 
239 void *
240 create_iter_unr(struct unrhdr *uh)
241 {
242 	struct unrhdr_iter *iter;
243 
244 	iter = Malloc(sizeof(*iter));
245 	iter->ipos = -1;
246 	iter->uh = uh;
247 	iter->upos = NULL;
248 	iter->upos_first_item = -1;
249 	return (iter);
250 }
251 
252 static void
253 next_iter_unrl(struct unrhdr *uh, struct unrhdr_iter *iter)
254 {
255 	struct unr *up;
256 	struct unrb *ub;
257 	u_int y;
258 	int c;
259 
260 	if (iter->ipos == -1) {
261 		if (iter->upos == uh)
262 			return;
263 		y = uh->low - 1;
264 		if (uh->first == 0) {
265 			up = TAILQ_FIRST(&uh->head);
266 			if (up == NULL) {
267 				iter->upos = uh;
268 				return;
269 			}
270 			iter->upos = up;
271 			if (up->ptr == NULL)
272 				iter->upos = NULL;
273 			else
274 				iter->upos_first_item = uh->low;
275 		}
276 	} else {
277 		y = iter->ipos;
278 	}
279 
280 	up = iter->upos;
281 
282 	/* Special case for the compacted [low, first) run. */
283 	if (up == NULL) {
284 		if (y + 1 < uh->low + uh->first) {
285 			iter->ipos = y + 1;
286 			return;
287 		}
288 		up = iter->upos = TAILQ_FIRST(&uh->head);
289 		iter->upos_first_item = uh->low + uh->first;
290 	}
291 
292 	for (;;) {
293 		if (y + 1 < iter->upos_first_item + up->len) {
294 			if (up->ptr == uh) {
295 				iter->ipos = y + 1;
296 				return;
297 			} else if (is_bitmap(uh, up)) {
298 				ub = up->ptr;
299 				bit_ffs_at(&ub->map[0],
300 				    y + 1 - iter->upos_first_item,
301 				    up->len, &c);
302 				if (c != -1) {
303 					iter->ipos = iter->upos_first_item + c;
304 					return;
305 				}
306 			}
307 		}
308 		iter->upos_first_item += up->len;
309 		y = iter->upos_first_item - 1;
310 		up = iter->upos = TAILQ_NEXT((struct unr *)iter->upos, list);
311 		if (iter->upos == NULL) {
312 			iter->ipos = -1;
313 			iter->upos = uh;
314 			return;
315 		}
316 	}
317 }
318 
319 /*
320  * returns -1 on end, otherwise the next element
321  */
322 int
323 next_iter_unr(void *handle)
324 {
325 	struct unrhdr *uh;
326 	struct unrhdr_iter *iter;
327 
328 	iter = handle;
329 	uh = iter->uh;
330 	if (uh->mtx != NULL)
331 		mtx_lock(uh->mtx);
332 	next_iter_unrl(uh, iter);
333 	if (uh->mtx != NULL)
334 		mtx_unlock(uh->mtx);
335 	return (iter->ipos);
336 }
337 
338 void
339 free_iter_unr(void *handle)
340 {
341 	Free(handle);
342 }
343 
344 #if defined(DIAGNOSTIC) || !defined(_KERNEL)
345 /*
346  * Consistency check function.
347  *
348  * Checks the internal consistency as well as we can.
349  *
350  * Called at all boundaries of this API.
351  */
352 static void
353 check_unrhdr(struct unrhdr *uh, int line)
354 {
355 	struct unr *up;
356 	struct unrb *ub;
357 	int w;
358 	u_int y, z;
359 
360 	y = uh->first;
361 	z = 0;
362 	TAILQ_FOREACH(up, &uh->head, list) {
363 		z++;
364 		if (is_bitmap(uh, up)) {
365 			ub = up->ptr;
366 			KASSERT (up->len <= NBITS,
367 			    ("UNR inconsistency: len %u max %zd (line %d)\n",
368 			    up->len, NBITS, line));
369 			z++;
370 			w = 0;
371 			bit_count(ub->map, 0, up->len, &w);
372 			y += w;
373 		} else if (up->ptr != NULL)
374 			y += up->len;
375 	}
376 	KASSERT (y == uh->busy,
377 	    ("UNR inconsistency: items %u found %u (line %d)\n",
378 	    uh->busy, y, line));
379 	KASSERT (z == uh->alloc,
380 	    ("UNR inconsistency: chunks %u found %u (line %d)\n",
381 	    uh->alloc, z, line));
382 }
383 
384 #else
385 
386 static __inline void
387 check_unrhdr(struct unrhdr *uh __unused, int line __unused)
388 {
389 
390 }
391 
392 #endif
393 
394 /*
395  * Userland memory management.  Just use calloc and keep track of how
396  * many elements we have allocated for check_unrhdr().
397  */
398 
399 static __inline void *
400 new_unr(struct unrhdr *uh, void **p1, void **p2)
401 {
402 	void *p;
403 
404 	uh->alloc++;
405 	KASSERT(*p1 != NULL || *p2 != NULL, ("Out of cached memory"));
406 	if (*p1 != NULL) {
407 		p = *p1;
408 		*p1 = NULL;
409 		return (p);
410 	} else {
411 		p = *p2;
412 		*p2 = NULL;
413 		return (p);
414 	}
415 }
416 
417 static __inline void
418 delete_unr(struct unrhdr *uh, void *ptr)
419 {
420 	struct unr *up;
421 
422 	uh->alloc--;
423 	up = ptr;
424 	TAILQ_INSERT_TAIL(&uh->ppfree, up, list);
425 }
426 
427 void
428 clean_unrhdrl(struct unrhdr *uh)
429 {
430 	struct unr *up;
431 
432 	if (uh->mtx != NULL)
433 		mtx_assert(uh->mtx, MA_OWNED);
434 	while ((up = TAILQ_FIRST(&uh->ppfree)) != NULL) {
435 		TAILQ_REMOVE(&uh->ppfree, up, list);
436 		if (uh->mtx != NULL)
437 			mtx_unlock(uh->mtx);
438 		Free(up);
439 		if (uh->mtx != NULL)
440 			mtx_lock(uh->mtx);
441 	}
442 
443 }
444 
445 void
446 clean_unrhdr(struct unrhdr *uh)
447 {
448 
449 	if (uh->mtx != NULL)
450 		mtx_lock(uh->mtx);
451 	clean_unrhdrl(uh);
452 	if (uh->mtx != NULL)
453 		mtx_unlock(uh->mtx);
454 }
455 
456 void
457 init_unrhdr(struct unrhdr *uh, int low, int high, struct mtx *mutex)
458 {
459 
460 	KASSERT(low >= 0 && low <= high,
461 	    ("UNR: use error: new_unrhdr(%d, %d)", low, high));
462 	if (mutex == UNR_NO_MTX)
463 		uh->mtx = NULL;
464 	else if (mutex != NULL)
465 		uh->mtx = mutex;
466 	else
467 		uh->mtx = &unitmtx;
468 	TAILQ_INIT(&uh->head);
469 	TAILQ_INIT(&uh->ppfree);
470 	uh->low = low;
471 	uh->high = high;
472 	uh->first = 0;
473 	uh->last = 1 + (high - low);
474 	uh->busy = 0;
475 	uh->alloc = 0;
476 	check_unrhdr(uh, __LINE__);
477 }
478 
479 /*
480  * Allocate a new unrheader set.
481  *
482  * Highest and lowest valid values given as parameters.
483  */
484 
485 struct unrhdr *
486 new_unrhdr(int low, int high, struct mtx *mutex)
487 {
488 	struct unrhdr *uh;
489 
490 	uh = Malloc(sizeof *uh);
491 	init_unrhdr(uh, low, high, mutex);
492 	return (uh);
493 }
494 
495 void
496 delete_unrhdr(struct unrhdr *uh)
497 {
498 
499 	check_unrhdr(uh, __LINE__);
500 	KASSERT(uh->busy == 0, ("unrhdr has %u allocations", uh->busy));
501 	KASSERT(uh->alloc == 0, ("UNR memory leak in delete_unrhdr"));
502 	KASSERT(TAILQ_FIRST(&uh->ppfree) == NULL,
503 	    ("unrhdr has postponed item for free"));
504 	Free(uh);
505 }
506 
507 void
508 clear_unrhdr(struct unrhdr *uh)
509 {
510 	struct unr *up, *uq;
511 
512 	KASSERT(TAILQ_EMPTY(&uh->ppfree),
513 	    ("unrhdr has postponed item for free"));
514 	TAILQ_FOREACH_SAFE(up, &uh->head, list, uq) {
515 		if (up->ptr != uh) {
516 			Free(up->ptr);
517 		}
518 		Free(up);
519 	}
520 	uh->busy = 0;
521 	uh->alloc = 0;
522 	init_unrhdr(uh, uh->low, uh->high, uh->mtx);
523 
524 	check_unrhdr(uh, __LINE__);
525 }
526 
527 /*
528  * Look for sequence of items which can be combined into a bitmap, if
529  * multiple are present, take the one which saves most memory.
530  *
531  * Return (1) if a sequence was found to indicate that another call
532  * might be able to do more.  Return (0) if we found no suitable sequence.
533  *
534  * NB: called from alloc_unr(), no new memory allocation allowed.
535  */
536 static int
537 optimize_unr(struct unrhdr *uh)
538 {
539 	struct unr *up, *uf, *us;
540 	struct unrb *ub, *ubf;
541 	u_int a, l, ba;
542 
543 	/*
544 	 * Look for the run of items (if any) which when collapsed into
545 	 * a bitmap would save most memory.
546 	 */
547 	us = NULL;
548 	ba = 0;
549 	TAILQ_FOREACH(uf, &uh->head, list) {
550 		if (uf->len >= NBITS)
551 			continue;
552 		a = 1;
553 		if (is_bitmap(uh, uf))
554 			a++;
555 		l = uf->len;
556 		up = uf;
557 		while (1) {
558 			up = TAILQ_NEXT(up, list);
559 			if (up == NULL)
560 				break;
561 			if ((up->len + l) > NBITS)
562 				break;
563 			a++;
564 			if (is_bitmap(uh, up))
565 				a++;
566 			l += up->len;
567 		}
568 		if (a > ba) {
569 			ba = a;
570 			us = uf;
571 		}
572 	}
573 	if (ba < 3)
574 		return (0);
575 
576 	/*
577 	 * If the first element is not a bitmap, make it one.
578 	 * Trying to do so without allocating more memory complicates things
579 	 * a bit
580 	 */
581 	if (!is_bitmap(uh, us)) {
582 		uf = TAILQ_NEXT(us, list);
583 		TAILQ_REMOVE(&uh->head, us, list);
584 		a = us->len;
585 		l = us->ptr == uh ? 1 : 0;
586 		ub = (void *)us;
587 		bit_nclear(ub->map, 0, NBITS - 1);
588 		if (l)
589 			bit_nset(ub->map, 0, a);
590 		if (!is_bitmap(uh, uf)) {
591 			if (uf->ptr == NULL)
592 				bit_nclear(ub->map, a, a + uf->len - 1);
593 			else
594 				bit_nset(ub->map, a, a + uf->len - 1);
595 			uf->ptr = ub;
596 			uf->len += a;
597 			us = uf;
598 		} else {
599 			ubf = uf->ptr;
600 			for (l = 0; l < uf->len; l++, a++) {
601 				if (bit_test(ubf->map, l))
602 					bit_set(ub->map, a);
603 				else
604 					bit_clear(ub->map, a);
605 			}
606 			uf->len = a;
607 			delete_unr(uh, uf->ptr);
608 			uf->ptr = ub;
609 			us = uf;
610 		}
611 	}
612 	ub = us->ptr;
613 	while (1) {
614 		uf = TAILQ_NEXT(us, list);
615 		if (uf == NULL)
616 			return (1);
617 		if (uf->len + us->len > NBITS)
618 			return (1);
619 		if (uf->ptr == NULL) {
620 			bit_nclear(ub->map, us->len, us->len + uf->len - 1);
621 			us->len += uf->len;
622 			TAILQ_REMOVE(&uh->head, uf, list);
623 			delete_unr(uh, uf);
624 		} else if (uf->ptr == uh) {
625 			bit_nset(ub->map, us->len, us->len + uf->len - 1);
626 			us->len += uf->len;
627 			TAILQ_REMOVE(&uh->head, uf, list);
628 			delete_unr(uh, uf);
629 		} else {
630 			ubf = uf->ptr;
631 			for (l = 0; l < uf->len; l++, us->len++) {
632 				if (bit_test(ubf->map, l))
633 					bit_set(ub->map, us->len);
634 				else
635 					bit_clear(ub->map, us->len);
636 			}
637 			TAILQ_REMOVE(&uh->head, uf, list);
638 			delete_unr(uh, ubf);
639 			delete_unr(uh, uf);
640 		}
641 	}
642 }
643 
644 /*
645  * See if a given unr should be collapsed with a neighbor.
646  *
647  * NB: called from alloc_unr(), no new memory allocation allowed.
648  */
649 static void
650 collapse_unr(struct unrhdr *uh, struct unr *up)
651 {
652 	struct unr *upp;
653 	struct unrb *ub;
654 
655 	/* If bitmap is all set or clear, change it to runlength */
656 	if (is_bitmap(uh, up)) {
657 		ub = up->ptr;
658 		if (ub_full(ub, up->len)) {
659 			delete_unr(uh, up->ptr);
660 			up->ptr = uh;
661 		} else if (ub_empty(ub, up->len)) {
662 			delete_unr(uh, up->ptr);
663 			up->ptr = NULL;
664 		}
665 	}
666 
667 	/* If nothing left in runlength, delete it */
668 	if (up->len == 0) {
669 		upp = TAILQ_PREV(up, unrhd, list);
670 		if (upp == NULL)
671 			upp = TAILQ_NEXT(up, list);
672 		TAILQ_REMOVE(&uh->head, up, list);
673 		delete_unr(uh, up);
674 		up = upp;
675 	}
676 
677 	/* If we have "hot-spot" still, merge with neighbor if possible */
678 	if (up != NULL) {
679 		upp = TAILQ_PREV(up, unrhd, list);
680 		if (upp != NULL && up->ptr == upp->ptr) {
681 			up->len += upp->len;
682 			TAILQ_REMOVE(&uh->head, upp, list);
683 			delete_unr(uh, upp);
684 			}
685 		upp = TAILQ_NEXT(up, list);
686 		if (upp != NULL && up->ptr == upp->ptr) {
687 			up->len += upp->len;
688 			TAILQ_REMOVE(&uh->head, upp, list);
689 			delete_unr(uh, upp);
690 		}
691 	}
692 
693 	/* Merge into ->first if possible */
694 	upp = TAILQ_FIRST(&uh->head);
695 	if (upp != NULL && upp->ptr == uh) {
696 		uh->first += upp->len;
697 		TAILQ_REMOVE(&uh->head, upp, list);
698 		delete_unr(uh, upp);
699 		if (up == upp)
700 			up = NULL;
701 	}
702 
703 	/* Merge into ->last if possible */
704 	upp = TAILQ_LAST(&uh->head, unrhd);
705 	if (upp != NULL && upp->ptr == NULL) {
706 		uh->last += upp->len;
707 		TAILQ_REMOVE(&uh->head, upp, list);
708 		delete_unr(uh, upp);
709 		if (up == upp)
710 			up = NULL;
711 	}
712 
713 	/* Try to make bitmaps */
714 	while (optimize_unr(uh))
715 		continue;
716 }
717 
718 /*
719  * Allocate a free unr.
720  */
721 int
722 alloc_unrl(struct unrhdr *uh)
723 {
724 	struct unr *up;
725 	struct unrb *ub;
726 	u_int x;
727 	int y;
728 
729 	if (uh->mtx != NULL)
730 		mtx_assert(uh->mtx, MA_OWNED);
731 	check_unrhdr(uh, __LINE__);
732 	x = uh->low + uh->first;
733 
734 	up = TAILQ_FIRST(&uh->head);
735 
736 	/*
737 	 * If we have an ideal split, just adjust the first+last
738 	 */
739 	if (up == NULL && uh->last > 0) {
740 		uh->first++;
741 		uh->last--;
742 		uh->busy++;
743 		return (x);
744 	}
745 
746 	/*
747 	 * We can always allocate from the first list element, so if we have
748 	 * nothing on the list, we must have run out of unit numbers.
749 	 */
750 	if (up == NULL)
751 		return (-1);
752 
753 	KASSERT(up->ptr != uh, ("UNR first element is allocated"));
754 
755 	if (up->ptr == NULL) {	/* free run */
756 		uh->first++;
757 		up->len--;
758 	} else {		/* bitmap */
759 		ub = up->ptr;
760 		bit_ffc(ub->map, up->len, &y);
761 		KASSERT(y != -1, ("UNR corruption: No clear bit in bitmap."));
762 		bit_set(ub->map, y);
763 		x += y;
764 	}
765 	uh->busy++;
766 	collapse_unr(uh, up);
767 	return (x);
768 }
769 
770 int
771 alloc_unr(struct unrhdr *uh)
772 {
773 	int i;
774 
775 	if (uh->mtx != NULL)
776 		mtx_lock(uh->mtx);
777 	i = alloc_unrl(uh);
778 	clean_unrhdrl(uh);
779 	if (uh->mtx != NULL)
780 		mtx_unlock(uh->mtx);
781 	return (i);
782 }
783 
784 static int
785 alloc_unr_specificl(struct unrhdr *uh, u_int item, void **p1, void **p2)
786 {
787 	struct unr *up, *upn;
788 	struct unrb *ub;
789 	u_int i, last, tl;
790 
791 	if (uh->mtx != NULL)
792 		mtx_assert(uh->mtx, MA_OWNED);
793 
794 	if (item < uh->low + uh->first || item > uh->high)
795 		return (-1);
796 
797 	up = TAILQ_FIRST(&uh->head);
798 	/* Ideal split. */
799 	if (up == NULL && item - uh->low == uh->first) {
800 		uh->first++;
801 		uh->last--;
802 		uh->busy++;
803 		check_unrhdr(uh, __LINE__);
804 		return (item);
805 	}
806 
807 	i = item - uh->low - uh->first;
808 
809 	if (up == NULL) {
810 		up = new_unr(uh, p1, p2);
811 		up->ptr = NULL;
812 		up->len = i;
813 		TAILQ_INSERT_TAIL(&uh->head, up, list);
814 		up = new_unr(uh, p1, p2);
815 		up->ptr = uh;
816 		up->len = 1;
817 		TAILQ_INSERT_TAIL(&uh->head, up, list);
818 		uh->last = uh->high - uh->low - i;
819 		uh->busy++;
820 		check_unrhdr(uh, __LINE__);
821 		return (item);
822 	} else {
823 		/* Find the item which contains the unit we want to allocate. */
824 		TAILQ_FOREACH(up, &uh->head, list) {
825 			if (up->len > i)
826 				break;
827 			i -= up->len;
828 		}
829 	}
830 
831 	if (up == NULL) {
832 		if (i > 0) {
833 			up = new_unr(uh, p1, p2);
834 			up->ptr = NULL;
835 			up->len = i;
836 			TAILQ_INSERT_TAIL(&uh->head, up, list);
837 		}
838 		up = new_unr(uh, p1, p2);
839 		up->ptr = uh;
840 		up->len = 1;
841 		TAILQ_INSERT_TAIL(&uh->head, up, list);
842 		goto done;
843 	}
844 
845 	if (is_bitmap(uh, up)) {
846 		ub = up->ptr;
847 		if (bit_test(ub->map, i) == 0) {
848 			bit_set(ub->map, i);
849 			goto done;
850 		} else
851 			return (-1);
852 	} else if (up->ptr == uh)
853 		return (-1);
854 
855 	KASSERT(up->ptr == NULL,
856 	    ("alloc_unr_specificl: up->ptr != NULL (up=%p)", up));
857 
858 	/* Split off the tail end, if any. */
859 	tl = up->len - (1 + i);
860 	if (tl > 0) {
861 		upn = new_unr(uh, p1, p2);
862 		upn->ptr = NULL;
863 		upn->len = tl;
864 		TAILQ_INSERT_AFTER(&uh->head, up, upn, list);
865 	}
866 
867 	/* Split off head end, if any */
868 	if (i > 0) {
869 		upn = new_unr(uh, p1, p2);
870 		upn->len = i;
871 		upn->ptr = NULL;
872 		TAILQ_INSERT_BEFORE(up, upn, list);
873 	}
874 	up->len = 1;
875 	up->ptr = uh;
876 
877 done:
878 	last = uh->high - uh->low - (item - uh->low);
879 	if (uh->last > last)
880 		uh->last = last;
881 	uh->busy++;
882 	collapse_unr(uh, up);
883 	check_unrhdr(uh, __LINE__);
884 	return (item);
885 }
886 
887 int
888 alloc_unr_specific(struct unrhdr *uh, u_int item)
889 {
890 	void *p1, *p2;
891 	int i;
892 
893 	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "alloc_unr_specific");
894 
895 	p1 = Malloc(sizeof(struct unr));
896 	p2 = Malloc(sizeof(struct unr));
897 
898 	if (uh->mtx != NULL)
899 		mtx_lock(uh->mtx);
900 	i = alloc_unr_specificl(uh, item, &p1, &p2);
901 	if (uh->mtx != NULL)
902 		mtx_unlock(uh->mtx);
903 
904 	if (p1 != NULL)
905 		Free(p1);
906 	if (p2 != NULL)
907 		Free(p2);
908 
909 	return (i);
910 }
911 
912 /*
913  * Free a unr.
914  *
915  * If we can save unrs by using a bitmap, do so.
916  */
917 static void
918 free_unrl(struct unrhdr *uh, u_int item, void **p1, void **p2)
919 {
920 	struct unr *up, *upp, *upn;
921 	struct unrb *ub;
922 	u_int pl;
923 
924 	KASSERT(item >= uh->low && item <= uh->high,
925 	    ("UNR: free_unr(%u) out of range [%u...%u]",
926 	     item, uh->low, uh->high));
927 	check_unrhdr(uh, __LINE__);
928 	item -= uh->low;
929 	upp = TAILQ_FIRST(&uh->head);
930 	/*
931 	 * Freeing in the ideal split case
932 	 */
933 	if (item + 1 == uh->first && upp == NULL) {
934 		uh->last++;
935 		uh->first--;
936 		uh->busy--;
937 		check_unrhdr(uh, __LINE__);
938 		return;
939 	}
940 	/*
941  	 * Freeing in the ->first section.  Create a run starting at the
942 	 * freed item.  The code below will subdivide it.
943 	 */
944 	if (item < uh->first) {
945 		up = new_unr(uh, p1, p2);
946 		up->ptr = uh;
947 		up->len = uh->first - item;
948 		TAILQ_INSERT_HEAD(&uh->head, up, list);
949 		uh->first -= up->len;
950 	}
951 
952 	item -= uh->first;
953 
954 	/* Find the item which contains the unit we want to free */
955 	TAILQ_FOREACH(up, &uh->head, list) {
956 		if (up->len > item)
957 			break;
958 		item -= up->len;
959 	}
960 
961 	/* Handle bitmap items */
962 	if (is_bitmap(uh, up)) {
963 		ub = up->ptr;
964 
965 		KASSERT(bit_test(ub->map, item) != 0,
966 		    ("UNR: Freeing free item %d (bitmap)\n", item));
967 		bit_clear(ub->map, item);
968 		uh->busy--;
969 		collapse_unr(uh, up);
970 		return;
971 	}
972 
973 	KASSERT(up->ptr == uh, ("UNR Freeing free item %d (run))\n", item));
974 
975 	/* Just this one left, reap it */
976 	if (up->len == 1) {
977 		up->ptr = NULL;
978 		uh->busy--;
979 		collapse_unr(uh, up);
980 		return;
981 	}
982 
983 	/* Check if we can shift the item into the previous 'free' run */
984 	upp = TAILQ_PREV(up, unrhd, list);
985 	if (item == 0 && upp != NULL && upp->ptr == NULL) {
986 		upp->len++;
987 		up->len--;
988 		uh->busy--;
989 		collapse_unr(uh, up);
990 		return;
991 	}
992 
993 	/* Check if we can shift the item to the next 'free' run */
994 	upn = TAILQ_NEXT(up, list);
995 	if (item == up->len - 1 && upn != NULL && upn->ptr == NULL) {
996 		upn->len++;
997 		up->len--;
998 		uh->busy--;
999 		collapse_unr(uh, up);
1000 		return;
1001 	}
1002 
1003 	/* Split off the tail end, if any. */
1004 	pl = up->len - (1 + item);
1005 	if (pl > 0) {
1006 		upp = new_unr(uh, p1, p2);
1007 		upp->ptr = uh;
1008 		upp->len = pl;
1009 		TAILQ_INSERT_AFTER(&uh->head, up, upp, list);
1010 	}
1011 
1012 	/* Split off head end, if any */
1013 	if (item > 0) {
1014 		upp = new_unr(uh, p1, p2);
1015 		upp->len = item;
1016 		upp->ptr = uh;
1017 		TAILQ_INSERT_BEFORE(up, upp, list);
1018 	}
1019 	up->len = 1;
1020 	up->ptr = NULL;
1021 	uh->busy--;
1022 	collapse_unr(uh, up);
1023 }
1024 
1025 void
1026 free_unr(struct unrhdr *uh, u_int item)
1027 {
1028 	void *p1, *p2;
1029 
1030 	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "free_unr");
1031 	p1 = Malloc(sizeof(struct unr));
1032 	p2 = Malloc(sizeof(struct unr));
1033 	if (uh->mtx != NULL)
1034 		mtx_lock(uh->mtx);
1035 	free_unrl(uh, item, &p1, &p2);
1036 	clean_unrhdrl(uh);
1037 	if (uh->mtx != NULL)
1038 		mtx_unlock(uh->mtx);
1039 	if (p1 != NULL)
1040 		Free(p1);
1041 	if (p2 != NULL)
1042 		Free(p2);
1043 }
1044 
1045 #ifdef _KERNEL
1046 #include "opt_ddb.h"
1047 #ifdef DDB
1048 #include <ddb/ddb.h>
1049 #endif
1050 #endif
1051 
1052 #if (defined(_KERNEL) && defined(DDB)) || !defined(_KERNEL)
1053 
1054 #if !defined(_KERNEL)
1055 #define db_printf printf
1056 #endif
1057 
1058 static void
1059 print_unr(struct unrhdr *uh, struct unr *up)
1060 {
1061 	u_int x;
1062 	struct unrb *ub;
1063 
1064 	db_printf("  %p len = %5u ", up, up->len);
1065 	if (up->ptr == NULL)
1066 		db_printf("free\n");
1067 	else if (up->ptr == uh)
1068 		db_printf("alloc\n");
1069 	else {
1070 		ub = up->ptr;
1071 		db_printf("bitmap [");
1072 		for (x = 0; x < up->len; x++) {
1073 			if (bit_test(ub->map, x))
1074 				db_printf("#");
1075 			else
1076 				db_printf(" ");
1077 		}
1078 		db_printf("]\n");
1079 	}
1080 }
1081 
1082 static void
1083 print_unrhdr(struct unrhdr *uh)
1084 {
1085 	struct unr *up;
1086 	u_int x;
1087 
1088 	db_printf(
1089 	    "%p low = %u high = %u first = %u last = %u busy %u chunks = %u\n",
1090 	    uh, uh->low, uh->high, uh->first, uh->last, uh->busy, uh->alloc);
1091 	x = uh->low + uh->first;
1092 	TAILQ_FOREACH(up, &uh->head, list) {
1093 		db_printf("  from = %5u", x);
1094 		print_unr(uh, up);
1095 		if (up->ptr == NULL || up->ptr == uh)
1096 			x += up->len;
1097 		else
1098 			x += NBITS;
1099 	}
1100 }
1101 
1102 #endif
1103 
1104 #if defined(_KERNEL) && defined(DDB)
1105 DB_SHOW_COMMAND(unrhdr, unrhdr_print_unrhdr)
1106 {
1107 	if (!have_addr) {
1108 		db_printf("show unrhdr addr\n");
1109 		return;
1110 	}
1111 
1112 	print_unrhdr((struct unrhdr *)addr);
1113 }
1114 
1115 static void
1116 print_unrhdr_iter(struct unrhdr_iter *iter)
1117 {
1118 	db_printf("iter %p unrhdr %p ipos %d upos %p ufi %d\n",
1119 	    iter, iter->uh, iter->ipos, iter->upos, iter->upos_first_item);
1120 }
1121 
1122 DB_SHOW_COMMAND(unrhdr_iter, unrhdr_print_iter)
1123 {
1124 	if (!have_addr) {
1125 		db_printf("show unrhdr_iter addr\n");
1126 		return;
1127 	}
1128 
1129 	print_unrhdr_iter((struct unrhdr_iter *)addr);
1130 }
1131 #endif
1132 
1133 #ifndef _KERNEL	/* USERLAND test driver */
1134 
1135 /*
1136  * Simple stochastic test driver for the above functions.  The code resides
1137  * here so that it can access static functions and structures.
1138  */
1139 
1140 static bool verbose;
1141 #define VPRINTF(...)	{if (verbose) printf(__VA_ARGS__);}
1142 
1143 static void
1144 test_alloc_unr(struct unrhdr *uh, u_int i, char a[])
1145 {
1146 	int j;
1147 
1148 	if (a[i]) {
1149 		VPRINTF("F %u\n", i);
1150 		free_unr(uh, i);
1151 		a[i] = 0;
1152 	} else {
1153 		no_alloc = 1;
1154 		j = alloc_unr(uh);
1155 		if (j != -1) {
1156 			a[j] = 1;
1157 			VPRINTF("A %d\n", j);
1158 		}
1159 		no_alloc = 0;
1160 	}
1161 }
1162 
1163 static void
1164 test_alloc_unr_specific(struct unrhdr *uh, u_int i, char a[])
1165 {
1166 	int j;
1167 
1168 	j = alloc_unr_specific(uh, i);
1169 	if (j == -1) {
1170 		VPRINTF("F %u\n", i);
1171 		a[i] = 0;
1172 		free_unr(uh, i);
1173 	} else {
1174 		a[i] = 1;
1175 		VPRINTF("A %d\n", j);
1176 	}
1177 }
1178 
1179 #define	TBASE	7
1180 #define	XSIZE	10
1181 #define	ISIZE	1000
1182 
1183 static int
1184 test_iter_compar(const void *a, const void *b)
1185 {
1186 	return (*(const int *)a - *(const int *)b);
1187 }
1188 
1189 static void
1190 test_iter_fill(int *vals, struct unrhdr *uh, int i, int v, int *res)
1191 {
1192 	int x;
1193 
1194 	vals[i] = v;
1195 	x = alloc_unr_specific(uh, v);
1196 	if (x != v) {
1197 		VPRINTF("alloc_unr_specific failed %d %d\n", x, v);
1198 		*res = 1;
1199 	}
1200 }
1201 
1202 static void
1203 test_iter(void)
1204 {
1205 	struct unrhdr *uh;
1206 	void *ihandle;
1207 	int vals[ISIZE];
1208 	int i, j, v, x, res;
1209 
1210 	res = 0;
1211 	uh = new_unrhdr(TBASE, INT_MAX, NULL);
1212 	for (i = 0; i < XSIZE; i++) {
1213 		vals[i] = i + TBASE;
1214 		x = alloc_unr_specific(uh, i + TBASE);
1215 		if (x != i + TBASE) {
1216 			VPRINTF("alloc_unr_specific failed %d %d\n", x,
1217 			    i + TBASE);
1218 			res = 1;
1219 		}
1220 	}
1221 	for (; i < ISIZE; i++) {
1222 		for (;;) {
1223 again:
1224 			v = arc4random_uniform(INT_MAX);
1225 			if (v < TBASE)
1226 				goto again;
1227 			for (j = 0; j < i; j++) {
1228 				if (v == vals[j] || v + 1 == vals[j])
1229 					goto again;
1230 			}
1231 			break;
1232 		}
1233 		test_iter_fill(vals, uh, i, v, &res);
1234 		i++, v++;
1235 		if (i < ISIZE)
1236 			test_iter_fill(vals, uh, i, v, &res);
1237 	}
1238 	qsort(vals, ISIZE, sizeof(vals[0]), test_iter_compar);
1239 
1240 	ihandle = create_iter_unr(uh);
1241 	i = 0;
1242 	while ((v = next_iter_unr(ihandle)) != -1) {
1243 		if (vals[i] != v) {
1244 			VPRINTF("iter %d: iter %d != val %d\n", i, v, vals[i]);
1245 			if (res == 0) {
1246 				if (verbose)
1247 					print_unrhdr(uh);
1248 				res = 1;
1249 			}
1250 		} else {
1251 			VPRINTF("iter %d: val %d\n", i, v);
1252 		}
1253 		i++;
1254 	}
1255 	free_iter_unr(ihandle);
1256 	clean_unrhdr(uh);
1257 	clear_unrhdr(uh);
1258 	delete_unrhdr(uh);
1259 	exit(res);
1260 }
1261 
1262 static void
1263 usage(char **argv)
1264 {
1265 	printf("%s [-h] [-i] [-r REPETITIONS] [-v]\n", argv[0]);
1266 }
1267 
1268 int
1269 main(int argc, char **argv)
1270 {
1271 	struct unrhdr *uh;
1272 	char *a;
1273 	long count = 10000;	/* Number of unrs to test */
1274 	long reps = 1, m;
1275 	int ch;
1276 	u_int i;
1277 	bool testing_iter;
1278 
1279 	verbose = false;
1280 	testing_iter = false;
1281 
1282 	while ((ch = getopt(argc, argv, "hir:v")) != -1) {
1283 		switch (ch) {
1284 		case 'i':
1285 			testing_iter = true;
1286 			break;
1287 		case 'r':
1288 			errno = 0;
1289 			reps = strtol(optarg, NULL, 0);
1290 			if (errno == ERANGE || errno == EINVAL) {
1291 				usage(argv);
1292 				exit(2);
1293 			}
1294 
1295 			break;
1296 		case 'v':
1297 			verbose = true;
1298 			break;
1299 		case 'h':
1300 		default:
1301 			usage(argv);
1302 			exit(2);
1303 		}
1304 	}
1305 
1306 	setbuf(stdout, NULL);
1307 
1308 	if (testing_iter)
1309 		test_iter();
1310 
1311 	uh = new_unrhdr(0, count - 1, NULL);
1312 	print_unrhdr(uh);
1313 
1314 	a = calloc(count, sizeof(char));
1315 	if (a == NULL)
1316 		err(1, "calloc failed");
1317 
1318 	printf("sizeof(struct unr) %zu\n", sizeof(struct unr));
1319 	printf("sizeof(struct unrb) %zu\n", sizeof(struct unrb));
1320 	printf("sizeof(struct unrhdr) %zu\n", sizeof(struct unrhdr));
1321 	printf("NBITS %lu\n", (unsigned long)NBITS);
1322 	for (m = 0; m < count * reps; m++) {
1323 		i = arc4random_uniform(count);
1324 #if 0
1325 		if (a[i] && (j & 1))
1326 			continue;
1327 #endif
1328 		if ((arc4random() & 1) != 0)
1329 			test_alloc_unr(uh, i, a);
1330 		else
1331 			test_alloc_unr_specific(uh, i, a);
1332 
1333 		if (verbose)
1334 			print_unrhdr(uh);
1335 		check_unrhdr(uh, __LINE__);
1336 	}
1337 	for (i = 0; i < (u_int)count; i++) {
1338 		if (a[i]) {
1339 			if (verbose) {
1340 				printf("C %u\n", i);
1341 				print_unrhdr(uh);
1342 			}
1343 			free_unr(uh, i);
1344 		}
1345 	}
1346 	print_unrhdr(uh);
1347 	delete_unrhdr(uh);
1348 	free(a);
1349 	return (0);
1350 }
1351 #endif
1352