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>
44 #undef PRINT_MAP_ERROR
45 /* #define MAP_DEBUG */
46 /* #define NEED_READ_WRITE */
49 #define MSHIFT 8 /* XXX make this 8 in the production version... */
50 #define MDATA (1<<MSHIFT)
52 struct bitmap
*m_next
;
57 #define MAP(p) ((struct bitmap*)((intptr_t)(p)&~1))
58 #define NEGMAP(p) (((intptr_t)(p))&1)
59 #define POSMAP(p) (!NEGMAP(p))
60 #define NOT_MAP(mp) ((struct map *) (((intptr_t)(mp)) ^ 1))
62 #define NUMBERTOBIT(n) ((n) & ((1<<LSHIFT)-1))
63 #define NUMBERTOINDEX(n) ((n>>LSHIFT) & ((1<<MSHIFT)-1))
64 #define NUMBERTOPAGE(n) ((n>>(LSHIFT+MSHIFT)))
65 #define TONUMBER(p,x,b) ((b) + ((x)<<LSHIFT) + ((p)<<((LSHIFT+MSHIFT))))
67 #define Mflag (debug_mask & (1L<<('Y'-'@')))
68 #define Aflag (debug_mask & (1L<<('Z'-'@')))
69 extern int debug_mask
;
72 in_map(struct map
*parm
, int node
)
81 printf("in_map: is %d in [", node
);
86 bit
= NUMBERTOBIT(node
);
87 x
= NUMBERTOINDEX(node
);
88 page
= NUMBERTOPAGE(node
);
91 if (TONUMBER(page
, x
, bit
) != node
) {
93 ("bxp mixup: node=%d -> p=%d x=%d b=%d -> %d, %d, %d = %d\n",
94 node
, page
, x
, bit
, TONUMBER(page
, 0, 0), TONUMBER(0, x
, 0),
95 TONUMBER(0, 0, bit
), TONUMBER(page
, x
, bit
));
100 for (map
= MAP(parm
); map
; map
= map
->m_next
)
101 if (map
->m_page
== page
)
102 return NEGMAP(parm
) ^ (!!(map
->m_data
[x
] & bit
));
103 result
= !POSMAP(parm
);
106 printf(" -> %s\n", result
? "yes" : "no");
112 free_map(struct map
*parm
)
114 struct bitmap
*map
, *next
;
117 printf("Freeing map");
131 add_map(struct map
*parm
, int node
)
139 printf("add_map: adding %d to [", node
);
144 bit
= NUMBERTOBIT(node
);
145 x
= NUMBERTOINDEX(node
);
146 page
= NUMBERTOPAGE(node
);
150 for (map
= MAP(parm
); map
; map
= map
->m_next
)
151 if (map
->m_page
== page
)
154 map
= (struct bitmap
*)malloc(sizeof *map
);
156 #ifdef PRINT_MAP_ERROR
157 printf("No memory!\n");
159 free_map((struct map
*)map
);
163 memset( map
->m_data
, 0, sizeof map
->m_data
);
166 for (i
= 0; i
< MDATA
; ++i
)
169 map
->m_next
= MAP(parm
);
171 parm
= (struct map
*)map
;
176 map
->m_data
[x
] |= bit
;
178 map
->m_data
[x
] &= ~bit
;
186 return (struct map
*)parm
;
190 simplify_bitmap(struct bitmap
*map
)
192 struct bitmap
**mpp
, *mp2
;
194 for (mpp
= &map
; (mp2
= *mpp
);) {
195 for (i
= 0; i
< MDATA
; ++i
)
199 #ifdef PRINT_MAP_ERROR
200 printf("simplify_bitmap: failed to eliminate zero page %d\n",
212 or_bitmap(struct bitmap
*left
, struct bitmap
*right
)
214 struct bitmap
**rightmp
, *lmap
, *rmap
;
216 for (lmap
= left
; lmap
; lmap
= lmap
->m_next
) {
217 for (rightmp
= &right
; (rmap
= *rightmp
); rightmp
= &rmap
->m_next
)
218 if (rmap
->m_page
== lmap
->m_page
) {
219 for (i
= 0; i
< MDATA
; ++i
)
220 lmap
->m_data
[i
] |= rmap
->m_data
[i
];
221 *rightmp
= rmap
->m_next
;
226 for (rightmp
= &left
; *rightmp
; rightmp
= &(*rightmp
)->m_next
)
233 and_bitmap(struct bitmap
*left
, struct bitmap
*right
)
235 struct bitmap
**rightmp
, *lmap
, *rmap
, **leftmp
;
238 for (leftmp
= &left
; (lmap
= *leftmp
);) {
240 for (rightmp
= &right
; (rmap
= *rightmp
); rightmp
= &rmap
->m_next
)
241 if (rmap
->m_page
== lmap
->m_page
) {
242 for (i
= 0; i
< MDATA
; ++i
)
243 sig
|= (lmap
->m_data
[i
] &= rmap
->m_data
[i
]);
244 *rightmp
= rmap
->m_next
;
249 leftmp
= &lmap
->m_next
;
251 *leftmp
= lmap
->m_next
;
255 free_map((struct map
*)right
);
256 return simplify_bitmap(left
);
259 /* bit set in left, but not in right */
261 bic_bitmap(struct bitmap
*left
, struct bitmap
*right
)
263 struct bitmap
**rightmp
, *lmap
, *rmap
, **leftmp
;
268 printf("bic_bitmap: left=%#lx right=%#lx\n", (long)left
, (long)right
);
271 for (leftmp
= &left
; (lmap
= *leftmp
);) {
273 for (rightmp
= &right
; (rmap
= *rightmp
); rightmp
= &rmap
->m_next
)
274 if (rmap
->m_page
== lmap
->m_page
) {
275 for (i
= 0; i
< MDATA
; ++i
)
276 sig
|= (lmap
->m_data
[i
] &= ~rmap
->m_data
[i
]);
277 *rightmp
= rmap
->m_next
;
282 leftmp
= &lmap
->m_next
;
284 *leftmp
= lmap
->m_next
;
288 free_map((struct map
*)right
);
289 left
= simplify_bitmap(left
);
292 printf("bic_bitmap: result=%#lx\n", (long) left
);
299 and_map(struct map
*mp1
, struct map
*mp2
)
303 printf("Anding maps");
311 mp1
= (struct map
*)and_bitmap((struct bitmap
*) mp1
,
312 (struct bitmap
*) mp2
);
314 mp1
= (struct map
*)bic_bitmap((struct bitmap
*) mp1
, MAP(mp2
));
315 else if (POSMAP(mp2
))
316 mp1
= (struct map
*)bic_bitmap((struct bitmap
*) mp2
, MAP(mp1
));
318 mp1
= NOT_MAP(or_bitmap(MAP(mp1
), MAP(mp2
)));
330 or_map(struct map
*mp1
, struct map
*mp2
)
334 printf("Oring maps");
342 mp1
= (struct map
*)or_bitmap((struct bitmap
*) mp1
,
343 (struct bitmap
*) mp2
);
345 mp1
= NOT_MAP(bic_bitmap(MAP(mp2
), (struct bitmap
*) mp1
));
346 else if (POSMAP(mp2
))
347 mp1
= NOT_MAP(bic_bitmap(MAP(mp1
), (struct bitmap
*) mp2
));
349 mp1
= NOT_MAP(and_bitmap(MAP(mp1
), MAP(mp2
)));
361 not_map(struct map
*map
)
365 printf("Notting map");
374 copy_map(struct map
*parm
)
376 struct bitmap
*result
, **mpp
, *map
;
385 for (mpp
= &result
; (*mpp
= 0), map
; map
= map
->m_next
) {
386 *mpp
= (struct bitmap
*)malloc(sizeof **mpp
);
390 printf("copy_map: out of memory\n");
392 free_map((struct map
*)result
);
397 mpp
= &(*mpp
)->m_next
;
400 return NOT_MAP(result
);
402 return (struct map
*)result
;
406 count_map(struct map
*parm
)
413 for (map
= MAP(parm
); map
; map
= map
->m_next
) {
414 for (i
= 0; i
< MDATA
; ++i
) {
417 else if (!~map
->m_data
[i
])
420 for (j
= 0; j
< (1L << LSHIFT
); ++j
)
421 if (map
->m_data
[i
] & (1L << j
))
426 nf
= ~nf
; /* note 1's complement */
431 printf(" -> %d\n", nf
);
438 next_map(struct map
*parm
, int node
)
440 struct bitmap
*map
, *lowest
;
449 printf("next_map: selecting next after %d from", node
);
456 printf("next_map failed; negative map\n");
462 bit
= NUMBERTOBIT(node
);
463 x
= NUMBERTOINDEX(node
);
464 page
= NUMBERTOPAGE(node
);
468 for (map
= MAP(parm
); map
; map
= map
->m_next
)
469 if (map
->m_page
>= page
&& (!lowest
|| lowest
->m_page
> map
->m_page
)) {
472 if (page
== map
->m_page
)
474 for (; i
< MDATA
; ++i
, mask
= ~0)
475 if (map
->m_data
[i
] & mask
)
478 for (bn
= 0; bn
< (1 << LSHIFT
); ++bn
)
479 if (map
->m_data
[i
] & mask
& (1L << bn
)) {
484 if (bn
== (1 << LSHIFT
)) {
486 ("next_map: botch; pageno %d index %d data %#x mask %#x x,bit %d,%#x\n",
487 map
->m_page
, i
, map
->m_data
[i
], mask
, x
, bit
);
492 best
= bn
+ ((i
+ ((map
->m_page
) << MSHIFT
)
499 printf(" -> %d\n", best
);
500 if (best
>= 0 && !in_map(parm
, best
)) {
501 printf("next_map: botch; %d not in map\n", best
);
510 first_map(struct map
*parm
)
512 return next_map(parm
, -9999);
516 prev_map(struct map
*parm
, int node
)
518 struct bitmap
*map
, *lowest
;
527 printf("prev_map: selecting previous before %d from", node
);
534 printf("prev_map failed; negative map\n");
540 node
= ((unsigned int)~0) >> 1;
543 bit
= NUMBERTOBIT(node
);
544 x
= NUMBERTOINDEX(node
);
545 page
= NUMBERTOPAGE(node
);
549 for (map
= MAP(parm
); map
; map
= map
->m_next
)
550 if (map
->m_page
<= page
&& (!lowest
|| lowest
->m_page
< map
->m_page
)) {
553 if (page
== map
->m_page
)
554 i
= x
, mask
= (bit
<< 1) - 1;
555 for (; i
>= 0; --i
, mask
= ~0)
556 if (map
->m_data
[i
] & mask
)
559 for (bn
= (1 << LSHIFT
) - 1; bn
>= 0; --bn
)
560 if (map
->m_data
[i
] & mask
& (1L << bn
)) {
567 ("prev_map: botch; pageno %d index %d data %#x mask %#x x,bit %d,%#x\n",
568 map
->m_page
, i
, map
->m_data
[i
], mask
, x
, bit
);
573 best
= bn
+ ((i
+ ((map
->m_page
) << MSHIFT
)
580 printf(" -> %d\n", best
);
581 if (best
>= 0 && !in_map(parm
, best
)) {
582 printf("prev_map: botch; %d not in map\n", best
);
591 last_map(struct map
*parm
)
593 return prev_map(parm
, 0x7fffffff);
597 negative_map(struct map
*map
)
599 return (struct map
*)NEGMAP(map
);
603 bic_map(struct map
*mp1
, struct map
*mp2
)
613 mp1
= and_map(mp1
, NOT_MAP(mp2
));
624 #ifdef PRINT_MAP_ERROR
626 print_map(struct map
*parm
)
630 int bitno
, firstbitno
, lastbitno
;
636 printf(" nil(%lx)", (long)parm
);
638 printf(" %lx", (long)parm
);
641 for (; map
; map
= map
->m_next
)
642 for (i
= 0; i
< MDATA
; ++i
)
644 for (j
= 0; j
< (1 << LSHIFT
); ++j
) {
647 ((map
->m_page
) << (LSHIFT
+ MSHIFT
));
648 if (map
->m_data
[i
] & (1 << j
)) {
649 if (bitno
== lastbitno
+ 1) {
653 if (bitno
!= (lastbitno
+ 1)) {
654 if (firstbitno
>= 0 && firstbitno
!= lastbitno
)
655 printf("-%d", lastbitno
);
658 printf(" %d", bitno
);
659 firstbitno
= lastbitno
= bitno
;
661 if (firstbitno
>= 0 && firstbitno
!= lastbitno
)
662 printf("-%d", lastbitno
);
666 if (firstbitno
>= 0 && firstbitno
!= lastbitno
)
667 printf("-%d", lastbitno
);
671 #ifdef NEED_READ_WRITE
673 read_map(int (*f
) (void *), char *arg
)
675 struct bitmap
*map
, *result
, **mp
;
680 /* count, then startbitno, then bits. */
681 lastno
= ((*f
) (arg
));
684 if (lastno
& ((1 << LSHIFT
) - 1)) {
685 #ifdef PRINT_MAP_ERROR
686 printf("read_map: bad count\n");
690 bitno
= ((*f
) (arg
));
691 if (bitno
& ((1 << LSHIFT
) - 1)) {
692 #ifdef PRINT_MAP_ERROR
693 printf("read_map: bad start\n");
699 for (; bitno
< lastno
; bitno
+= (1 << LSHIFT
)) {
703 page
= NUMBERTOPAGE(bitno
);
704 if (!map
|| map
->m_page
!= page
)
705 for (mp
= &result
; (map
= *mp
); mp
= &map
->m_next
)
706 if (map
->m_page
== page
)
709 map
= (struct bitmap
*)malloc(sizeof *map
);
711 #ifdef PRINT_MAP_ERROR
712 printf("No memory!\n");
715 free_map((struct map
*)result
);
718 memset( map
->m_data
, 0, sizeof map
->m_data
);
723 map
->m_data
[NUMBERTOINDEX(bitno
)] = data
;
725 return (struct map
*)result
;
729 write_map(struct map
*parm
, int (*f
) (void *, int), char *arg
)
733 int bitno
, lastno
, thisno
, prevno
;
736 bitno
= first_map(parm
);
737 bitno
&= ~((1 << LSHIFT
) - 1);
739 lastno
= last_map(parm
);
741 lastno
+= ((1 << LSHIFT
));
742 lastno
&= ~((1 << LSHIFT
) - 1);
743 /* count, then startbitno, then bits. */
744 if ((*f
) (arg
, lastno
) == -1)
746 /* word: number of bits */
747 if ((*f
) (arg
, bitno
) == -1)
751 for (bitno
= first_map(parm
); bitno
>= 0; bitno
= next_map(parm
, bitno
)) {
752 page
= NUMBERTOPAGE(bitno
);
753 for (map
= MAP(parm
); map
; map
= map
->m_next
)
754 if (map
->m_page
== page
)
757 #ifdef PRINT_MAP_ERROR
758 printf("write_map: botch #1: can't find page %d\n", page
);
762 for (i
= 0; i
< MDATA
; ++i
) {
765 thisno
= TONUMBER(page
, i
, 0);
766 for (j
= thisno
- prevno
; j
> 0; j
-= (1 << LSHIFT
))
767 if ((*f
) (arg
, 0) == -1)
771 if ((*f
) (arg
, map
->m_data
[i
]) == -1)
773 prevno
+= (1 << LSHIFT
);
775 if (i
>= MDATA
|| !map
->m_data
[i
])
780 bitno
= TONUMBER(page
, i
, 0) - 1;
782 #ifdef PRINT_MAP_ERROR
783 if (prevno
!= lastno
)
784 printf("write_map: botch #2: bitno=%d prevno=%d lastno=%d\n", bitno
,