/*
* Copyright 2007 The Android Open Source Project
*
* Simple bit vector.
*/
#include "Common.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#define kBitVectorGrowth 4 /* increase by 4 uint32_t when limit hit */
/*
* Allocate a bit vector with enough space to hold at least the specified
* number of bits.
*/
BitVector* wsAllocBitVector(int startBits, int isExpandable)
{
BitVector* bv;
int count;
assert(sizeof(bv->storage[0]) == 4); /* assuming 32-bit units */
assert(startBits > 0);
bv = (BitVector*) malloc(sizeof(BitVector));
count = (startBits + 31) >> 5;
bv->storageSize = count;
bv->isExpandable = isExpandable;
bv->storage = (uint32_t*) malloc(count * sizeof(uint32_t));
memset(bv->storage, 0xff, count * sizeof(uint32_t));
return bv;
}
/*
* Free a BitVector.
*/
void wsFreeBitVector(BitVector* pBits)
{
if (pBits == NULL)
return;
free(pBits->storage);
free(pBits);
}
/*
* "Allocate" the first-available bit in the bitmap.
*
* This is not synchronized. The caller is expected to hold some sort of
* lock that prevents multiple threads from executing simultaneously in
* dvmAllocBit/dvmFreeBit.
*
* The bitmap indicates which resources are free, so we use '1' to indicate
* available and '0' to indicate allocated.
*/
int wsAllocBit(BitVector* pBits)
{
int word, bit;
retry:
for (word = 0; word < pBits->storageSize; word++) {
if (pBits->storage[word] != 0) {
/*
* There are unallocated bits in this word. Return the first.
*/
bit = ffs(pBits->storage[word]) -1;
assert(bit >= 0 && bit < 32);
pBits->storage[word] &= ~(1 << bit);
return (word << 5) | bit;
}
}
/*
* Ran out of space, allocate more if we're allowed to.
*/
if (!pBits->isExpandable)
return -1;
pBits->storage = realloc(pBits->storage,
(pBits->storageSize + kBitVectorGrowth) * sizeof(uint32_t));
memset(&pBits->storage[pBits->storageSize], 0xff,
kBitVectorGrowth * sizeof(uint32_t));
pBits->storageSize += kBitVectorGrowth;
goto retry;
}
/*
* Mark the specified bit as "free".
*/
void wsFreeBit(BitVector* pBits, int num)
{
assert(num >= 0 &&
num < (int) pBits->storageSize * (int)sizeof(uint32_t) * 8);
pBits->storage[num >> 5] |= 1 << (num & 0x1f);
}