[Sheepdog] expected bit size of __ffs

FUJITA Tomonori fujita.tomonori at lab.ntt.co.jp
Tue May 18 01:45:03 CEST 2010


On Mon, 17 May 2010 09:34:37 -0700
Steven Dake <sdake at redhat.com> wrote:

> Is __ffs expecting 64 bit parameters?  At line 18 of bitops.h, there is
> a >> by 32, which with a 32 bit parameter results in the value 0.

I think that 'if (BITS_PER_LONG == 64)' trick works on 32-bit archs.
 
#define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long))

static inline unsigned long __ffs(unsigned long word)
{
	int num = 0;

	if (BITS_PER_LONG == 64) {
		if ((word & 0xffffffff) == 0) {
			num += 32;
			word >>= 32;
		}
	}

So we don't hit "word >>= 32" on 32-bit archs. We get a warning like
"right shift count >= width of type" on this though.

The following patch kills the warning with gcc's built-in ffs().

=
From: FUJITA Tomonori <fujita.tomonori at lab.ntt.co.jp>
Subject: [PATCH] use gcc built-in ffs()

Signed-off-by: FUJITA Tomonori <fujita.tomonori at lab.ntt.co.jp>
---
 include/bitops.h |   34 +---------------------------------
 1 files changed, 1 insertions(+), 33 deletions(-)

diff --git a/include/bitops.h b/include/bitops.h
index 6c85d5e..0e0f402 100644
--- a/include/bitops.h
+++ b/include/bitops.h
@@ -3,43 +3,11 @@
 #define BITS_TO_LONGS(nr)	DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
 #define DECLARE_BITMAP(name,bits) \
 	unsigned long name[BITS_TO_LONGS(bits)]
-
 #define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long))
 
+#define __ffs(x)  (x ? __builtin_ffsl(x) - 1 : 0)
 #define ffz(x)  __ffs(~(x))
 
-static inline unsigned long __ffs(unsigned long word)
-{
-	int num = 0;
-
-	if (BITS_PER_LONG == 64) {
-		if ((word & 0xffffffff) == 0) {
-			num += 32;
-			word >>= 32;
-		}
-	}
-
-	if ((word & 0xffff) == 0) {
-		num += 16;
-		word >>= 16;
-	}
-	if ((word & 0xff) == 0) {
-		num += 8;
-		word >>= 8;
-	}
-	if ((word & 0xf) == 0) {
-		num += 4;
-		word >>= 4;
-	}
-	if ((word & 0x3) == 0) {
-		num += 2;
-		word >>= 2;
-	}
-	if ((word & 0x1) == 0)
-		num += 1;
-	return num;
-}
-
 #define BITOP_WORD(nr)		((nr) / BITS_PER_LONG)
 
 static inline unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
-- 
1.6.5




More information about the sheepdog mailing list