1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2639b9e34SAkinobu Mita #include <linux/export.h> 3639b9e34SAkinobu Mita #include <linux/bug.h> 4639b9e34SAkinobu Mita #include <linux/bitmap.h> 5639b9e34SAkinobu Mita 6639b9e34SAkinobu Mita /** 7639b9e34SAkinobu Mita * memweight - count the total number of bits set in memory area 8639b9e34SAkinobu Mita * @ptr: pointer to the start of the area 9639b9e34SAkinobu Mita * @bytes: the size of the area 10639b9e34SAkinobu Mita */ memweight(const void * ptr,size_t bytes)11639b9e34SAkinobu Mitasize_t memweight(const void *ptr, size_t bytes) 12639b9e34SAkinobu Mita { 13639b9e34SAkinobu Mita size_t ret = 0; 14639b9e34SAkinobu Mita size_t longs; 15639b9e34SAkinobu Mita const unsigned char *bitmap = ptr; 16639b9e34SAkinobu Mita 17639b9e34SAkinobu Mita for (; bytes > 0 && ((unsigned long)bitmap) % sizeof(long); 18639b9e34SAkinobu Mita bytes--, bitmap++) 19639b9e34SAkinobu Mita ret += hweight8(*bitmap); 20639b9e34SAkinobu Mita 21639b9e34SAkinobu Mita longs = bytes / sizeof(long); 22639b9e34SAkinobu Mita if (longs) { 23639b9e34SAkinobu Mita BUG_ON(longs >= INT_MAX / BITS_PER_LONG); 24639b9e34SAkinobu Mita ret += bitmap_weight((unsigned long *)bitmap, 25639b9e34SAkinobu Mita longs * BITS_PER_LONG); 26639b9e34SAkinobu Mita bytes -= longs * sizeof(long); 27639b9e34SAkinobu Mita bitmap += longs * sizeof(long); 28639b9e34SAkinobu Mita } 29639b9e34SAkinobu Mita /* 30639b9e34SAkinobu Mita * The reason that this last loop is distinct from the preceding 31639b9e34SAkinobu Mita * bitmap_weight() call is to compute 1-bits in the last region smaller 32639b9e34SAkinobu Mita * than sizeof(long) properly on big-endian systems. 33639b9e34SAkinobu Mita */ 34639b9e34SAkinobu Mita for (; bytes > 0; bytes--, bitmap++) 35639b9e34SAkinobu Mita ret += hweight8(*bitmap); 36639b9e34SAkinobu Mita 37639b9e34SAkinobu Mita return ret; 38639b9e34SAkinobu Mita } 39639b9e34SAkinobu Mita EXPORT_SYMBOL(memweight); 40