xref: /onnv-gate/usr/src/uts/common/os/bitset.c (revision 3434:5142e1d7d0bc)
1*3434Sesaxe /*
2*3434Sesaxe  * CDDL HEADER START
3*3434Sesaxe  *
4*3434Sesaxe  * The contents of this file are subject to the terms of the
5*3434Sesaxe  * Common Development and Distribution License (the "License").
6*3434Sesaxe  * You may not use this file except in compliance with the License.
7*3434Sesaxe  *
8*3434Sesaxe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3434Sesaxe  * or http://www.opensolaris.org/os/licensing.
10*3434Sesaxe  * See the License for the specific language governing permissions
11*3434Sesaxe  * and limitations under the License.
12*3434Sesaxe  *
13*3434Sesaxe  * When distributing Covered Code, include this CDDL HEADER in each
14*3434Sesaxe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3434Sesaxe  * If applicable, add the following below this CDDL HEADER, with the
16*3434Sesaxe  * fields enclosed by brackets "[]" replaced with your own identifying
17*3434Sesaxe  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3434Sesaxe  *
19*3434Sesaxe  * CDDL HEADER END
20*3434Sesaxe  */
21*3434Sesaxe /*
22*3434Sesaxe  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*3434Sesaxe  * Use is subject to license terms.
24*3434Sesaxe  */
25*3434Sesaxe 
26*3434Sesaxe #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*3434Sesaxe 
28*3434Sesaxe #include <sys/bitset.h>
29*3434Sesaxe #include <sys/kmem.h>
30*3434Sesaxe #include <sys/systm.h>
31*3434Sesaxe #include <sys/cmn_err.h>
32*3434Sesaxe #include <sys/sysmacros.h>
33*3434Sesaxe 
34*3434Sesaxe /*
35*3434Sesaxe  * Initialize a bitset_t.
36*3434Sesaxe  * After bitset_init(), the bitset will be zero sized.
37*3434Sesaxe  */
38*3434Sesaxe void
39*3434Sesaxe bitset_init(bitset_t *b)
40*3434Sesaxe {
41*3434Sesaxe 	bzero(b, sizeof (bitset_t));
42*3434Sesaxe }
43*3434Sesaxe 
44*3434Sesaxe /*
45*3434Sesaxe  * Uninitialize a bitset_t.
46*3434Sesaxe  * This will free the bitset's data, leaving it zero sized.
47*3434Sesaxe  */
48*3434Sesaxe void
49*3434Sesaxe bitset_fini(bitset_t *b)
50*3434Sesaxe {
51*3434Sesaxe 	if (b->bs_words > 0)
52*3434Sesaxe 		kmem_free(b->bs_set, b->bs_words * sizeof (ulong_t));
53*3434Sesaxe }
54*3434Sesaxe 
55*3434Sesaxe /*
56*3434Sesaxe  * Resize a bitset to where it can hold sz number of bits.
57*3434Sesaxe  * This can either grow or shrink the bitset holding capacity.
58*3434Sesaxe  * In the case of shrinkage, elements that reside outside the new
59*3434Sesaxe  * holding capacity of the bitset are lost.
60*3434Sesaxe  */
61*3434Sesaxe void
62*3434Sesaxe bitset_resize(bitset_t *b, uint_t sz)
63*3434Sesaxe {
64*3434Sesaxe 	uint_t	nwords;
65*3434Sesaxe 	ulong_t	*bset_new, *bset_tmp;
66*3434Sesaxe 
67*3434Sesaxe 	nwords = BT_BITOUL(sz);
68*3434Sesaxe 	if (b->bs_words == nwords)
69*3434Sesaxe 		return;	/* already properly sized */
70*3434Sesaxe 
71*3434Sesaxe 	/*
72*3434Sesaxe 	 * Allocate the new ulong_t array, and copy the old one.
73*3434Sesaxe 	 */
74*3434Sesaxe 	if (nwords > 0) {
75*3434Sesaxe 		bset_new = kmem_zalloc(nwords * sizeof (ulong_t), KM_SLEEP);
76*3434Sesaxe 		bcopy(b->bs_set, bset_new,
77*3434Sesaxe 		    MIN(b->bs_words, nwords) * sizeof (ulong_t));
78*3434Sesaxe 	} else {
79*3434Sesaxe 		bset_new = NULL;
80*3434Sesaxe 	}
81*3434Sesaxe 
82*3434Sesaxe 	/* swap out the old ulong_t array for new one */
83*3434Sesaxe 	bset_tmp = b->bs_set;
84*3434Sesaxe 	b->bs_set = bset_new;
85*3434Sesaxe 
86*3434Sesaxe 	/* free up the old array */
87*3434Sesaxe 	kmem_free(bset_tmp, b->bs_words * sizeof (ulong_t));
88*3434Sesaxe 	b->bs_words = nwords;
89*3434Sesaxe }
90*3434Sesaxe 
91*3434Sesaxe /*
92*3434Sesaxe  * Returns the current holding capacity of the bitset
93*3434Sesaxe  */
94*3434Sesaxe uint_t
95*3434Sesaxe bitset_capacity(bitset_t *b)
96*3434Sesaxe {
97*3434Sesaxe 	return (b->bs_words * BT_NBIPUL);
98*3434Sesaxe }
99*3434Sesaxe 
100*3434Sesaxe /*
101*3434Sesaxe  * Add and delete bits in the bitset.
102*3434Sesaxe  *
103*3434Sesaxe  * Adding a bit that is already set, and clearing a bit that's already clear
104*3434Sesaxe  * is legal.
105*3434Sesaxe  *
106*3434Sesaxe  * Adding or deleting an element that falls outside the bitset's current
107*3434Sesaxe  * holding capacity is illegal.
108*3434Sesaxe  */
109*3434Sesaxe void
110*3434Sesaxe bitset_add(bitset_t *b, uint_t elt)
111*3434Sesaxe {
112*3434Sesaxe 	ASSERT(b->bs_words * BT_NBIPUL > elt);
113*3434Sesaxe 
114*3434Sesaxe 	BT_SET(b->bs_set, elt);
115*3434Sesaxe }
116*3434Sesaxe 
117*3434Sesaxe void
118*3434Sesaxe bitset_del(bitset_t *b, uint_t elt)
119*3434Sesaxe {
120*3434Sesaxe 	ASSERT(b->bs_words * BT_NBIPUL > elt);
121*3434Sesaxe 
122*3434Sesaxe 	BT_CLEAR(b->bs_set, elt);
123*3434Sesaxe }
124*3434Sesaxe 
125*3434Sesaxe /*
126*3434Sesaxe  * Return non-zero if the bit is present in the set
127*3434Sesaxe  */
128*3434Sesaxe int
129*3434Sesaxe bitset_in_set(bitset_t *b, uint_t elt)
130*3434Sesaxe {
131*3434Sesaxe 	ASSERT(b->bs_words * BT_NBIPUL > elt);
132*3434Sesaxe 
133*3434Sesaxe 	return (BT_TEST(b->bs_set, elt));
134*3434Sesaxe }
135*3434Sesaxe 
136*3434Sesaxe /*
137*3434Sesaxe  * Return non-zero if the bitset is empty
138*3434Sesaxe  */
139*3434Sesaxe int
140*3434Sesaxe bitset_is_null(bitset_t *b)
141*3434Sesaxe {
142*3434Sesaxe 	int	i;
143*3434Sesaxe 
144*3434Sesaxe 	for (i = 0; i < b->bs_words; i++)
145*3434Sesaxe 		if (b->bs_set[i] != 0)
146*3434Sesaxe 			return (0);
147*3434Sesaxe 	return (1);
148*3434Sesaxe }
149*3434Sesaxe 
150*3434Sesaxe /*
151*3434Sesaxe  * Find the first set bit in the bitset
152*3434Sesaxe  * Return -1 if no bit was found
153*3434Sesaxe  */
154*3434Sesaxe uint_t
155*3434Sesaxe bitset_find(bitset_t *b)
156*3434Sesaxe {
157*3434Sesaxe 	uint_t	i;
158*3434Sesaxe 	uint_t	elt = (uint_t)-1;
159*3434Sesaxe 
160*3434Sesaxe 	for (i = 0; i < b->bs_words; i++) {
161*3434Sesaxe 		elt = (uint_t)(lowbit(b->bs_set[i]) - 1);
162*3434Sesaxe 		if (elt != (uint_t)-1) {
163*3434Sesaxe 			elt += i * BT_NBIPUL;
164*3434Sesaxe 			break;
165*3434Sesaxe 		}
166*3434Sesaxe 	}
167*3434Sesaxe 	return (elt);
168*3434Sesaxe }
169