b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 2) #include <linux/export.h>
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 3) #include <linux/bug.h>
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 4) #include <linux/bitmap.h>
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 5)
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 6) /**
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 7) * memweight - count the total number of bits set in memory area
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 8) * @ptr: pointer to the start of the area
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 9) * @bytes: the size of the area
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 10) */
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 11) size_t memweight(const void *ptr, size_t bytes)
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 12) {
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 13) size_t ret = 0;
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 14) size_t longs;
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 15) const unsigned char *bitmap = ptr;
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 16)
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 17) for (; bytes > 0 && ((unsigned long)bitmap) % sizeof(long);
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 18) bytes--, bitmap++)
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 19) ret += hweight8(*bitmap);
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 20)
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 21) longs = bytes / sizeof(long);
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 22) if (longs) {
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 23) BUG_ON(longs >= INT_MAX / BITS_PER_LONG);
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 24) ret += bitmap_weight((unsigned long *)bitmap,
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 25) longs * BITS_PER_LONG);
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 26) bytes -= longs * sizeof(long);
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 27) bitmap += longs * sizeof(long);
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 28) }
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 29) /*
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 30) * The reason that this last loop is distinct from the preceding
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 31) * bitmap_weight() call is to compute 1-bits in the last region smaller
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 32) * than sizeof(long) properly on big-endian systems.
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 33) */
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 34) for (; bytes > 0; bytes--, bitmap++)
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 35) ret += hweight8(*bitmap);
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 36)
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 37) return ret;
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 38) }
639b9e34f15e4 (Akinobu Mita 2012-07-30 14:40:55 -0700 39) EXPORT_SYMBOL(memweight);