xref: /onnv-gate/usr/src/uts/common/os/bitset.c (revision 3693:0500530f987d)
13434Sesaxe /*
23434Sesaxe  * CDDL HEADER START
33434Sesaxe  *
43434Sesaxe  * The contents of this file are subject to the terms of the
53434Sesaxe  * Common Development and Distribution License (the "License").
63434Sesaxe  * You may not use this file except in compliance with the License.
73434Sesaxe  *
83434Sesaxe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93434Sesaxe  * or http://www.opensolaris.org/os/licensing.
103434Sesaxe  * See the License for the specific language governing permissions
113434Sesaxe  * and limitations under the License.
123434Sesaxe  *
133434Sesaxe  * When distributing Covered Code, include this CDDL HEADER in each
143434Sesaxe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153434Sesaxe  * If applicable, add the following below this CDDL HEADER, with the
163434Sesaxe  * fields enclosed by brackets "[]" replaced with your own identifying
173434Sesaxe  * information: Portions Copyright [yyyy] [name of copyright owner]
183434Sesaxe  *
193434Sesaxe  * CDDL HEADER END
203434Sesaxe  */
213434Sesaxe /*
223434Sesaxe  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
233434Sesaxe  * Use is subject to license terms.
243434Sesaxe  */
253434Sesaxe 
263434Sesaxe #pragma ident	"%Z%%M%	%I%	%E% SMI"
273434Sesaxe 
283434Sesaxe #include <sys/bitset.h>
293434Sesaxe #include <sys/kmem.h>
303434Sesaxe #include <sys/systm.h>
313434Sesaxe #include <sys/cmn_err.h>
323434Sesaxe #include <sys/sysmacros.h>
333434Sesaxe 
343434Sesaxe /*
353434Sesaxe  * Initialize a bitset_t.
363434Sesaxe  * After bitset_init(), the bitset will be zero sized.
373434Sesaxe  */
383434Sesaxe void
393434Sesaxe bitset_init(bitset_t *b)
403434Sesaxe {
413434Sesaxe 	bzero(b, sizeof (bitset_t));
423434Sesaxe }
433434Sesaxe 
443434Sesaxe /*
453434Sesaxe  * Uninitialize a bitset_t.
463434Sesaxe  * This will free the bitset's data, leaving it zero sized.
473434Sesaxe  */
483434Sesaxe void
493434Sesaxe bitset_fini(bitset_t *b)
503434Sesaxe {
513434Sesaxe 	if (b->bs_words > 0)
523434Sesaxe 		kmem_free(b->bs_set, b->bs_words * sizeof (ulong_t));
533434Sesaxe }
543434Sesaxe 
553434Sesaxe /*
563434Sesaxe  * Resize a bitset to where it can hold sz number of bits.
573434Sesaxe  * This can either grow or shrink the bitset holding capacity.
583434Sesaxe  * In the case of shrinkage, elements that reside outside the new
593434Sesaxe  * holding capacity of the bitset are lost.
603434Sesaxe  */
613434Sesaxe void
623434Sesaxe bitset_resize(bitset_t *b, uint_t sz)
633434Sesaxe {
643434Sesaxe 	uint_t	nwords;
653434Sesaxe 	ulong_t	*bset_new, *bset_tmp;
663434Sesaxe 
673434Sesaxe 	nwords = BT_BITOUL(sz);
683434Sesaxe 	if (b->bs_words == nwords)
693434Sesaxe 		return;	/* already properly sized */
703434Sesaxe 
713434Sesaxe 	/*
723434Sesaxe 	 * Allocate the new ulong_t array, and copy the old one.
733434Sesaxe 	 */
743434Sesaxe 	if (nwords > 0) {
753434Sesaxe 		bset_new = kmem_zalloc(nwords * sizeof (ulong_t), KM_SLEEP);
763434Sesaxe 		bcopy(b->bs_set, bset_new,
773434Sesaxe 		    MIN(b->bs_words, nwords) * sizeof (ulong_t));
783434Sesaxe 	} else {
793434Sesaxe 		bset_new = NULL;
803434Sesaxe 	}
813434Sesaxe 
823434Sesaxe 	/* swap out the old ulong_t array for new one */
833434Sesaxe 	bset_tmp = b->bs_set;
843434Sesaxe 	b->bs_set = bset_new;
853434Sesaxe 
863434Sesaxe 	/* free up the old array */
873434Sesaxe 	kmem_free(bset_tmp, b->bs_words * sizeof (ulong_t));
883434Sesaxe 	b->bs_words = nwords;
893434Sesaxe }
903434Sesaxe 
913434Sesaxe /*
923434Sesaxe  * Returns the current holding capacity of the bitset
933434Sesaxe  */
943434Sesaxe uint_t
953434Sesaxe bitset_capacity(bitset_t *b)
963434Sesaxe {
973434Sesaxe 	return (b->bs_words * BT_NBIPUL);
983434Sesaxe }
993434Sesaxe 
1003434Sesaxe /*
1013434Sesaxe  * Add and delete bits in the bitset.
1023434Sesaxe  *
1033434Sesaxe  * Adding a bit that is already set, and clearing a bit that's already clear
1043434Sesaxe  * is legal.
1053434Sesaxe  *
1063434Sesaxe  * Adding or deleting an element that falls outside the bitset's current
1073434Sesaxe  * holding capacity is illegal.
1083434Sesaxe  */
1093434Sesaxe void
1103434Sesaxe bitset_add(bitset_t *b, uint_t elt)
1113434Sesaxe {
1123434Sesaxe 	ASSERT(b->bs_words * BT_NBIPUL > elt);
1133434Sesaxe 
1143434Sesaxe 	BT_SET(b->bs_set, elt);
1153434Sesaxe }
1163434Sesaxe 
1173434Sesaxe void
1183434Sesaxe bitset_del(bitset_t *b, uint_t elt)
1193434Sesaxe {
1203434Sesaxe 	ASSERT(b->bs_words * BT_NBIPUL > elt);
1213434Sesaxe 
1223434Sesaxe 	BT_CLEAR(b->bs_set, elt);
1233434Sesaxe }
1243434Sesaxe 
1253434Sesaxe /*
1263434Sesaxe  * Return non-zero if the bit is present in the set
1273434Sesaxe  */
1283434Sesaxe int
1293434Sesaxe bitset_in_set(bitset_t *b, uint_t elt)
1303434Sesaxe {
131*3693Sesaxe 	if (elt >= b->bs_words * BT_NBIPUL)
132*3693Sesaxe 		return (0);
1333434Sesaxe 
1343434Sesaxe 	return (BT_TEST(b->bs_set, elt));
1353434Sesaxe }
1363434Sesaxe 
1373434Sesaxe /*
1383434Sesaxe  * Return non-zero if the bitset is empty
1393434Sesaxe  */
1403434Sesaxe int
1413434Sesaxe bitset_is_null(bitset_t *b)
1423434Sesaxe {
1433434Sesaxe 	int	i;
1443434Sesaxe 
1453434Sesaxe 	for (i = 0; i < b->bs_words; i++)
1463434Sesaxe 		if (b->bs_set[i] != 0)
1473434Sesaxe 			return (0);
1483434Sesaxe 	return (1);
1493434Sesaxe }
1503434Sesaxe 
1513434Sesaxe /*
1523434Sesaxe  * Find the first set bit in the bitset
1533434Sesaxe  * Return -1 if no bit was found
1543434Sesaxe  */
1553434Sesaxe uint_t
1563434Sesaxe bitset_find(bitset_t *b)
1573434Sesaxe {
1583434Sesaxe 	uint_t	i;
1593434Sesaxe 	uint_t	elt = (uint_t)-1;
1603434Sesaxe 
1613434Sesaxe 	for (i = 0; i < b->bs_words; i++) {
1623434Sesaxe 		elt = (uint_t)(lowbit(b->bs_set[i]) - 1);
1633434Sesaxe 		if (elt != (uint_t)-1) {
1643434Sesaxe 			elt += i * BT_NBIPUL;
1653434Sesaxe 			break;
1663434Sesaxe 		}
1673434Sesaxe 	}
1683434Sesaxe 	return (elt);
1693434Sesaxe }
170