bitmap.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /*
  2. This file is taken from the Linux kernel and minimally adapted for use in userspace
  3. */
  4. /*
  5. * lib/bitmap.c
  6. * Helper functions for bitmap.h.
  7. *
  8. * This source code is licensed under the GNU General Public License,
  9. * Version 2. See the file COPYING for more details.
  10. */
  11. #include "config.h"
  12. #include <unistd.h>
  13. #include <errno.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <ctype.h>
  17. #include "bitmap.h"
  18. #include "non-atomic.h"
  19. /*
  20. * bitmaps provide an array of bits, implemented using an an
  21. * array of unsigned longs. The number of valid bits in a
  22. * given bitmap does _not_ need to be an exact multiple of
  23. * BITS_PER_LONG.
  24. *
  25. * The possible unused bits in the last, partially used word
  26. * of a bitmap are 'don't care'. The implementation makes
  27. * no particular effort to keep them zero. It ensures that
  28. * their value will not affect the results of any operation.
  29. * The bitmap operations that return Boolean (bitmap_empty,
  30. * for example) or scalar (bitmap_weight, for example) results
  31. * carefully filter out these unused bits from impacting their
  32. * results.
  33. *
  34. * These operations actually hold to a slightly stronger rule:
  35. * if you don't input any bitmaps to these ops that have some
  36. * unused bits set, then they won't output any set unused bits
  37. * in output bitmaps.
  38. *
  39. * The byte ordering of bitmaps is more natural on little
  40. * endian architectures. See the big-endian headers
  41. * include/asm-ppc64/bitops.h and include/asm-s390/bitops.h
  42. * for the best explanations of this ordering.
  43. */
  44. int __bitmap_empty(const unsigned long *bitmap, int bits)
  45. {
  46. int k, lim = bits/BITS_PER_LONG;
  47. for (k = 0; k < lim; ++k)
  48. if (bitmap[k])
  49. return 0;
  50. if (bits % BITS_PER_LONG)
  51. if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
  52. return 0;
  53. return 1;
  54. }
  55. int __bitmap_full(const unsigned long *bitmap, int bits)
  56. {
  57. int k, lim = bits/BITS_PER_LONG;
  58. for (k = 0; k < lim; ++k)
  59. if (~bitmap[k])
  60. return 0;
  61. if (bits % BITS_PER_LONG)
  62. if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
  63. return 0;
  64. return 1;
  65. }
  66. int __bitmap_weight(const unsigned long *bitmap, int bits)
  67. {
  68. int k, w = 0, lim = bits/BITS_PER_LONG;
  69. for (k = 0; k < lim; k++)
  70. w += hweight_long(bitmap[k]);
  71. if (bits % BITS_PER_LONG)
  72. w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
  73. return w;
  74. }
  75. int __bitmap_equal(const unsigned long *bitmap1,
  76. const unsigned long *bitmap2, int bits)
  77. {
  78. int k, lim = bits/BITS_PER_LONG;
  79. for (k = 0; k < lim; ++k)
  80. if (bitmap1[k] != bitmap2[k])
  81. return 0;
  82. if (bits % BITS_PER_LONG)
  83. if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
  84. return 0;
  85. return 1;
  86. }
  87. void __bitmap_complement(unsigned long *dst, const unsigned long *src, int bits)
  88. {
  89. int k, lim = bits/BITS_PER_LONG;
  90. for (k = 0; k < lim; ++k)
  91. dst[k] = ~src[k];
  92. if (bits % BITS_PER_LONG)
  93. dst[k] = ~src[k] & BITMAP_LAST_WORD_MASK(bits);
  94. }
  95. /*
  96. * __bitmap_shift_right - logical right shift of the bits in a bitmap
  97. * @dst - destination bitmap
  98. * @src - source bitmap
  99. * @nbits - shift by this many bits
  100. * @bits - bitmap size, in bits
  101. *
  102. * Shifting right (dividing) means moving bits in the MS -> LS bit
  103. * direction. Zeros are fed into the vacated MS positions and the
  104. * LS bits shifted off the bottom are lost.
  105. */
  106. void __bitmap_shift_right(unsigned long *dst,
  107. const unsigned long *src, int shift, int bits)
  108. {
  109. int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
  110. int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
  111. unsigned long mask = (1UL << left) - 1;
  112. for (k = 0; off + k < lim; ++k) {
  113. unsigned long upper, lower;
  114. /*
  115. * If shift is not word aligned, take lower rem bits of
  116. * word above and make them the top rem bits of result.
  117. */
  118. if (!rem || off + k + 1 >= lim)
  119. upper = 0;
  120. else {
  121. upper = src[off + k + 1];
  122. if (off + k + 1 == lim - 1 && left)
  123. upper &= mask;
  124. }
  125. lower = src[off + k];
  126. if (left && off + k == lim - 1)
  127. lower &= mask;
  128. dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem;
  129. if (left && k == lim - 1)
  130. dst[k] &= mask;
  131. }
  132. if (off)
  133. memset(&dst[lim - off], 0, off*sizeof(unsigned long));
  134. }
  135. /*
  136. * __bitmap_shift_left - logical left shift of the bits in a bitmap
  137. * @dst - destination bitmap
  138. * @src - source bitmap
  139. * @nbits - shift by this many bits
  140. * @bits - bitmap size, in bits
  141. *
  142. * Shifting left (multiplying) means moving bits in the LS -> MS
  143. * direction. Zeros are fed into the vacated LS bit positions
  144. * and those MS bits shifted off the top are lost.
  145. */
  146. void __bitmap_shift_left(unsigned long *dst,
  147. const unsigned long *src, int shift, int bits)
  148. {
  149. int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
  150. int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
  151. for (k = lim - off - 1; k >= 0; --k) {
  152. unsigned long upper, lower;
  153. /*
  154. * If shift is not word aligned, take upper rem bits of
  155. * word below and make them the bottom rem bits of result.
  156. */
  157. if (rem && k > 0)
  158. lower = src[k - 1];
  159. else
  160. lower = 0;
  161. upper = src[k];
  162. if (left && k == lim - 1)
  163. upper &= (1UL << left) - 1;
  164. dst[k + off] = lower >> (BITS_PER_LONG - rem) | upper << rem;
  165. if (left && k + off == lim - 1)
  166. dst[k + off] &= (1UL << left) - 1;
  167. }
  168. if (off)
  169. memset(dst, 0, off*sizeof(unsigned long));
  170. }
  171. void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
  172. const unsigned long *bitmap2, int bits)
  173. {
  174. int k;
  175. int nr = BITS_TO_LONGS(bits);
  176. for (k = 0; k < nr; k++)
  177. dst[k] = bitmap1[k] & bitmap2[k];
  178. }
  179. void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
  180. const unsigned long *bitmap2, int bits)
  181. {
  182. int k;
  183. int nr = BITS_TO_LONGS(bits);
  184. for (k = 0; k < nr; k++)
  185. dst[k] = bitmap1[k] | bitmap2[k];
  186. }
  187. void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
  188. const unsigned long *bitmap2, int bits)
  189. {
  190. int k;
  191. int nr = BITS_TO_LONGS(bits);
  192. for (k = 0; k < nr; k++)
  193. dst[k] = bitmap1[k] ^ bitmap2[k];
  194. }
  195. void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
  196. const unsigned long *bitmap2, int bits)
  197. {
  198. int k;
  199. int nr = BITS_TO_LONGS(bits);
  200. for (k = 0; k < nr; k++)
  201. dst[k] = bitmap1[k] & ~bitmap2[k];
  202. }
  203. int __bitmap_intersects(const unsigned long *bitmap1,
  204. const unsigned long *bitmap2, int bits)
  205. {
  206. int k, lim = bits/BITS_PER_LONG;
  207. for (k = 0; k < lim; ++k)
  208. if (bitmap1[k] & bitmap2[k])
  209. return 1;
  210. if (bits % BITS_PER_LONG)
  211. if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
  212. return 1;
  213. return 0;
  214. }
  215. /*
  216. * Bitmap printing & parsing functions: first version by Bill Irwin,
  217. * second version by Paul Jackson, third by Joe Korty.
  218. */
  219. #define CHUNKSZ 32
  220. #define nbits_to_hold_value(val) fls(val)
  221. #define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
  222. #define BASEDEC 10 /* fancier cpuset lists input in decimal */
  223. /**
  224. * bitmap_scnprintf - convert bitmap to an ASCII hex string.
  225. * @buf: byte buffer into which string is placed
  226. * @buflen: reserved size of @buf, in bytes
  227. * @maskp: pointer to bitmap to convert
  228. * @nmaskbits: size of bitmap, in bits
  229. *
  230. * Exactly @nmaskbits bits are displayed. Hex digits are grouped into
  231. * comma-separated sets of eight digits per set.
  232. */
  233. int bitmap_scnprintf(char *buf, unsigned int buflen,
  234. const unsigned long *maskp, int nmaskbits)
  235. {
  236. int i, word, bit, len = 0;
  237. unsigned long val;
  238. const char *sep = "";
  239. int chunksz;
  240. uint32_t chunkmask;
  241. int first = 1;
  242. chunksz = nmaskbits & (CHUNKSZ - 1);
  243. if (chunksz == 0)
  244. chunksz = CHUNKSZ;
  245. i = ALIGN(nmaskbits, CHUNKSZ) - CHUNKSZ;
  246. for (; i >= 0; i -= CHUNKSZ) {
  247. chunkmask = ((1ULL << chunksz) - 1);
  248. word = i / BITS_PER_LONG;
  249. bit = i % BITS_PER_LONG;
  250. val = (maskp[word] >> bit) & chunkmask;
  251. if (val!=0 || !first || i==0) {
  252. len += snprintf(buf+len, buflen-len, "%s%0*lx", sep,
  253. (chunksz+3)/4, val);
  254. chunksz = CHUNKSZ;
  255. sep = ",";
  256. first = 0;
  257. }
  258. }
  259. return len;
  260. }
  261. /**
  262. * __bitmap_parse - convert an ASCII hex string into a bitmap.
  263. * @buf: pointer to buffer containing string.
  264. * @buflen: buffer size in bytes. If string is smaller than this
  265. * then it must be terminated with a \0.
  266. * @is_user: location of buffer, 0 indicates kernel space
  267. * @maskp: pointer to bitmap array that will contain result.
  268. * @nmaskbits: size of bitmap, in bits.
  269. *
  270. * Commas group hex digits into chunks. Each chunk defines exactly 32
  271. * bits of the resultant bitmask. No chunk may specify a value larger
  272. * than 32 bits (%-EOVERFLOW), and if a chunk specifies a smaller value
  273. * then leading 0-bits are prepended. %-EINVAL is returned for illegal
  274. * characters and for grouping errors such as "1,,5", ",44", "," and "".
  275. * Leading and trailing whitespace accepted, but not embedded whitespace.
  276. */
  277. int __bitmap_parse(const char *buf, unsigned int buflen,
  278. int is_user __attribute((unused)), unsigned long *maskp,
  279. int nmaskbits)
  280. {
  281. int c, old_c, totaldigits, ndigits, nchunks, nbits;
  282. uint32_t chunk;
  283. bitmap_zero(maskp, nmaskbits);
  284. nchunks = nbits = totaldigits = c = 0;
  285. do {
  286. chunk = ndigits = 0;
  287. /* Get the next chunk of the bitmap */
  288. while (buflen) {
  289. old_c = c;
  290. c = *buf++;
  291. buflen--;
  292. if (isspace(c))
  293. continue;
  294. /*
  295. * If the last character was a space and the current
  296. * character isn't '\0', we've got embedded whitespace.
  297. * This is a no-no, so throw an error.
  298. */
  299. if (totaldigits && c && isspace(old_c))
  300. return 0;
  301. /* A '\0' or a ',' signal the end of the chunk */
  302. if (c == '\0' || c == ',')
  303. break;
  304. if (!isxdigit(c))
  305. return -EINVAL;
  306. /*
  307. * Make sure there are at least 4 free bits in 'chunk'.
  308. * If not, this hexdigit will overflow 'chunk', so
  309. * throw an error.
  310. */
  311. if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1))
  312. return -EOVERFLOW;
  313. chunk = (chunk << 4) | unhex(c);
  314. ndigits++; totaldigits++;
  315. }
  316. if (ndigits == 0)
  317. return -EINVAL;
  318. if (nchunks == 0 && chunk == 0)
  319. continue;
  320. __bitmap_shift_left(maskp, maskp, CHUNKSZ, nmaskbits);
  321. *maskp |= chunk;
  322. nchunks++;
  323. nbits += (nchunks == 1) ? nbits_to_hold_value(chunk) : CHUNKSZ;
  324. if (nbits > nmaskbits)
  325. return -EOVERFLOW;
  326. } while (buflen && c == ',');
  327. return 0;
  328. }