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