Path: blob/21.2-virgl/src/gallium/auxiliary/util/u_bitmask.c
4561 views
/**************************************************************************1*2* Copyright 2009 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627/**28* @file29* Generic bitmask implementation.30*31* @author Jose Fonseca <[email protected]>32*/333435#include "pipe/p_compiler.h"36#include "util/u_debug.h"3738#include "util/u_memory.h"39#include "util/u_bitmask.h"404142typedef uint32_t util_bitmask_word;434445#define UTIL_BITMASK_INITIAL_WORDS 1646#define UTIL_BITMASK_BITS_PER_BYTE 847#define UTIL_BITMASK_BITS_PER_WORD (sizeof(util_bitmask_word) * UTIL_BITMASK_BITS_PER_BYTE)484950struct util_bitmask51{52util_bitmask_word *words;5354/** Number of bits we can currently hold */55unsigned size;5657/** Number of consecutive bits set at the start of the bitmask */58unsigned filled;59};606162struct util_bitmask *63util_bitmask_create(void)64{65struct util_bitmask *bm;6667bm = MALLOC_STRUCT(util_bitmask);68if (!bm)69return NULL;7071bm->words = (util_bitmask_word *)72CALLOC(UTIL_BITMASK_INITIAL_WORDS, sizeof(util_bitmask_word));73if (!bm->words) {74FREE(bm);75return NULL;76}7778bm->size = UTIL_BITMASK_INITIAL_WORDS * UTIL_BITMASK_BITS_PER_WORD;79bm->filled = 0;8081return bm;82}838485/**86* Resize the bitmask if necessary87*/88static inline boolean89util_bitmask_resize(struct util_bitmask *bm,90unsigned minimum_index)91{92const unsigned minimum_size = minimum_index + 1;93unsigned new_size;94util_bitmask_word *new_words;9596/* Check integer overflow */97if (!minimum_size)98return FALSE;99100if (bm->size >= minimum_size)101return TRUE;102103assert(bm->size % UTIL_BITMASK_BITS_PER_WORD == 0);104new_size = bm->size;105while (new_size < minimum_size) {106new_size *= 2;107/* Check integer overflow */108if (new_size < bm->size)109return FALSE;110}111assert(new_size);112assert(new_size % UTIL_BITMASK_BITS_PER_WORD == 0);113114new_words = (util_bitmask_word *)115REALLOC((void *)bm->words,116bm->size / UTIL_BITMASK_BITS_PER_BYTE,117new_size / UTIL_BITMASK_BITS_PER_BYTE);118if (!new_words)119return FALSE;120121memset(new_words + bm->size/UTIL_BITMASK_BITS_PER_WORD,1220,123(new_size - bm->size)/UTIL_BITMASK_BITS_PER_BYTE);124125bm->size = new_size;126bm->words = new_words;127128return TRUE;129}130131132/**133* Check if we can increment the filled counter.134*/135static inline void136util_bitmask_filled_set(struct util_bitmask *bm,137unsigned index)138{139assert(bm->filled <= bm->size);140assert(index < bm->size);141142if (index == bm->filled) {143++bm->filled;144assert(bm->filled <= bm->size);145}146}147148149/**150* Check if we need to decrement the filled counter.151*/152static inline void153util_bitmask_filled_unset(struct util_bitmask *bm,154unsigned index)155{156assert(bm->filled <= bm->size);157assert(index < bm->size);158159if (index < bm->filled)160bm->filled = index;161}162163164unsigned165util_bitmask_add(struct util_bitmask *bm)166{167unsigned word;168unsigned bit;169util_bitmask_word mask;170171assert(bm);172173/* linear search for an empty index, starting at filled position */174word = bm->filled / UTIL_BITMASK_BITS_PER_WORD;175bit = bm->filled % UTIL_BITMASK_BITS_PER_WORD;176mask = 1 << bit;177while (word < bm->size / UTIL_BITMASK_BITS_PER_WORD) {178while (bit < UTIL_BITMASK_BITS_PER_WORD) {179if (!(bm->words[word] & mask))180goto found;181++bm->filled;182++bit;183mask <<= 1;184}185++word;186bit = 0;187mask = 1;188}189found:190191/* grow the bitmask if necessary */192if (!util_bitmask_resize(bm, bm->filled))193return UTIL_BITMASK_INVALID_INDEX;194195assert(!(bm->words[word] & mask));196bm->words[word] |= mask;197198return bm->filled++;199}200201202unsigned203util_bitmask_set(struct util_bitmask *bm,204unsigned index)205{206unsigned word;207unsigned bit;208util_bitmask_word mask;209210assert(bm);211212/* grow the bitmask if necessary */213if (!util_bitmask_resize(bm, index))214return UTIL_BITMASK_INVALID_INDEX;215216word = index / UTIL_BITMASK_BITS_PER_WORD;217bit = index % UTIL_BITMASK_BITS_PER_WORD;218mask = 1 << bit;219220bm->words[word] |= mask;221222util_bitmask_filled_set(bm, index);223224return index;225}226227228void229util_bitmask_clear(struct util_bitmask *bm,230unsigned index)231{232unsigned word;233unsigned bit;234util_bitmask_word mask;235236assert(bm);237238if (index >= bm->size)239return;240241word = index / UTIL_BITMASK_BITS_PER_WORD;242bit = index % UTIL_BITMASK_BITS_PER_WORD;243mask = 1 << bit;244245bm->words[word] &= ~mask;246247util_bitmask_filled_unset(bm, index);248}249250251boolean252util_bitmask_get(struct util_bitmask *bm,253unsigned index)254{255const unsigned word = index / UTIL_BITMASK_BITS_PER_WORD;256const unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD;257const util_bitmask_word mask = 1 << bit;258259assert(bm);260261if (index < bm->filled) {262assert(bm->words[word] & mask);263return TRUE;264}265266if (index >= bm->size)267return FALSE;268269if (bm->words[word] & mask) {270util_bitmask_filled_set(bm, index);271return TRUE;272}273else274return FALSE;275}276277278unsigned279util_bitmask_get_next_index(struct util_bitmask *bm,280unsigned index)281{282unsigned word = index / UTIL_BITMASK_BITS_PER_WORD;283unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD;284util_bitmask_word mask = 1 << bit;285286if (index < bm->filled) {287assert(bm->words[word] & mask);288return index;289}290291if (index >= bm->size) {292return UTIL_BITMASK_INVALID_INDEX;293}294295/* Do a linear search */296while (word < bm->size / UTIL_BITMASK_BITS_PER_WORD) {297while (bit < UTIL_BITMASK_BITS_PER_WORD) {298if (bm->words[word] & mask) {299if (index == bm->filled) {300++bm->filled;301assert(bm->filled <= bm->size);302}303return index;304}305++index;306++bit;307mask <<= 1;308}309++word;310bit = 0;311mask = 1;312}313314return UTIL_BITMASK_INVALID_INDEX;315}316317318unsigned319util_bitmask_get_first_index(struct util_bitmask *bm)320{321return util_bitmask_get_next_index(bm, 0);322}323324325void326util_bitmask_destroy(struct util_bitmask *bm)327{328if (bm) {329FREE(bm->words);330FREE(bm);331}332}333334335