2 * bit map routines (in-core).
5 * Copyright (c) 1995, 1996, 2007 Marcus D. Watts All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the developer may not be used to endorse or promote
16 * products derived from this software without specific prior written
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 * MARCUS D. WATTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
28 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <afsconfig.h>
32 #include <afs/param.h>
40 #ifdef STDLIB_HAS_MALLOC_PROTOS
46 #undef PRINT_MAP_ERROR
47 /* #define MAP_DEBUG /**/
48 /* #define NEED_READ_WRITE /**/
51 #define MSHIFT 8 /* XXX make this 8 in the production version... */
52 #define MDATA (1<<MSHIFT)
54 struct bitmap *m_next;
59 #define MAP(p) ((struct bitmap*)((int)(p)&~1))
60 #define NEGMAP(p) (((int)(p))&1)
61 #define POSMAP(p) (!NEGMAP(p))
62 #define NOT_MAP(mp) ((struct map *) (((int)(mp)) ^ 1))
64 #define NUMBERTOBIT(n) ((n) & ((1<<LSHIFT)-1))
65 #define NUMBERTOINDEX(n) ((n>>LSHIFT) & ((1<<MSHIFT)-1))
66 #define NUMBERTOPAGE(n) ((n>>(LSHIFT+MSHIFT)))
67 #define TONUMBER(p,x,b) ((b) + ((x)<<LSHIFT) + ((p)<<((LSHIFT+MSHIFT))))
69 #define Mflag (debug_mask & (1L<<('Y'-'@')))
70 #define Aflag (debug_mask & (1L<<('Z'-'@')))
71 extern int debug_mask;
74 in_map(struct map *parm, int node)
83 printf("in_map: is %d in [", node);
88 bit = NUMBERTOBIT(node);
89 x = NUMBERTOINDEX(node);
90 page = NUMBERTOPAGE(node);
93 if (TONUMBER(page, x, bit) != node) {
95 ("bxp mixup: node=%d -> p=%d x=%d b=%d -> %d, %d, %d = %d\n",
96 node, page, x, bit, TONUMBER(page, 0, 0), TONUMBER(0, x, 0),
97 TONUMBER(0, 0, bit), TONUMBER(page, x, bit));
102 for (map = MAP(parm); map; map = map->m_next)
103 if (map->m_page == page)
104 return NEGMAP(parm) ^ (!!(map->m_data[x] & bit));
105 result = !POSMAP(parm);
108 printf(" -> %s\n", result ? "yes" : "no");
114 free_map(struct map *parm)
116 struct bitmap *map, *next;
119 printf("Freeing map");
133 add_map(struct map *parm, int node)
141 printf("add_map: adding %d to [", node);
146 bit = NUMBERTOBIT(node);
147 x = NUMBERTOINDEX(node);
148 page = NUMBERTOPAGE(node);
152 for (map = MAP(parm); map; map = map->m_next)
153 if (map->m_page == page)
156 map = (struct bitmap *)malloc(sizeof *map);
158 #ifdef PRINT_MAP_ERROR
159 printf("No memory!\n");
161 free_map((struct map *)map);
165 memset((char *) map->m_data, 0, sizeof map->m_data);
168 for (i = 0; i < MDATA; ++i)
171 map->m_next = MAP(parm);
173 parm = (struct map *)map;
178 map->m_data[x] |= bit;
180 map->m_data[x] &= ~bit;
188 return (struct map *)parm;
192 simplify_bitmap(struct bitmap *map)
194 struct bitmap **mpp, *mp2;
196 for (mpp = ↦ (mp2 = *mpp);) {
197 for (i = 0; i < MDATA; ++i)
201 #ifdef PRINT_MAP_ERROR
202 printf("simplify_bitmap: failed to eliminate zero page %d\n",
214 or_bitmap(struct bitmap *left, struct bitmap *right)
216 struct bitmap **rightmp, *lmap, *rmap;
218 for (lmap = left; lmap; lmap = lmap->m_next) {
219 for (rightmp = &right; (rmap = *rightmp); rightmp = &rmap->m_next)
220 if (rmap->m_page == lmap->m_page) {
221 for (i = 0; i < MDATA; ++i)
222 lmap->m_data[i] |= rmap->m_data[i];
223 *rightmp = rmap->m_next;
228 for (rightmp = &left; *rightmp; rightmp = &(*rightmp)->m_next)
235 and_bitmap(struct bitmap *left, struct bitmap *right)
237 struct bitmap **rightmp, *lmap, *rmap, **leftmp;
240 for (leftmp = &left; (lmap = *leftmp);) {
242 for (rightmp = &right; (rmap = *rightmp); rightmp = &rmap->m_next)
243 if (rmap->m_page == lmap->m_page) {
244 for (i = 0; i < MDATA; ++i)
245 sig |= (lmap->m_data[i] &= rmap->m_data[i]);
246 *rightmp = rmap->m_next;
251 leftmp = &lmap->m_next;
253 *leftmp = lmap->m_next;
257 free_map((struct map *)right);
258 return simplify_bitmap(left);
261 /* bit set in left, but not in right */
263 bic_bitmap(struct bitmap *left, struct bitmap *right)
265 struct bitmap **rightmp, *lmap, *rmap, **leftmp;
270 printf("bic_bitmap: left=%#lx right=%#lx\n", (long)left, (long)right);
273 for (leftmp = &left; (lmap = *leftmp);) {
275 for (rightmp = &right; (rmap = *rightmp); rightmp = &rmap->m_next)
276 if (rmap->m_page == lmap->m_page) {
277 for (i = 0; i < MDATA; ++i)
278 sig |= (lmap->m_data[i] &= ~rmap->m_data[i]);
279 *rightmp = rmap->m_next;
284 leftmp = &lmap->m_next;
286 *leftmp = lmap->m_next;
290 free_map((struct map *)right);
291 left = simplify_bitmap(left);
294 printf("bic_bitmap: result=%#lx\n", (long) left);
301 and_map(struct map *mp1, struct map *mp2)
305 printf("Anding maps");
313 mp1 = (struct map *)and_bitmap((struct bitmap *) mp1,
314 (struct bitmap *) mp2);
316 mp1 = (struct map *)bic_bitmap((struct bitmap *) mp1, MAP(mp2));
317 else if (POSMAP(mp2))
318 mp1 = (struct map *)bic_bitmap((struct bitmap *) mp2, MAP(mp1));
320 mp1 = NOT_MAP(or_bitmap(MAP(mp1), MAP(mp2)));
332 or_map(struct map *mp1, struct map *mp2)
336 printf("Oring maps");
344 mp1 = (struct map *)or_bitmap((struct bitmap *) mp1,
345 (struct bitmap *) mp2);
347 mp1 = NOT_MAP(bic_bitmap(MAP(mp2), (struct bitmap *) mp1));
348 else if (POSMAP(mp2))
349 mp1 = NOT_MAP(bic_bitmap(MAP(mp1), (struct bitmap *) mp2));
351 mp1 = NOT_MAP(and_bitmap(MAP(mp1), MAP(mp2)));
363 not_map(struct map *map)
367 printf("Notting map");
376 copy_map(struct map *parm)
378 struct bitmap *result, **mpp, *map;
387 for (mpp = &result; (*mpp = 0), map; map = map->m_next) {
388 *mpp = (struct bitmap *)malloc(sizeof **mpp);
392 printf("copy_map: out of memory\n");
394 free_map((struct map *)result);
399 mpp = &(*mpp)->m_next;
402 return NOT_MAP(result);
404 return (struct map *)result;
408 count_map(struct map *parm)
415 for (map = MAP(parm); map; map = map->m_next) {
416 for (i = 0; i < MDATA; ++i) {
419 else if (!~map->m_data[i])
422 for (j = 0; j < (1L << LSHIFT); ++j)
423 if (map->m_data[i] & (1L << j))
428 nf = ~nf; /* note 1's complement */
433 printf(" -> %d\n", nf);
440 next_map(struct map *parm, int node)
442 struct bitmap *map, *lowest;
451 printf("next_map: selecting next after %d from", node);
458 printf("next_map failed; negative map\n");
464 bit = NUMBERTOBIT(node);
465 x = NUMBERTOINDEX(node);
466 page = NUMBERTOPAGE(node);
470 for (map = MAP(parm); map; map = map->m_next)
471 if (map->m_page >= page && (!lowest || lowest->m_page > map->m_page)) {
474 if (page == map->m_page)
476 for (; i < MDATA; ++i, mask = ~0)
477 if (map->m_data[i] & mask)
480 for (bn = 0; bn < (1 << LSHIFT); ++bn)
481 if (map->m_data[i] & mask & (1L << bn)) {
486 if (bn == (1 << LSHIFT)) {
488 ("next_map: botch; pageno %d index %d data %#x mask %#x x,bit %d,%#x\n",
489 map->m_page, i, map->m_data[i], mask, x, bit);
494 best = bn + ((i + ((map->m_page) << MSHIFT)
501 printf(" -> %d\n", best);
502 if (best >= 0 && !in_map(parm, best)) {
503 printf("next_map: botch; %d not in map\n", best);
512 first_map(struct map *parm)
514 return next_map(parm, -9999);
518 prev_map(struct map *parm, int node)
520 struct bitmap *map, *lowest;
529 printf("prev_map: selecting previous before %d from", node);
536 printf("prev_map failed; negative map\n");
542 node = ((unsigned int)~0) >> 1;
545 bit = NUMBERTOBIT(node);
546 x = NUMBERTOINDEX(node);
547 page = NUMBERTOPAGE(node);
551 for (map = MAP(parm); map; map = map->m_next)
552 if (map->m_page <= page && (!lowest || lowest->m_page < map->m_page)) {
555 if (page == map->m_page)
556 i = x, mask = (bit << 1) - 1;
557 for (; i >= 0; --i, mask = ~0)
558 if (map->m_data[i] & mask)
561 for (bn = (1 << LSHIFT) - 1; bn >= 0; --bn)
562 if (map->m_data[i] & mask & (1L << bn)) {
569 ("prev_map: botch; pageno %d index %d data %#x mask %#x x,bit %d,%#x\n",
570 map->m_page, i, map->m_data[i], mask, x, bit);
575 best = bn + ((i + ((map->m_page) << MSHIFT)
582 printf(" -> %d\n", best);
583 if (best >= 0 && !in_map(parm, best)) {
584 printf("prev_map: botch; %d not in map\n", best);
593 last_map(struct map *parm)
595 return prev_map(parm, 0x7fffffff);
599 negative_map(struct map *map)
601 return (struct map *)NEGMAP(map);
605 bic_map(struct map *mp1, struct map *mp2)
615 mp1 = and_map(mp1, NOT_MAP(mp2));
626 #ifdef PRINT_MAP_ERROR
628 print_map(struct map *parm)
632 int bitno, firstbitno, lastbitno;
638 printf(" nil(%lx)", (long)parm);
640 printf(" %lx", (long)parm);
643 for (; map; map = map->m_next)
644 for (i = 0; i < MDATA; ++i)
646 for (j = 0; j < (1 << LSHIFT); ++j) {
649 ((map->m_page) << (LSHIFT + MSHIFT));
650 if (map->m_data[i] & (1 << j)) {
651 if (bitno == lastbitno + 1) {
655 if (bitno != (lastbitno + 1)) {
656 if (firstbitno >= 0 && firstbitno != lastbitno)
657 printf("-%d", lastbitno);
660 printf(" %d", bitno);
661 firstbitno = lastbitno = bitno;
663 if (firstbitno >= 0 && firstbitno != lastbitno)
664 printf("-%d", lastbitno);
668 if (firstbitno >= 0 && firstbitno != lastbitno)
669 printf("-%d", lastbitno);
673 #ifdef NEED_READ_WRITE
675 read_map(int (*f) (void *), char *arg)
677 struct bitmap *map, *result, **mp;
682 /* count, then startbitno, then bits. */
683 lastno = ((*f) (arg));
686 if (lastno & ((1 << LSHIFT) - 1)) {
687 #ifdef PRINT_MAP_ERROR
688 printf("read_map: bad count\n");
692 bitno = ((*f) (arg));
693 if (bitno & ((1 << LSHIFT) - 1)) {
694 #ifdef PRINT_MAP_ERROR
695 printf("read_map: bad start\n");
701 for (; bitno < lastno; bitno += (1 << LSHIFT)) {
705 page = NUMBERTOPAGE(bitno);
706 if (!map || map->m_page != page)
707 for (mp = &result; (map = *mp); mp = &map->m_next)
708 if (map->m_page == page)
711 map = (struct bitmap *)malloc(sizeof *map);
713 #ifdef PRINT_MAP_ERROR
714 printf("No memory!\n");
717 free_map((struct map *)result);
720 memset((char *) map->m_data, 0, sizeof map->m_data);
725 map->m_data[NUMBERTOINDEX(bitno)] = data;
727 return (struct map *)result;
731 write_map(struct map *parm, int (*f) (void *, int), char *arg)
735 int bitno, lastno, thisno, prevno;
738 bitno = first_map(parm);
739 bitno &= ~((1 << LSHIFT) - 1);
741 lastno = last_map(parm);
743 lastno += ((1 << LSHIFT));
744 lastno &= ~((1 << LSHIFT) - 1);
745 /* count, then startbitno, then bits. */
746 if ((*f) (arg, lastno) == -1)
748 /* word: number of bits */
749 if ((*f) (arg, bitno) == -1)
753 for (bitno = first_map(parm); bitno >= 0; bitno = next_map(parm, bitno)) {
754 page = NUMBERTOPAGE(bitno);
755 for (map = MAP(parm); map; map = map->m_next)
756 if (map->m_page == page)
759 #ifdef PRINT_MAP_ERROR
760 printf("write_map: botch #1: can't find page %d\n", page);
764 for (i = 0; i < MDATA; ++i) {
767 thisno = TONUMBER(page, i, 0);
768 for (j = thisno - prevno; j > 0; j -= (1 << LSHIFT))
769 if ((*f) (arg, 0) == -1)
773 if ((*f) (arg, map->m_data[i]) == -1)
775 prevno += (1 << LSHIFT);
777 if (i >= MDATA || !map->m_data[i])
782 bitno = TONUMBER(page, i, 0) - 1;
784 #ifdef PRINT_MAP_ERROR
785 if (prevno != lastno)
786 printf("write_map: botch #2: bitno=%d prevno=%d lastno=%d\n", bitno,