/*1* Copyright (c) 2000, 2001, 20022* The President and Fellows of Harvard College.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12* 3. Neither the name of the University nor the names of its contributors13* may be used to endorse or promote products derived from this software14* without specific prior written permission.15*16* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*/2829/*30* Fixed-size array of bits. (Intended for storage management.)31*/3233#include <types.h>34#include <kern/errno.h>35#include <lib.h>36#include <bitmap.h>3738/*39* It would be a lot more efficient on most platforms to use uint32_t40* or unsigned long as the base type for holding bits. But we don't,41* because if one uses any data type more than a single byte wide,42* bitmap data saved on disk becomes endian-dependent, which is a43* severe nuisance.44*/45#define BITS_PER_WORD (CHAR_BIT)46#define WORD_TYPE unsigned char47#define WORD_ALLBITS (0xff)4849struct bitmap {50unsigned nbits;51WORD_TYPE *v;52};535455struct bitmap *56bitmap_create(unsigned nbits)57{58struct bitmap *b;59unsigned words;6061words = DIVROUNDUP(nbits, BITS_PER_WORD);62b = kmalloc(sizeof(struct bitmap));63if (b == NULL) {64return NULL;65}66b->v = kmalloc(words*sizeof(WORD_TYPE));67if (b->v == NULL) {68kfree(b);69return NULL;70}7172bzero(b->v, words*sizeof(WORD_TYPE));73b->nbits = nbits;7475/* Mark any leftover bits at the end in use */76if (words > nbits / BITS_PER_WORD) {77unsigned j, ix = words-1;78unsigned overbits = nbits - ix*BITS_PER_WORD;7980KASSERT(nbits / BITS_PER_WORD == words-1);81KASSERT(overbits > 0 && overbits < BITS_PER_WORD);8283for (j=overbits; j<BITS_PER_WORD; j++) {84b->v[ix] |= ((WORD_TYPE)1 << j);85}86}8788return b;89}9091void *92bitmap_getdata(struct bitmap *b)93{94return b->v;95}9697int98bitmap_alloc(struct bitmap *b, unsigned *index)99{100unsigned ix;101unsigned maxix = DIVROUNDUP(b->nbits, BITS_PER_WORD);102unsigned offset;103104for (ix=0; ix<maxix; ix++) {105if (b->v[ix]!=WORD_ALLBITS) {106for (offset = 0; offset < BITS_PER_WORD; offset++) {107WORD_TYPE mask = ((WORD_TYPE)1) << offset;108109if ((b->v[ix] & mask)==0) {110b->v[ix] |= mask;111*index = (ix*BITS_PER_WORD)+offset;112KASSERT(*index < b->nbits);113return 0;114}115}116KASSERT(0);117}118}119return ENOSPC;120}121122static123inline124void125bitmap_translate(unsigned bitno, unsigned *ix, WORD_TYPE *mask)126{127unsigned offset;128*ix = bitno / BITS_PER_WORD;129offset = bitno % BITS_PER_WORD;130*mask = ((WORD_TYPE)1) << offset;131}132133void134bitmap_mark(struct bitmap *b, unsigned index)135{136unsigned ix;137WORD_TYPE mask;138139KASSERT(index < b->nbits);140bitmap_translate(index, &ix, &mask);141142KASSERT((b->v[ix] & mask)==0);143b->v[ix] |= mask;144}145146void147bitmap_unmark(struct bitmap *b, unsigned index)148{149unsigned ix;150WORD_TYPE mask;151152KASSERT(index < b->nbits);153bitmap_translate(index, &ix, &mask);154155KASSERT((b->v[ix] & mask)!=0);156b->v[ix] &= ~mask;157}158159160int161bitmap_isset(struct bitmap *b, unsigned index)162{163unsigned ix;164WORD_TYPE mask;165166bitmap_translate(index, &ix, &mask);167return (b->v[ix] & mask);168}169170void171bitmap_destroy(struct bitmap *b)172{173kfree(b->v);174kfree(b);175}176177178