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