2 * bit map routines (in-core).
5 * Copyright (c) 1995, 1996 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. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Marcus D. Watts.
18 * 4. The name of the developer may not be used to endorse or promote
19 * products derived from this software without specific prior written
22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
24 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
25 * MARCUS D. WATTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <afsconfig.h>
35 #include <afs/param.h>
45 #undef PRINT_MAP_ERROR
46 /* #define MAP_DEBUG /**/
47 /* #define NEED_READ_WRITE /**/
50 #define MSHIFT 8 /* XXX make this 8 in the production version... */
51 #define MDATA (1<<MSHIFT)
53 struct bitmap *m_next;
58 #define MAP(p) ((struct bitmap*)((long)(p)&~1))
59 #define NEGMAP(p) (((int)(p))&1)
60 #define POSMAP(p) (!NEGMAP(p))
61 #define NOT_MAP(mp) ((struct map *) (((long)(mp)) ^ 1))
63 #define NUMBERTOBIT(n) ((n) & ((1<<LSHIFT)-1))
64 #define NUMBERTOINDEX(n) ((n>>LSHIFT) & ((1<<MSHIFT)-1))
65 #define NUMBERTOPAGE(n) ((n>>(LSHIFT+MSHIFT)))
66 #define TONUMBER(p,x,b) ((b) + ((x)<<LSHIFT) + ((p)<<((LSHIFT+MSHIFT))))
68 #define Mflag (debug_mask & (1L<<('Y'-'@')))
69 #define Aflag (debug_mask & (1L<<('Z'-'@')))
70 extern int debug_mask;
74 in_map(struct map *parm, long node)
89 printf("in_map: is %d in [", node);
94 bit = NUMBERTOBIT(node);
95 x = NUMBERTOINDEX(node);
96 page = NUMBERTOPAGE(node);
99 if (TONUMBER(page, x, bit) != node) {
101 ("bxp mixup: node=%ld -> p=%d x=%d b=%d -> %ld, %ld, %ld = %ld\n",
102 node, page, x, bit, TONUMBER(page, 0, 0), TONUMBER(0, x, 0),
103 TONUMBER(0, 0, bit), TONUMBER(page, x, bit));
108 for (map = MAP(parm); map; map = map->m_next)
109 if (map->m_page == page)
110 return NEGMAP(parm) ^ (!!(map->m_data[x] & bit));
111 result = !POSMAP(parm);
114 printf(" -> %s\n", result ? "yes" : "no");
123 struct bitmap *map, *next;
126 printf("Freeing map");
150 printf("add_map: adding %d to [", node);
155 bit = NUMBERTOBIT(node);
156 x = NUMBERTOINDEX(node);
157 page = NUMBERTOPAGE(node);
161 for (map = MAP(parm); map; map = map->m_next)
162 if (map->m_page == page)
165 map = (struct bitmap *)malloc(sizeof *map);
167 #ifdef PRINT_MAP_ERROR
168 printf("No memory!\n");
170 free_map((struct map *)map);
174 bzero((char *)map->m_data, sizeof map->m_data);
177 for (i = 0; i < MDATA; ++i)
180 map->m_next = MAP(parm);
182 parm = (struct map *)map;
187 map->m_data[x] |= bit;
189 map->m_data[x] &= ~bit;
197 return (struct map *)parm;
204 struct bitmap **mpp, *mp2;
206 for (mpp = ↦ mp2 = *mpp;) {
207 for (i = 0; i < MDATA; ++i)
211 #ifdef PRINT_MAP_ERROR
212 printf("simplify_bitmap: failed to eliminate zero page %d\n",
224 or_bitmap(left, right)
225 struct bitmap *left, *right;
227 struct bitmap **rightmp, *lmap, *rmap;
229 for (lmap = left; lmap; lmap = lmap->m_next) {
230 for (rightmp = &right; rmap = *rightmp; rightmp = &rmap->m_next)
231 if (rmap->m_page == lmap->m_page) {
232 for (i = 0; i < MDATA; ++i)
233 lmap->m_data[i] |= rmap->m_data[i];
234 *rightmp = rmap->m_next;
239 for (rightmp = &left; *rightmp; rightmp = &(*rightmp)->m_next);
245 and_bitmap(left, right)
246 struct bitmap *left, *right;
248 struct bitmap **rightmp, *lmap, *rmap, **leftmp;
251 for (leftmp = &left; lmap = *leftmp;) {
253 for (rightmp = &right; rmap = *rightmp; rightmp = &rmap->m_next)
254 if (rmap->m_page == lmap->m_page) {
255 for (i = 0; i < MDATA; ++i)
256 sig |= (lmap->m_data[i] &= rmap->m_data[i]);
257 *rightmp = rmap->m_next;
262 leftmp = &lmap->m_next;
264 *leftmp = lmap->m_next;
268 free_map((struct map *)right);
269 return simplify_bitmap(left);
272 /* bit set in left, but not in right */
274 bic_bitmap(left, right)
275 struct bitmap *left, *right;
277 struct bitmap **rightmp, *lmap, *rmap, **leftmp;
282 printf("bic_bitmap: left=%#lx right=%#lx\n", left, right);
285 for (leftmp = &left; lmap = *leftmp;) {
287 for (rightmp = &right; rmap = *rightmp; rightmp = &rmap->m_next)
288 if (rmap->m_page == lmap->m_page) {
289 for (i = 0; i < MDATA; ++i)
290 sig |= (lmap->m_data[i] &= ~rmap->m_data[i]);
291 *rightmp = rmap->m_next;
296 leftmp = &lmap->m_next;
298 *leftmp = lmap->m_next;
302 free_map((struct map *)right);
303 left = simplify_bitmap(left);
306 printf("bic_bitmap: result=%#lx\n", left);
314 struct map *mp1, *mp2;
318 printf("Anding maps");
326 mp1 = (struct map *)and_bitmap(mp1, mp2);
328 mp1 = (struct map *)bic_bitmap(mp1, MAP(mp2));
329 else if (POSMAP(mp2))
330 mp1 = (struct map *)bic_bitmap(mp2, MAP(mp1));
332 mp1 = NOT_MAP(or_bitmap(MAP(mp1), MAP(mp2)));
345 struct map *mp1, *mp2;
349 printf("Oring maps");
357 mp1 = (struct map *)or_bitmap(mp1, mp2);
359 mp1 = NOT_MAP(bic_bitmap(MAP(mp2), mp1));
360 else if (POSMAP(mp2))
361 mp1 = NOT_MAP(bic_bitmap(MAP(mp1), mp2));
363 mp1 = NOT_MAP(and_bitmap(MAP(mp1), MAP(mp2)));
380 printf("Notting map");
392 struct bitmap *result, **mpp, *map;
401 for (mpp = &result; *mpp = 0, map; map = map->m_next) {
402 *mpp = (struct bitmap *)malloc(sizeof **mpp);
406 printf("copy_map: out of memory\n");
408 free_map((struct map *)result);
413 mpp = &(*mpp)->m_next;
416 return NOT_MAP(result);
418 return (struct map *)result;
430 for (map = MAP(parm); map; map = map->m_next) {
431 for (i = 0; i < MDATA; ++i) {
432 if (!map->m_data[i]);
433 else if (!~map->m_data[i])
436 for (j = 0; j < (1L << LSHIFT); ++j)
437 if (map->m_data[i] & (1L << j))
442 nf = ~nf; /* note 1's complement */
447 printf(" -> %d\n", nf);
458 struct bitmap *map, *lowest;
467 printf("next_map: selecting next after %d from", node);
474 printf("next_map failed; negative map\n");
480 bit = NUMBERTOBIT(node);
481 x = NUMBERTOINDEX(node);
482 page = NUMBERTOPAGE(node);
486 for (map = MAP(parm); map; map = map->m_next)
487 if (map->m_page >= page && (!lowest || lowest->m_page > map->m_page)) {
490 if (page == map->m_page)
492 for (; i < MDATA; ++i, mask = ~0)
493 if (map->m_data[i] & mask)
496 for (bn = 0; bn < (1 << LSHIFT); ++bn)
497 if (map->m_data[i] & mask & (1L << bn)) {
502 if (bn == (1 << LSHIFT)) {
504 ("next_map: botch; pageno %d index %d data %#lx mask %#lx x,bit %d,%#lx\n",
505 map->m_page, i, map->m_data[i], mask, x, bit);
510 best = bn + ((i + ((map->m_page) << MSHIFT)
517 printf(" -> %d\n", best);
518 if (best >= 0 && !in_map((struct map *)parm, best)) {
519 printf("next_map: botch; %d not in map\n", best);
531 return next_map(parm, -9999);
539 struct bitmap *map, *lowest;
548 printf("prev_map: selecting previous before %d from", node);
555 printf("prev_map failed; negative map\n");
561 node = ((unsigned long)~0) >> 1;
564 bit = NUMBERTOBIT(node);
565 x = NUMBERTOINDEX(node);
566 page = NUMBERTOPAGE(node);
570 for (map = MAP(parm); map; map = map->m_next)
571 if (map->m_page <= page && (!lowest || lowest->m_page < map->m_page)) {
574 if (page == map->m_page)
575 i = x, mask = (bit << 1) - 1;
576 for (; i >= 0; --i, mask = ~0)
577 if (map->m_data[i] & mask)
580 for (bn = (1 << LSHIFT) - 1; bn >= 0; --bn)
581 if (map->m_data[i] & mask & (1L << bn)) {
588 ("prev_map: botch; pageno %d index %d data %#lx mask %#lx x,bit %d,%#lx\n",
589 map->m_page, i, map->m_data[i], mask, x, bit);
594 best = bn + ((i + ((map->m_page) << MSHIFT)
601 printf(" -> %d\n", best);
602 if (best >= 0 && !in_map(parm, best)) {
603 printf("prev_map: botch; %d not in map\n", best);
615 return prev_map(parm, 0x7fffffff);
622 return (struct map *)NEGMAP(map);
627 struct map *mp1, *mp2;
637 mp1 = and_map(mp1, NOT_MAP(mp2));
648 #ifdef PRINT_MAP_ERROR
654 int bitno, firstbitno, lastbitno;
660 printf(" nil(%lx)", parm);
662 printf(" %lx", parm);
665 for (; map; map = map->m_next)
666 for (i = 0; i < MDATA; ++i)
668 for (j = 0; j < (1 << LSHIFT); ++j) {
671 ((map->m_page) << (LSHIFT + MSHIFT));
672 if (map->m_data[i] & (1 << j)) {
673 if (bitno == lastbitno + 1) {
677 if (bitno != (lastbitno + 1)) {
678 if (firstbitno >= 0 && firstbitno != lastbitno)
679 printf("-%d", lastbitno);
682 printf(" %d", bitno);
683 firstbitno = lastbitno = bitno;
685 if (firstbitno >= 0 && firstbitno != lastbitno)
686 printf("-%d", lastbitno);
690 if (firstbitno >= 0 && firstbitno != lastbitno)
691 printf("-%d", lastbitno);
695 #ifdef NEED_READ_WRITE
701 struct bitmap *map, *result, **mp;
703 int bitno, lastno, thisno, prevno;
707 /* count, then startbitno, then bits. */
708 lastno = ((*f) (arg));
711 if (lastno & ((1 << LSHIFT) - 1)) {
712 #ifdef PRINT_MAP_ERROR
713 printf("read_map: bad count\n");
717 bitno = ((*f) (arg));
718 if (bitno & ((1 << LSHIFT) - 1)) {
719 #ifdef PRINT_MAP_ERROR
720 printf("read_map: bad start\n");
726 for (; bitno < lastno; bitno += (1 << LSHIFT)) {
730 page = NUMBERTOPAGE(bitno);
731 if (!map || map->m_page != page)
732 for (mp = &result; map = *mp; mp = &map->m_next)
733 if (map->m_page == page)
736 map = (struct bitmap *)malloc(sizeof *map);
738 #ifdef PRINT_MAP_ERROR
739 printf("No memory!\n");
742 free_map((struct map *)result);
745 bzero((char *)map->m_data, sizeof map->m_data);
750 map->m_data[NUMBERTOINDEX(bitno)] = data;
752 return (struct map *)result;
755 write_map(parm, f, arg)
762 int bitno, lastno, thisno, prevno;
765 bitno = first_map(parm);
766 bitno &= ~((1 << LSHIFT) - 1);
768 lastno = last_map(parm);
770 lastno += ((1 << LSHIFT));
771 lastno &= ~((1 << LSHIFT) - 1);
772 /* count, then startbitno, then bits. */
773 if ((*f) (arg, lastno) == -1)
775 /* word: number of bits */
776 if ((*f) (arg, bitno) == -1)
780 for (bitno = first_map(parm); bitno >= 0; bitno = next_map(parm, bitno)) {
781 page = NUMBERTOPAGE(bitno);
782 for (map = MAP(parm); map; map = map->m_next)
783 if (map->m_page == page)
786 #ifdef PRINT_MAP_ERROR
787 printf("write_map: botch #1: can't find page %d\n", page);
791 for (i = 0; i < MDATA; ++i) {
794 thisno = TONUMBER(page, i, 0);
795 for (j = thisno - prevno; j > 0; j -= (1 << LSHIFT))
796 if ((*f) (arg, 0) == -1)
800 if ((*f) (arg, map->m_data[i]) == -1)
802 prevno += (1 << LSHIFT);
804 if (i >= MDATA || !map->m_data[i])
809 bitno = TONUMBER(page, i, 0) - 1;
811 #ifdef PRINT_MAP_ERROR
812 if (prevno != lastno)
813 printf("write_map: botch #2: bitno=%d prevno=%d lastno=%d\n", bitno,