diff options
Diffstat (limited to 'include/asm-generic/bitops')
| -rw-r--r-- | include/asm-generic/bitops/atomic.h | 4 | ||||
| -rw-r--r-- | include/asm-generic/bitops/builtin-__ffs.h | 15 | ||||
| -rw-r--r-- | include/asm-generic/bitops/builtin-__fls.h | 15 | ||||
| -rw-r--r-- | include/asm-generic/bitops/builtin-ffs.h | 17 | ||||
| -rw-r--r-- | include/asm-generic/bitops/builtin-fls.h | 16 | ||||
| -rw-r--r-- | include/asm-generic/bitops/const_hweight.h | 17 | ||||
| -rw-r--r-- | include/asm-generic/bitops/count_zeros.h | 57 | ||||
| -rw-r--r-- | include/asm-generic/bitops/find.h | 12 | ||||
| -rw-r--r-- | include/asm-generic/bitops/le.h | 10 | ||||
| -rw-r--r-- | include/asm-generic/bitops/lock.h | 2 |
10 files changed, 152 insertions, 13 deletions
diff --git a/include/asm-generic/bitops/atomic.h b/include/asm-generic/bitops/atomic.h index ecc44a8e2b4..49673510b48 100644 --- a/include/asm-generic/bitops/atomic.h +++ b/include/asm-generic/bitops/atomic.h @@ -2,7 +2,7 @@ #define _ASM_GENERIC_BITOPS_ATOMIC_H_ #include <asm/types.h> -#include <asm/system.h> +#include <linux/irqflags.h> #ifdef CONFIG_SMP #include <asm/spinlock.h> @@ -80,7 +80,7 @@ static inline void set_bit(int nr, volatile unsigned long *addr) * * clear_bit() is atomic and may not be reordered. However, it does * not contain a memory barrier, so if it is used for locking purposes, - * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * you should call smp_mb__before_atomic() and/or smp_mb__after_atomic() * in order to ensure changes are visible on other processors. */ static inline void clear_bit(int nr, volatile unsigned long *addr) diff --git a/include/asm-generic/bitops/builtin-__ffs.h b/include/asm-generic/bitops/builtin-__ffs.h new file mode 100644 index 00000000000..90041e3a41f --- /dev/null +++ b/include/asm-generic/bitops/builtin-__ffs.h @@ -0,0 +1,15 @@ +#ifndef _ASM_GENERIC_BITOPS_BUILTIN___FFS_H_ +#define _ASM_GENERIC_BITOPS_BUILTIN___FFS_H_ + +/** + * __ffs - find first bit in word. + * @word: The word to search + * + * Undefined if no bit exists, so code should check against 0 first. + */ +static __always_inline unsigned long __ffs(unsigned long word) +{ + return __builtin_ctzl(word); +} + +#endif diff --git a/include/asm-generic/bitops/builtin-__fls.h b/include/asm-generic/bitops/builtin-__fls.h new file mode 100644 index 00000000000..0248f386635 --- /dev/null +++ b/include/asm-generic/bitops/builtin-__fls.h @@ -0,0 +1,15 @@ +#ifndef _ASM_GENERIC_BITOPS_BUILTIN___FLS_H_ +#define _ASM_GENERIC_BITOPS_BUILTIN___FLS_H_ + +/** + * __fls - find last (most-significant) set bit in a long word + * @word: the word to search + * + * Undefined if no set bit exists, so code should check against 0 first. + */ +static __always_inline unsigned long __fls(unsigned long word) +{ + return (sizeof(word) * 8) - 1 - __builtin_clzl(word); +} + +#endif diff --git a/include/asm-generic/bitops/builtin-ffs.h b/include/asm-generic/bitops/builtin-ffs.h new file mode 100644 index 00000000000..064825829e1 --- /dev/null +++ b/include/asm-generic/bitops/builtin-ffs.h @@ -0,0 +1,17 @@ +#ifndef _ASM_GENERIC_BITOPS_BUILTIN_FFS_H_ +#define _ASM_GENERIC_BITOPS_BUILTIN_FFS_H_ + +/** + * ffs - find first bit set + * @x: the word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +static __always_inline int ffs(int x) +{ + return __builtin_ffs(x); +} + +#endif diff --git a/include/asm-generic/bitops/builtin-fls.h b/include/asm-generic/bitops/builtin-fls.h new file mode 100644 index 00000000000..eda652d0ac7 --- /dev/null +++ b/include/asm-generic/bitops/builtin-fls.h @@ -0,0 +1,16 @@ +#ifndef _ASM_GENERIC_BITOPS_BUILTIN_FLS_H_ +#define _ASM_GENERIC_BITOPS_BUILTIN_FLS_H_ + +/** + * fls - find last (most-significant) bit set + * @x: the word to search + * + * This is defined the same way as ffs. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ +static __always_inline int fls(int x) +{ + return x ? sizeof(x) * 8 - __builtin_clz(x) : 0; +} + +#endif diff --git a/include/asm-generic/bitops/const_hweight.h b/include/asm-generic/bitops/const_hweight.h index fa2a50b7ee6..0a7e0662347 100644 --- a/include/asm-generic/bitops/const_hweight.h +++ b/include/asm-generic/bitops/const_hweight.h @@ -5,14 +5,15 @@ * Compile time versions of __arch_hweightN() */ #define __const_hweight8(w) \ - ( (!!((w) & (1ULL << 0))) + \ - (!!((w) & (1ULL << 1))) + \ - (!!((w) & (1ULL << 2))) + \ - (!!((w) & (1ULL << 3))) + \ - (!!((w) & (1ULL << 4))) + \ - (!!((w) & (1ULL << 5))) + \ - (!!((w) & (1ULL << 6))) + \ - (!!((w) & (1ULL << 7))) ) + ((unsigned int) \ + ((!!((w) & (1ULL << 0))) + \ + (!!((w) & (1ULL << 1))) + \ + (!!((w) & (1ULL << 2))) + \ + (!!((w) & (1ULL << 3))) + \ + (!!((w) & (1ULL << 4))) + \ + (!!((w) & (1ULL << 5))) + \ + (!!((w) & (1ULL << 6))) + \ + (!!((w) & (1ULL << 7))))) #define __const_hweight16(w) (__const_hweight8(w) + __const_hweight8((w) >> 8 )) #define __const_hweight32(w) (__const_hweight16(w) + __const_hweight16((w) >> 16)) diff --git a/include/asm-generic/bitops/count_zeros.h b/include/asm-generic/bitops/count_zeros.h new file mode 100644 index 00000000000..97520d21fe6 --- /dev/null +++ b/include/asm-generic/bitops/count_zeros.h @@ -0,0 +1,57 @@ +/* Count leading and trailing zeros functions + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ +#define _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ + +#include <asm/bitops.h> + +/** + * count_leading_zeros - Count the number of zeros from the MSB back + * @x: The value + * + * Count the number of leading zeros from the MSB going towards the LSB in @x. + * + * If the MSB of @x is set, the result is 0. + * If only the LSB of @x is set, then the result is BITS_PER_LONG-1. + * If @x is 0 then the result is COUNT_LEADING_ZEROS_0. + */ +static inline int count_leading_zeros(unsigned long x) +{ + if (sizeof(x) == 4) + return BITS_PER_LONG - fls(x); + else + return BITS_PER_LONG - fls64(x); +} + +#define COUNT_LEADING_ZEROS_0 BITS_PER_LONG + +/** + * count_trailing_zeros - Count the number of zeros from the LSB forwards + * @x: The value + * + * Count the number of trailing zeros from the LSB going towards the MSB in @x. + * + * If the LSB of @x is set, the result is 0. + * If only the MSB of @x is set, then the result is BITS_PER_LONG-1. + * If @x is 0 then the result is COUNT_TRAILING_ZEROS_0. + */ +static inline int count_trailing_zeros(unsigned long x) +{ +#define COUNT_TRAILING_ZEROS_0 (-1) + + if (sizeof(x) == 4) + return ffs(x); + else + return (x != 0) ? __ffs(x) : COUNT_TRAILING_ZEROS_0; +} + +#endif /* _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ */ diff --git a/include/asm-generic/bitops/find.h b/include/asm-generic/bitops/find.h index 71c778033f5..998d4d544f1 100644 --- a/include/asm-generic/bitops/find.h +++ b/include/asm-generic/bitops/find.h @@ -7,6 +7,9 @@ * @addr: The address to base the search on * @offset: The bitnumber to start searching at * @size: The bitmap size in bits + * + * Returns the bit number for the next set bit + * If no bits are set, returns @size. */ extern unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset); @@ -18,6 +21,9 @@ extern unsigned long find_next_bit(const unsigned long *addr, unsigned long * @addr: The address to base the search on * @offset: The bitnumber to start searching at * @size: The bitmap size in bits + * + * Returns the bit number of the next zero bit + * If no bits are zero, returns @size. */ extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset); @@ -28,9 +34,10 @@ extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned /** * find_first_bit - find the first set bit in a memory region * @addr: The address to start the search at - * @size: The maximum size to search + * @size: The maximum number of bits to search * * Returns the bit number of the first set bit. + * If no bits are set, returns @size. */ extern unsigned long find_first_bit(const unsigned long *addr, unsigned long size); @@ -38,9 +45,10 @@ extern unsigned long find_first_bit(const unsigned long *addr, /** * find_first_zero_bit - find the first cleared bit in a memory region * @addr: The address to start the search at - * @size: The maximum size to search + * @size: The maximum number of bits to search * * Returns the bit number of the first cleared bit. + * If no bits are zero, returns @size. */ extern unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size); diff --git a/include/asm-generic/bitops/le.h b/include/asm-generic/bitops/le.h index f95c663a6a4..61731543c00 100644 --- a/include/asm-generic/bitops/le.h +++ b/include/asm-generic/bitops/le.h @@ -54,6 +54,16 @@ static inline int test_bit_le(int nr, const void *addr) return test_bit(nr ^ BITOP_LE_SWIZZLE, addr); } +static inline void set_bit_le(int nr, void *addr) +{ + set_bit(nr ^ BITOP_LE_SWIZZLE, addr); +} + +static inline void clear_bit_le(int nr, void *addr) +{ + clear_bit(nr ^ BITOP_LE_SWIZZLE, addr); +} + static inline void __set_bit_le(int nr, void *addr) { __set_bit(nr ^ BITOP_LE_SWIZZLE, addr); diff --git a/include/asm-generic/bitops/lock.h b/include/asm-generic/bitops/lock.h index 308a9e22c80..c30266e9480 100644 --- a/include/asm-generic/bitops/lock.h +++ b/include/asm-generic/bitops/lock.h @@ -20,7 +20,7 @@ */ #define clear_bit_unlock(nr, addr) \ do { \ - smp_mb__before_clear_bit(); \ + smp_mb__before_atomic(); \ clear_bit(nr, addr); \ } while (0) |
