1848b8605Smrg/************************************************************************** 2b8e80941Smrg * 3848b8605Smrg * Copyright 2009 VMware, Inc. 4848b8605Smrg * All Rights Reserved. 5b8e80941Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the 8848b8605Smrg * "Software"), to deal in the Software without restriction, including 9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 12848b8605Smrg * the following conditions: 13b8e80941Smrg * 14848b8605Smrg * The above copyright notice and this permission notice (including the 15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 16848b8605Smrg * of the Software. 17b8e80941Smrg * 18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25b8e80941Smrg * 26848b8605Smrg **************************************************************************/ 27848b8605Smrg 28848b8605Smrg/** 29848b8605Smrg * @file 30848b8605Smrg * Generic bitmask implementation. 31b8e80941Smrg * 32848b8605Smrg * @author Jose Fonseca <jfonseca@vmware.com> 33848b8605Smrg */ 34848b8605Smrg 35848b8605Smrg 36848b8605Smrg#include "pipe/p_compiler.h" 37848b8605Smrg#include "util/u_debug.h" 38848b8605Smrg 39848b8605Smrg#include "util/u_memory.h" 40848b8605Smrg#include "util/u_bitmask.h" 41848b8605Smrg 42848b8605Smrg 43b8e80941Smrgtypedef uint32_t util_bitmask_word; 44848b8605Smrg 45848b8605Smrg 46848b8605Smrg#define UTIL_BITMASK_INITIAL_WORDS 16 47848b8605Smrg#define UTIL_BITMASK_BITS_PER_BYTE 8 48848b8605Smrg#define UTIL_BITMASK_BITS_PER_WORD (sizeof(util_bitmask_word) * UTIL_BITMASK_BITS_PER_BYTE) 49848b8605Smrg 50848b8605Smrg 51848b8605Smrgstruct util_bitmask 52848b8605Smrg{ 53848b8605Smrg util_bitmask_word *words; 54b8e80941Smrg 55848b8605Smrg /** Number of bits we can currently hold */ 56848b8605Smrg unsigned size; 57b8e80941Smrg 58848b8605Smrg /** Number of consecutive bits set at the start of the bitmask */ 59848b8605Smrg unsigned filled; 60848b8605Smrg}; 61848b8605Smrg 62848b8605Smrg 63848b8605Smrgstruct util_bitmask * 64848b8605Smrgutil_bitmask_create(void) 65848b8605Smrg{ 66848b8605Smrg struct util_bitmask *bm; 67b8e80941Smrg 68848b8605Smrg bm = MALLOC_STRUCT(util_bitmask); 69b8e80941Smrg if (!bm) 70848b8605Smrg return NULL; 71b8e80941Smrg 72b8e80941Smrg bm->words = (util_bitmask_word *) 73b8e80941Smrg CALLOC(UTIL_BITMASK_INITIAL_WORDS, sizeof(util_bitmask_word)); 74b8e80941Smrg if (!bm->words) { 75848b8605Smrg FREE(bm); 76848b8605Smrg return NULL; 77848b8605Smrg } 78b8e80941Smrg 79848b8605Smrg bm->size = UTIL_BITMASK_INITIAL_WORDS * UTIL_BITMASK_BITS_PER_WORD; 80848b8605Smrg bm->filled = 0; 81b8e80941Smrg 82848b8605Smrg return bm; 83848b8605Smrg} 84848b8605Smrg 85848b8605Smrg 86848b8605Smrg/** 87b8e80941Smrg * Resize the bitmask if necessary 88848b8605Smrg */ 89b8e80941Smrgstatic inline boolean 90848b8605Smrgutil_bitmask_resize(struct util_bitmask *bm, 91848b8605Smrg unsigned minimum_index) 92848b8605Smrg{ 93b8e80941Smrg const unsigned minimum_size = minimum_index + 1; 94848b8605Smrg unsigned new_size; 95848b8605Smrg util_bitmask_word *new_words; 96848b8605Smrg 97848b8605Smrg /* Check integer overflow */ 98b8e80941Smrg if (!minimum_size) 99848b8605Smrg return FALSE; 100b8e80941Smrg 101b8e80941Smrg if (bm->size >= minimum_size) 102848b8605Smrg return TRUE; 103848b8605Smrg 104848b8605Smrg assert(bm->size % UTIL_BITMASK_BITS_PER_WORD == 0); 105848b8605Smrg new_size = bm->size; 106b8e80941Smrg while (new_size < minimum_size) { 107848b8605Smrg new_size *= 2; 108848b8605Smrg /* Check integer overflow */ 109b8e80941Smrg if (new_size < bm->size) 110848b8605Smrg return FALSE; 111848b8605Smrg } 112848b8605Smrg assert(new_size); 113848b8605Smrg assert(new_size % UTIL_BITMASK_BITS_PER_WORD == 0); 114b8e80941Smrg 115b8e80941Smrg new_words = (util_bitmask_word *) 116b8e80941Smrg REALLOC((void *)bm->words, 117b8e80941Smrg bm->size / UTIL_BITMASK_BITS_PER_BYTE, 118b8e80941Smrg new_size / UTIL_BITMASK_BITS_PER_BYTE); 119b8e80941Smrg if (!new_words) 120848b8605Smrg return FALSE; 121b8e80941Smrg 122b8e80941Smrg memset(new_words + bm->size/UTIL_BITMASK_BITS_PER_WORD, 123b8e80941Smrg 0, 124848b8605Smrg (new_size - bm->size)/UTIL_BITMASK_BITS_PER_BYTE); 125b8e80941Smrg 126848b8605Smrg bm->size = new_size; 127848b8605Smrg bm->words = new_words; 128b8e80941Smrg 129848b8605Smrg return TRUE; 130848b8605Smrg} 131848b8605Smrg 132848b8605Smrg 133848b8605Smrg/** 134b8e80941Smrg * Check if we can increment the filled counter. 135848b8605Smrg */ 136b8e80941Smrgstatic inline void 137848b8605Smrgutil_bitmask_filled_set(struct util_bitmask *bm, 138848b8605Smrg unsigned index) 139848b8605Smrg{ 140848b8605Smrg assert(bm->filled <= bm->size); 141848b8605Smrg assert(index < bm->size); 142b8e80941Smrg 143b8e80941Smrg if (index == bm->filled) { 144848b8605Smrg ++bm->filled; 145848b8605Smrg assert(bm->filled <= bm->size); 146848b8605Smrg } 147848b8605Smrg} 148848b8605Smrg 149b8e80941Smrg 150b8e80941Smrg/** 151b8e80941Smrg * Check if we need to decrement the filled counter. 152b8e80941Smrg */ 153b8e80941Smrgstatic inline void 154848b8605Smrgutil_bitmask_filled_unset(struct util_bitmask *bm, 155848b8605Smrg unsigned index) 156848b8605Smrg{ 157848b8605Smrg assert(bm->filled <= bm->size); 158848b8605Smrg assert(index < bm->size); 159b8e80941Smrg 160b8e80941Smrg if (index < bm->filled) 161848b8605Smrg bm->filled = index; 162848b8605Smrg} 163848b8605Smrg 164848b8605Smrg 165848b8605Smrgunsigned 166848b8605Smrgutil_bitmask_add(struct util_bitmask *bm) 167848b8605Smrg{ 168848b8605Smrg unsigned word; 169848b8605Smrg unsigned bit; 170848b8605Smrg util_bitmask_word mask; 171b8e80941Smrg 172848b8605Smrg assert(bm); 173848b8605Smrg 174b8e80941Smrg /* linear search for an empty index, starting at filled position */ 175848b8605Smrg word = bm->filled / UTIL_BITMASK_BITS_PER_WORD; 176848b8605Smrg bit = bm->filled % UTIL_BITMASK_BITS_PER_WORD; 177848b8605Smrg mask = 1 << bit; 178b8e80941Smrg while (word < bm->size / UTIL_BITMASK_BITS_PER_WORD) { 179b8e80941Smrg while (bit < UTIL_BITMASK_BITS_PER_WORD) { 180b8e80941Smrg if (!(bm->words[word] & mask)) 181848b8605Smrg goto found; 182848b8605Smrg ++bm->filled; 183848b8605Smrg ++bit; 184848b8605Smrg mask <<= 1; 185848b8605Smrg } 186848b8605Smrg ++word; 187848b8605Smrg bit = 0; 188848b8605Smrg mask = 1; 189848b8605Smrg } 190848b8605Smrgfound: 191848b8605Smrg 192848b8605Smrg /* grow the bitmask if necessary */ 193b8e80941Smrg if (!util_bitmask_resize(bm, bm->filled)) 194848b8605Smrg return UTIL_BITMASK_INVALID_INDEX; 195848b8605Smrg 196848b8605Smrg assert(!(bm->words[word] & mask)); 197848b8605Smrg bm->words[word] |= mask; 198848b8605Smrg 199848b8605Smrg return bm->filled++; 200848b8605Smrg} 201848b8605Smrg 202848b8605Smrg 203848b8605Smrgunsigned 204b8e80941Smrgutil_bitmask_set(struct util_bitmask *bm, 205848b8605Smrg unsigned index) 206848b8605Smrg{ 207848b8605Smrg unsigned word; 208848b8605Smrg unsigned bit; 209848b8605Smrg util_bitmask_word mask; 210b8e80941Smrg 211848b8605Smrg assert(bm); 212b8e80941Smrg 213848b8605Smrg /* grow the bitmask if necessary */ 214b8e80941Smrg if (!util_bitmask_resize(bm, index)) 215848b8605Smrg return UTIL_BITMASK_INVALID_INDEX; 216848b8605Smrg 217848b8605Smrg word = index / UTIL_BITMASK_BITS_PER_WORD; 218848b8605Smrg bit = index % UTIL_BITMASK_BITS_PER_WORD; 219848b8605Smrg mask = 1 << bit; 220848b8605Smrg 221848b8605Smrg bm->words[word] |= mask; 222848b8605Smrg 223848b8605Smrg util_bitmask_filled_set(bm, index); 224b8e80941Smrg 225848b8605Smrg return index; 226848b8605Smrg} 227848b8605Smrg 228848b8605Smrg 229848b8605Smrgvoid 230b8e80941Smrgutil_bitmask_clear(struct util_bitmask *bm, 231848b8605Smrg unsigned index) 232848b8605Smrg{ 233848b8605Smrg unsigned word; 234848b8605Smrg unsigned bit; 235848b8605Smrg util_bitmask_word mask; 236b8e80941Smrg 237848b8605Smrg assert(bm); 238b8e80941Smrg 239b8e80941Smrg if (index >= bm->size) 240848b8605Smrg return; 241848b8605Smrg 242848b8605Smrg word = index / UTIL_BITMASK_BITS_PER_WORD; 243848b8605Smrg bit = index % UTIL_BITMASK_BITS_PER_WORD; 244848b8605Smrg mask = 1 << bit; 245848b8605Smrg 246848b8605Smrg bm->words[word] &= ~mask; 247b8e80941Smrg 248848b8605Smrg util_bitmask_filled_unset(bm, index); 249848b8605Smrg} 250848b8605Smrg 251848b8605Smrg 252848b8605Smrgboolean 253b8e80941Smrgutil_bitmask_get(struct util_bitmask *bm, 254848b8605Smrg unsigned index) 255848b8605Smrg{ 256b8e80941Smrg const unsigned word = index / UTIL_BITMASK_BITS_PER_WORD; 257b8e80941Smrg const unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD; 258b8e80941Smrg const util_bitmask_word mask = 1 << bit; 259b8e80941Smrg 260848b8605Smrg assert(bm); 261b8e80941Smrg 262b8e80941Smrg if (index < bm->filled) { 263848b8605Smrg assert(bm->words[word] & mask); 264848b8605Smrg return TRUE; 265848b8605Smrg } 266848b8605Smrg 267b8e80941Smrg if (index >= bm->size) 268848b8605Smrg return FALSE; 269848b8605Smrg 270b8e80941Smrg if (bm->words[word] & mask) { 271848b8605Smrg util_bitmask_filled_set(bm, index); 272848b8605Smrg return TRUE; 273848b8605Smrg } 274848b8605Smrg else 275848b8605Smrg return FALSE; 276848b8605Smrg} 277848b8605Smrg 278848b8605Smrg 279848b8605Smrgunsigned 280b8e80941Smrgutil_bitmask_get_next_index(struct util_bitmask *bm, 281848b8605Smrg unsigned index) 282848b8605Smrg{ 283848b8605Smrg unsigned word = index / UTIL_BITMASK_BITS_PER_WORD; 284848b8605Smrg unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD; 285848b8605Smrg util_bitmask_word mask = 1 << bit; 286848b8605Smrg 287b8e80941Smrg if (index < bm->filled) { 288848b8605Smrg assert(bm->words[word] & mask); 289848b8605Smrg return index; 290848b8605Smrg } 291848b8605Smrg 292b8e80941Smrg if (index >= bm->size) { 293848b8605Smrg return UTIL_BITMASK_INVALID_INDEX; 294848b8605Smrg } 295848b8605Smrg 296848b8605Smrg /* Do a linear search */ 297b8e80941Smrg while (word < bm->size / UTIL_BITMASK_BITS_PER_WORD) { 298b8e80941Smrg while (bit < UTIL_BITMASK_BITS_PER_WORD) { 299b8e80941Smrg if (bm->words[word] & mask) { 300b8e80941Smrg if (index == bm->filled) { 301848b8605Smrg ++bm->filled; 302848b8605Smrg assert(bm->filled <= bm->size); 303848b8605Smrg } 304848b8605Smrg return index; 305848b8605Smrg } 306848b8605Smrg ++index; 307848b8605Smrg ++bit; 308848b8605Smrg mask <<= 1; 309848b8605Smrg } 310848b8605Smrg ++word; 311848b8605Smrg bit = 0; 312848b8605Smrg mask = 1; 313848b8605Smrg } 314b8e80941Smrg 315848b8605Smrg return UTIL_BITMASK_INVALID_INDEX; 316848b8605Smrg} 317848b8605Smrg 318848b8605Smrg 319848b8605Smrgunsigned 320848b8605Smrgutil_bitmask_get_first_index(struct util_bitmask *bm) 321848b8605Smrg{ 322848b8605Smrg return util_bitmask_get_next_index(bm, 0); 323848b8605Smrg} 324848b8605Smrg 325848b8605Smrg 326848b8605Smrgvoid 327848b8605Smrgutil_bitmask_destroy(struct util_bitmask *bm) 328848b8605Smrg{ 329b8e80941Smrg if (bm) { 330b8e80941Smrg FREE(bm->words); 331b8e80941Smrg FREE(bm); 332b8e80941Smrg } 333848b8605Smrg} 334