aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/Kconfig3
-rw-r--r--include/asm-x86/bitops_32.h2
-rw-r--r--include/linux/bitops.h34
-rw-r--r--lib/Makefile1
-rw-r--r--lib/find_next_bit.c58
5 files changed, 98 insertions, 0 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5639de47ed45..1a69b68ff6cc 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -77,6 +77,9 @@ config GENERIC_BUG
77 def_bool y 77 def_bool y
78 depends on BUG 78 depends on BUG
79 79
80config GENERIC_FIND_FIRST_BIT
81 def_bool X86_32
82
80config GENERIC_FIND_NEXT_BIT 83config GENERIC_FIND_NEXT_BIT
81 def_bool y 84 def_bool y
82 85
diff --git a/include/asm-x86/bitops_32.h b/include/asm-x86/bitops_32.h
index 3ed64b21b765..ba2c0defafa8 100644
--- a/include/asm-x86/bitops_32.h
+++ b/include/asm-x86/bitops_32.h
@@ -5,6 +5,7 @@
5 * Copyright 1992, Linus Torvalds. 5 * Copyright 1992, Linus Torvalds.
6 */ 6 */
7 7
8#ifndef CONFIG_GENERIC_FIND_FIRST_BIT
8/** 9/**
9 * find_first_zero_bit - find the first zero bit in a memory region 10 * find_first_zero_bit - find the first zero bit in a memory region
10 * @addr: The address to start the search at 11 * @addr: The address to start the search at
@@ -59,6 +60,7 @@ static inline unsigned find_first_bit(const unsigned long *addr, unsigned size)
59 } 60 }
60 return x; 61 return x;
61} 62}
63#endif
62 64
63#ifdef __KERNEL__ 65#ifdef __KERNEL__
64 66
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 3865f2c93bd8..355d67ba3bdc 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -113,6 +113,40 @@ static inline unsigned fls_long(unsigned long l)
113} 113}
114 114
115#ifdef __KERNEL__ 115#ifdef __KERNEL__
116#ifdef CONFIG_GENERIC_FIND_FIRST_BIT
117extern unsigned long __find_first_bit(const unsigned long *addr,
118 unsigned long size);
119
120/**
121 * find_first_bit - find the first set bit in a memory region
122 * @addr: The address to start the search at
123 * @size: The maximum size to search
124 *
125 * Returns the bit number of the first set bit.
126 */
127static __always_inline unsigned long
128find_first_bit(const unsigned long *addr, unsigned long size)
129{
130 return __find_first_bit(addr, size);
131}
132
133extern unsigned long __find_first_zero_bit(const unsigned long *addr,
134 unsigned long size);
135
136/**
137 * find_first_zero_bit - find the first cleared bit in a memory region
138 * @addr: The address to start the search at
139 * @size: The maximum size to search
140 *
141 * Returns the bit number of the first cleared bit.
142 */
143static __always_inline unsigned long
144find_first_zero_bit(const unsigned long *addr, unsigned long size)
145{
146 return __find_first_zero_bit(addr, size);
147}
148#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
149
116#ifdef CONFIG_GENERIC_FIND_NEXT_BIT 150#ifdef CONFIG_GENERIC_FIND_NEXT_BIT
117extern unsigned long __find_next_bit(const unsigned long *addr, 151extern unsigned long __find_next_bit(const unsigned long *addr,
118 unsigned long size, unsigned long offset); 152 unsigned long size, unsigned long offset);
diff --git a/lib/Makefile b/lib/Makefile
index bf8000fc7d48..2d7001b7f5a4 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
29obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o 29obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
30lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o 30lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
31lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o 31lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
32lib-$(CONFIG_GENERIC_FIND_FIRST_BIT) += find_next_bit.o
32lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o 33lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
33obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o 34obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
34obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o 35obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c
index ce94c4c92d10..d3f5784807b4 100644
--- a/lib/find_next_bit.c
+++ b/lib/find_next_bit.c
@@ -16,6 +16,7 @@
16 16
17#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) 17#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
18 18
19#ifdef CONFIG_GENERIC_FIND_NEXT_BIT
19/* 20/*
20 * Find the next set bit in a memory region. 21 * Find the next set bit in a memory region.
21 */ 22 */
@@ -102,6 +103,63 @@ found_middle:
102 return result + ffz(tmp); 103 return result + ffz(tmp);
103} 104}
104EXPORT_SYMBOL(__find_next_zero_bit); 105EXPORT_SYMBOL(__find_next_zero_bit);
106#endif /* CONFIG_GENERIC_FIND_NEXT_BIT */
107
108#ifdef CONFIG_GENERIC_FIND_FIRST_BIT
109/*
110 * Find the first set bit in a memory region.
111 */
112unsigned long __find_first_bit(const unsigned long *addr,
113 unsigned long size)
114{
115 const unsigned long *p = addr;
116 unsigned long result = 0;
117 unsigned long tmp;
118
119 while (size & ~(BITS_PER_LONG-1)) {
120 if ((tmp = *(p++)))
121 goto found;
122 result += BITS_PER_LONG;
123 size -= BITS_PER_LONG;
124 }
125 if (!size)
126 return result;
127
128 tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
129 if (tmp == 0UL) /* Are any bits set? */
130 return result + size; /* Nope. */
131found:
132 return result + __ffs(tmp);
133}
134EXPORT_SYMBOL(__find_first_bit);
135
136/*
137 * Find the first cleared bit in a memory region.
138 */
139unsigned long __find_first_zero_bit(const unsigned long *addr,
140 unsigned long size)
141{
142 const unsigned long *p = addr;
143 unsigned long result = 0;
144 unsigned long tmp;
145
146 while (size & ~(BITS_PER_LONG-1)) {
147 if (~(tmp = *(p++)))
148 goto found;
149 result += BITS_PER_LONG;
150 size -= BITS_PER_LONG;
151 }
152 if (!size)
153 return result;
154
155 tmp = (*p) | (~0UL << size);
156 if (tmp == ~0UL) /* Are any bits zero? */
157 return result + size; /* Nope. */
158found:
159 return result + ffz(tmp);
160}
161EXPORT_SYMBOL(__find_first_zero_bit);
162#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
105 163
106#ifdef __BIG_ENDIAN 164#ifdef __BIG_ENDIAN
107 165