os161-1.99
 All Data Structures
bitmap.c
00001 /*
00002  * Copyright (c) 2000, 2001, 2002
00003  *      The President and Fellows of Harvard College.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 /*
00031  * Fixed-size array of bits. (Intended for storage management.)
00032  */
00033 
00034 #include <types.h>
00035 #include <kern/errno.h>
00036 #include <lib.h>
00037 #include <bitmap.h>
00038 
00039 /*
00040  * It would be a lot more efficient on most platforms to use uint32_t
00041  * or unsigned long as the base type for holding bits. But we don't,
00042  * because if one uses any data type more than a single byte wide,
00043  * bitmap data saved on disk becomes endian-dependent, which is a
00044  * severe nuisance.
00045  */
00046 #define BITS_PER_WORD   (CHAR_BIT)
00047 #define WORD_TYPE       unsigned char
00048 #define WORD_ALLBITS    (0xff)
00049 
00050 struct bitmap {
00051         unsigned nbits;
00052         WORD_TYPE *v;
00053 };
00054 
00055 
00056 struct bitmap *
00057 bitmap_create(unsigned nbits)
00058 {
00059         struct bitmap *b; 
00060         unsigned words;
00061 
00062         words = DIVROUNDUP(nbits, BITS_PER_WORD);
00063         b = kmalloc(sizeof(struct bitmap));
00064         if (b == NULL) {
00065                 return NULL;
00066         }
00067         b->v = kmalloc(words*sizeof(WORD_TYPE));
00068         if (b->v == NULL) {
00069                 kfree(b);
00070                 return NULL;
00071         }
00072 
00073         bzero(b->v, words*sizeof(WORD_TYPE));
00074         b->nbits = nbits;
00075 
00076         /* Mark any leftover bits at the end in use */
00077         if (words > nbits / BITS_PER_WORD) {
00078                 unsigned j, ix = words-1;
00079                 unsigned overbits = nbits - ix*BITS_PER_WORD;
00080 
00081                 KASSERT(nbits / BITS_PER_WORD == words-1);
00082                 KASSERT(overbits > 0 && overbits < BITS_PER_WORD);
00083                 
00084                 for (j=overbits; j<BITS_PER_WORD; j++) {
00085                         b->v[ix] |= ((WORD_TYPE)1 << j);
00086                 }
00087         }
00088 
00089         return b;
00090 }
00091 
00092 void *
00093 bitmap_getdata(struct bitmap *b)
00094 {
00095         return b->v;
00096 }
00097 
00098 int
00099 bitmap_alloc(struct bitmap *b, unsigned *index)
00100 {
00101         unsigned ix;
00102         unsigned maxix = DIVROUNDUP(b->nbits, BITS_PER_WORD);
00103         unsigned offset;
00104 
00105         for (ix=0; ix<maxix; ix++) {
00106                 if (b->v[ix]!=WORD_ALLBITS) {
00107                         for (offset = 0; offset < BITS_PER_WORD; offset++) {
00108                                 WORD_TYPE mask = ((WORD_TYPE)1) << offset;
00109 
00110                                 if ((b->v[ix] & mask)==0) {
00111                                         b->v[ix] |= mask;
00112                                         *index = (ix*BITS_PER_WORD)+offset;
00113                                         KASSERT(*index < b->nbits);
00114                                         return 0;
00115                                 }
00116                         }
00117                         KASSERT(0);
00118                 }
00119         }
00120         return ENOSPC;
00121 }
00122 
00123 static
00124 inline
00125 void
00126 bitmap_translate(unsigned bitno, unsigned *ix, WORD_TYPE *mask)
00127 {
00128         unsigned offset;
00129         *ix = bitno / BITS_PER_WORD;
00130         offset = bitno % BITS_PER_WORD;
00131         *mask = ((WORD_TYPE)1) << offset;
00132 }
00133 
00134 void
00135 bitmap_mark(struct bitmap *b, unsigned index)
00136 {
00137         unsigned ix;
00138         WORD_TYPE mask;
00139 
00140         KASSERT(index < b->nbits);
00141         bitmap_translate(index, &ix, &mask);
00142 
00143         KASSERT((b->v[ix] & mask)==0);
00144         b->v[ix] |= mask;
00145 }
00146 
00147 void
00148 bitmap_unmark(struct bitmap *b, unsigned index)
00149 {
00150         unsigned ix;
00151         WORD_TYPE mask;
00152 
00153         KASSERT(index < b->nbits);
00154         bitmap_translate(index, &ix, &mask);
00155 
00156         KASSERT((b->v[ix] & mask)!=0);
00157         b->v[ix] &= ~mask;
00158 }
00159 
00160 
00161 int
00162 bitmap_isset(struct bitmap *b, unsigned index) 
00163 {
00164         unsigned ix;
00165         WORD_TYPE mask;
00166 
00167         bitmap_translate(index, &ix, &mask);
00168         return (b->v[ix] & mask);
00169 }
00170 
00171 void
00172 bitmap_destroy(struct bitmap *b)
00173 {
00174         kfree(b->v);
00175         kfree(b);
00176 }
 All Data Structures