[CRIU] [PATCH 5/8] asm: convert the ARM implementation of bit operations to the reference
Alexander Kartashov
alekskartashov at parallels.com
Mon Mar 10 01:51:25 PDT 2014
The implementation of bit operations for ARM isn't actually
architecture-specific so it would rather be shared with
the upcoming port for AArch64 that won't provide optimized
implementation of bit operations.
Proposed-by: Christopher Covington <cov at codeaurora.org>
Signed-off-by: Alexander Kartashov <alekskartashov at parallels.com>
---
arch/arm/include/asm/bitops.h | 119 ++---------------------------------------
include/asm-generic/bitops.h | 116 +++++++++++++++++++++++++++++++++++++++
2 files changed, 121 insertions(+), 114 deletions(-)
create mode 100644 include/asm-generic/bitops.h
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index cf42235..5a75044 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -1,116 +1,7 @@
-#ifndef __CR_BITOPS_H__
-#define __CR_BITOPS_H__
+#ifndef __CR_ASM_BITOPS_H__
+#define __CR_ASM_BITOPS_H__
-#include "asm/bitsperlong.h"
+#include "compiler.h"
+#include "asm-generic/bitops.h"
-#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
-#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG)
-
-#define DECLARE_BITMAP(name, bits) \
- unsigned long name[BITS_TO_LONGS(bits)]
-
-#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
-/* Technically wrong, but this avoids compilation errors on some gcc
- versions. */
-#define BITOP_ADDR(x) "=m" (*(volatile long *) (x))
-#else
-#define BITOP_ADDR(x) "+m" (*(volatile long *) (x))
-#endif
-
-#define ADDR BITOP_ADDR(addr)
-
-static inline void set_bit(int nr, volatile unsigned long *addr) {
- addr += nr / BITS_PER_LONG;
- *addr |= (1 << (nr % BITS_PER_LONG));
-}
-
-static inline void change_bit(int nr, volatile unsigned long *addr)
-{
- addr += nr / BITS_PER_LONG;
- *addr ^= (1 << (nr % BITS_PER_LONG));
-}
-
-static inline int test_bit(int nr, volatile const unsigned long *addr)
-{
- addr += nr / BITS_PER_LONG;
- return (*addr & (1 << (nr % BITS_PER_LONG))) ? -1 : 0;
-}
-
-static inline void clear_bit(int nr, volatile unsigned long *addr)
-{
- addr += nr / BITS_PER_LONG;
- *addr &= ~(1 << (nr % BITS_PER_LONG));
-}
-
-/**
- * __ffs - find first set bit in word
- * @word: The word to search
- *
- * Undefined if no bit exists, so code should check against 0 first.
- */
-static inline unsigned long __ffs(unsigned long word)
-{
- int p = 0;
-
- for (; p < 8*sizeof(word); ++p) {
- if (word & 1) {
- break;
- }
-
- word >>= 1;
- }
-
- return p;
-}
-
-#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
-
-/*
- * Find the next set bit in a memory region.
- */
-static inline
-unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
- unsigned long offset)
-{
- const unsigned long *p = addr + BITOP_WORD(offset);
- unsigned long result = offset & ~(BITS_PER_LONG-1);
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset %= BITS_PER_LONG;
- if (offset) {
- tmp = *(p++);
- tmp &= (~0UL << offset);
- if (size < BITS_PER_LONG)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= BITS_PER_LONG;
- result += BITS_PER_LONG;
- }
- while (size & ~(BITS_PER_LONG-1)) {
- if ((tmp = *(p++)))
- goto found_middle;
- result += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- }
- if (!size)
- return result;
- tmp = *p;
-
-found_first:
- tmp &= (~0UL >> (BITS_PER_LONG - size));
- if (tmp == 0UL) /* Are any bits set? */
- return result + size; /* Nope. */
-found_middle:
- return result + __ffs(tmp);
-}
-
-#define for_each_bit(i, bitmask) \
- for (i = find_next_bit(bitmask, sizeof(bitmask), 0); \
- i < sizeof(bitmask); \
- i = find_next_bit(bitmask, sizeof(bitmask), i + 1))
-
-#endif /* __CR_BITOPS_H__ */
+#endif /* __CR_ASM_BITOPS_H__ */
diff --git a/include/asm-generic/bitops.h b/include/asm-generic/bitops.h
new file mode 100644
index 0000000..6620ef3
--- /dev/null
+++ b/include/asm-generic/bitops.h
@@ -0,0 +1,116 @@
+#ifndef __CR_GENERIC_BITOPS_H__
+#define __CR_GENERIC_BITOPS_H__
+
+#include "asm/bitsperlong.h"
+
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG)
+
+#define DECLARE_BITMAP(name, bits) \
+ unsigned long name[BITS_TO_LONGS(bits)]
+
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
+/* Technically wrong, but this avoids compilation errors on some gcc
+ versions. */
+#define BITOP_ADDR(x) "=m" (*(volatile long *) (x))
+#else
+#define BITOP_ADDR(x) "+m" (*(volatile long *) (x))
+#endif
+
+#define ADDR BITOP_ADDR(addr)
+
+static inline void set_bit(int nr, volatile unsigned long *addr) {
+ addr += nr / BITS_PER_LONG;
+ *addr |= (1 << (nr % BITS_PER_LONG));
+}
+
+static inline void change_bit(int nr, volatile unsigned long *addr)
+{
+ addr += nr / BITS_PER_LONG;
+ *addr ^= (1 << (nr % BITS_PER_LONG));
+}
+
+static inline int test_bit(int nr, volatile const unsigned long *addr)
+{
+ addr += nr / BITS_PER_LONG;
+ return (*addr & (1 << (nr % BITS_PER_LONG))) ? -1 : 0;
+}
+
+static inline void clear_bit(int nr, volatile unsigned long *addr)
+{
+ addr += nr / BITS_PER_LONG;
+ *addr &= ~(1 << (nr % BITS_PER_LONG));
+}
+
+/**
+ * __ffs - find first set bit in word
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+ int p = 0;
+
+ for (; p < 8*sizeof(word); ++p) {
+ if (word & 1) {
+ break;
+ }
+
+ word >>= 1;
+ }
+
+ return p;
+}
+
+#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
+
+/*
+ * Find the next set bit in a memory region.
+ */
+static inline
+unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
+ unsigned long offset)
+{
+ const unsigned long *p = addr + BITOP_WORD(offset);
+ unsigned long result = offset & ~(BITS_PER_LONG-1);
+ unsigned long tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset %= BITS_PER_LONG;
+ if (offset) {
+ tmp = *(p++);
+ tmp &= (~0UL << offset);
+ if (size < BITS_PER_LONG)
+ goto found_first;
+ if (tmp)
+ goto found_middle;
+ size -= BITS_PER_LONG;
+ result += BITS_PER_LONG;
+ }
+ while (size & ~(BITS_PER_LONG-1)) {
+ if ((tmp = *(p++)))
+ goto found_middle;
+ result += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
+ }
+ if (!size)
+ return result;
+ tmp = *p;
+
+found_first:
+ tmp &= (~0UL >> (BITS_PER_LONG - size));
+ if (tmp == 0UL) /* Are any bits set? */
+ return result + size; /* Nope. */
+found_middle:
+ return result + __ffs(tmp);
+}
+
+#define for_each_bit(i, bitmask) \
+ for (i = find_next_bit(bitmask, sizeof(bitmask), 0); \
+ i < sizeof(bitmask); \
+ i = find_next_bit(bitmask, sizeof(bitmask), i + 1))
+
+#endif /* __CR_GENERIC_BITOPS_H__ */
--
1.7.9.5
More information about the CRIU
mailing list