140b0b3f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2915b0882SArnaldo Carvalho de Melo /*
3915b0882SArnaldo Carvalho de Melo * From lib/bitmap.c
4915b0882SArnaldo Carvalho de Melo * Helper functions for bitmap.h.
5915b0882SArnaldo Carvalho de Melo */
6915b0882SArnaldo Carvalho de Melo #include <linux/bitmap.h>
7915b0882SArnaldo Carvalho de Melo
__bitmap_weight(const unsigned long * bitmap,int bits)84e23eeebSLinus Torvalds unsigned int __bitmap_weight(const unsigned long *bitmap, int bits)
9915b0882SArnaldo Carvalho de Melo {
104e23eeebSLinus Torvalds unsigned int k, w = 0, lim = bits/BITS_PER_LONG;
11915b0882SArnaldo Carvalho de Melo
12915b0882SArnaldo Carvalho de Melo for (k = 0; k < lim; k++)
13915b0882SArnaldo Carvalho de Melo w += hweight_long(bitmap[k]);
14915b0882SArnaldo Carvalho de Melo
15915b0882SArnaldo Carvalho de Melo if (bits % BITS_PER_LONG)
16915b0882SArnaldo Carvalho de Melo w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
17915b0882SArnaldo Carvalho de Melo
18915b0882SArnaldo Carvalho de Melo return w;
19915b0882SArnaldo Carvalho de Melo }
20915b0882SArnaldo Carvalho de Melo
__bitmap_or(unsigned long * dst,const unsigned long * bitmap1,const unsigned long * bitmap2,int bits)21915b0882SArnaldo Carvalho de Melo void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
22915b0882SArnaldo Carvalho de Melo const unsigned long *bitmap2, int bits)
23915b0882SArnaldo Carvalho de Melo {
24915b0882SArnaldo Carvalho de Melo int k;
25915b0882SArnaldo Carvalho de Melo int nr = BITS_TO_LONGS(bits);
26915b0882SArnaldo Carvalho de Melo
27915b0882SArnaldo Carvalho de Melo for (k = 0; k < nr; k++)
28915b0882SArnaldo Carvalho de Melo dst[k] = bitmap1[k] | bitmap2[k];
29915b0882SArnaldo Carvalho de Melo }
30820d12b7SJiri Olsa
bitmap_scnprintf(unsigned long * bitmap,unsigned int nbits,char * buf,size_t size)31e5b9252dSYury Norov size_t bitmap_scnprintf(unsigned long *bitmap, unsigned int nbits,
32820d12b7SJiri Olsa char *buf, size_t size)
33820d12b7SJiri Olsa {
34820d12b7SJiri Olsa /* current bit is 'cur', most recently seen range is [rbot, rtop] */
35e5b9252dSYury Norov unsigned int cur, rbot, rtop;
36820d12b7SJiri Olsa bool first = true;
37820d12b7SJiri Olsa size_t ret = 0;
38820d12b7SJiri Olsa
39820d12b7SJiri Olsa rbot = cur = find_first_bit(bitmap, nbits);
40820d12b7SJiri Olsa while (cur < nbits) {
41820d12b7SJiri Olsa rtop = cur;
42820d12b7SJiri Olsa cur = find_next_bit(bitmap, nbits, cur + 1);
43820d12b7SJiri Olsa if (cur < nbits && cur <= rtop + 1)
44820d12b7SJiri Olsa continue;
45820d12b7SJiri Olsa
46820d12b7SJiri Olsa if (!first)
47820d12b7SJiri Olsa ret += scnprintf(buf + ret, size - ret, ",");
48820d12b7SJiri Olsa
49820d12b7SJiri Olsa first = false;
50820d12b7SJiri Olsa
51820d12b7SJiri Olsa ret += scnprintf(buf + ret, size - ret, "%d", rbot);
52820d12b7SJiri Olsa if (rbot < rtop)
53820d12b7SJiri Olsa ret += scnprintf(buf + ret, size - ret, "-%d", rtop);
54820d12b7SJiri Olsa
55820d12b7SJiri Olsa rbot = cur;
56820d12b7SJiri Olsa }
57820d12b7SJiri Olsa return ret;
58820d12b7SJiri Olsa }
59741c74f5SJiri Olsa
__bitmap_and(unsigned long * dst,const unsigned long * bitmap1,const unsigned long * bitmap2,unsigned int bits)60e2863a78SYury Norov bool __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
61741c74f5SJiri Olsa const unsigned long *bitmap2, unsigned int bits)
62741c74f5SJiri Olsa {
63741c74f5SJiri Olsa unsigned int k;
64741c74f5SJiri Olsa unsigned int lim = bits/BITS_PER_LONG;
65741c74f5SJiri Olsa unsigned long result = 0;
66741c74f5SJiri Olsa
67741c74f5SJiri Olsa for (k = 0; k < lim; k++)
68741c74f5SJiri Olsa result |= (dst[k] = bitmap1[k] & bitmap2[k]);
69741c74f5SJiri Olsa if (bits % BITS_PER_LONG)
70741c74f5SJiri Olsa result |= (dst[k] = bitmap1[k] & bitmap2[k] &
71741c74f5SJiri Olsa BITMAP_LAST_WORD_MASK(bits));
72741c74f5SJiri Olsa return result != 0;
73741c74f5SJiri Olsa }
748812ad41SAlexey Budankov
__bitmap_equal(const unsigned long * bitmap1,const unsigned long * bitmap2,unsigned int bits)75005f1700SKees Cook bool __bitmap_equal(const unsigned long *bitmap1,
768812ad41SAlexey Budankov const unsigned long *bitmap2, unsigned int bits)
778812ad41SAlexey Budankov {
788812ad41SAlexey Budankov unsigned int k, lim = bits/BITS_PER_LONG;
798812ad41SAlexey Budankov for (k = 0; k < lim; ++k)
808812ad41SAlexey Budankov if (bitmap1[k] != bitmap2[k])
81005f1700SKees Cook return false;
828812ad41SAlexey Budankov
838812ad41SAlexey Budankov if (bits % BITS_PER_LONG)
848812ad41SAlexey Budankov if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
85005f1700SKees Cook return false;
868812ad41SAlexey Budankov
87005f1700SKees Cook return true;
888812ad41SAlexey Budankov }
89f20510d5SAlexey Bayduraev
__bitmap_intersects(const unsigned long * bitmap1,const unsigned long * bitmap2,unsigned int bits)90005f1700SKees Cook bool __bitmap_intersects(const unsigned long *bitmap1,
91f20510d5SAlexey Bayduraev const unsigned long *bitmap2, unsigned int bits)
92f20510d5SAlexey Bayduraev {
93f20510d5SAlexey Bayduraev unsigned int k, lim = bits/BITS_PER_LONG;
94f20510d5SAlexey Bayduraev for (k = 0; k < lim; ++k)
95f20510d5SAlexey Bayduraev if (bitmap1[k] & bitmap2[k])
96005f1700SKees Cook return true;
97f20510d5SAlexey Bayduraev
98f20510d5SAlexey Bayduraev if (bits % BITS_PER_LONG)
99f20510d5SAlexey Bayduraev if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
100005f1700SKees Cook return true;
101005f1700SKees Cook return false;
102f20510d5SAlexey Bayduraev }
103692a68eeSWei Yang
__bitmap_set(unsigned long * map,unsigned int start,int len)104*82114e45SWei Yang void __bitmap_set(unsigned long *map, unsigned int start, int len)
105*82114e45SWei Yang {
106*82114e45SWei Yang unsigned long *p = map + BIT_WORD(start);
107*82114e45SWei Yang const unsigned int size = start + len;
108*82114e45SWei Yang int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
109*82114e45SWei Yang unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
110*82114e45SWei Yang
111*82114e45SWei Yang while (len - bits_to_set >= 0) {
112*82114e45SWei Yang *p |= mask_to_set;
113*82114e45SWei Yang len -= bits_to_set;
114*82114e45SWei Yang bits_to_set = BITS_PER_LONG;
115*82114e45SWei Yang mask_to_set = ~0UL;
116*82114e45SWei Yang p++;
117*82114e45SWei Yang }
118*82114e45SWei Yang if (len) {
119*82114e45SWei Yang mask_to_set &= BITMAP_LAST_WORD_MASK(size);
120*82114e45SWei Yang *p |= mask_to_set;
121*82114e45SWei Yang }
122*82114e45SWei Yang }
123*82114e45SWei Yang
__bitmap_clear(unsigned long * map,unsigned int start,int len)124692a68eeSWei Yang void __bitmap_clear(unsigned long *map, unsigned int start, int len)
125692a68eeSWei Yang {
126692a68eeSWei Yang unsigned long *p = map + BIT_WORD(start);
127692a68eeSWei Yang const unsigned int size = start + len;
128692a68eeSWei Yang int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
129692a68eeSWei Yang unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
130692a68eeSWei Yang
131692a68eeSWei Yang while (len - bits_to_clear >= 0) {
132692a68eeSWei Yang *p &= ~mask_to_clear;
133692a68eeSWei Yang len -= bits_to_clear;
134692a68eeSWei Yang bits_to_clear = BITS_PER_LONG;
135692a68eeSWei Yang mask_to_clear = ~0UL;
136692a68eeSWei Yang p++;
137692a68eeSWei Yang }
138692a68eeSWei Yang if (len) {
139692a68eeSWei Yang mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
140692a68eeSWei Yang *p &= ~mask_to_clear;
141692a68eeSWei Yang }
142692a68eeSWei Yang }
143