xen/bitops: Introduce a multiple_bits_set() helper

This will be used to simplify real logic in the following patch.  Add compile
and boot time testing as with other bitops.

Because the expression is so simple, implement it as a function-like macro
which is generic on the type of it's argument, rather than having multiple
variants.

Testing function-like macros needs a minor adjustments to the infrastructure
in xen/self-tests.h to avoid bracketing the fn parameter.  The utility of this
outweighs the associated risks.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Andrew Cooper committed 2024-09-03 20:22:18 +01:00
1 parent 11aa8f5ff8
commit bd1664db7b
3 files changed
+41 -2

No files matched your search

+23
View File
@@ -112,9 +112,32 @@ static void __init test_for_each_set_bit(void)
panic("for_each_set_bit(uint64) expected %#"PRIx64", got %#"PRIx64"\n", ull, ull_res);
}
static void __init test_multiple_bits_set(void)
{
/*
* multiple_bits_set() is generic on the type of it's parameter, as the
* internal expression is so simple.
*/
CHECK(multiple_bits_set, 0, false);
CHECK(multiple_bits_set, 1, false);
CHECK(multiple_bits_set, 2, false);
CHECK(multiple_bits_set, 3, true);
CHECK(multiple_bits_set, 1 | (1UL << (BITS_PER_LONG - 1)), true);
#if BITS_PER_LONG > 32
CHECK(multiple_bits_set, 1 | (1UL << 32), true);
#endif
CHECK(multiple_bits_set, 0x8000000000000001ULL, true);
CHECK(multiple_bits_set, 0xc000000000000000ULL, true);
}
static void __init __constructor test_bitops(void)
{
test_ffs();
test_fls();
test_for_each_set_bit();
test_multiple_bits_set();
}
+10
View File
@@ -296,6 +296,16 @@ static always_inline attr_const unsigned int fls64(uint64_t x)
__v && ((iter) = ffs_g(__v) - 1, true); \
__v &= __v - 1 )
/*
* Calculate if a value has two or more bits set. Always use this in
* preference to an expression of the form 'hweight(x) > 1'.
*/
#define multiple_bits_set(x) \
({ \
typeof(x) _v = (x); \
(_v & (_v - 1)) != 0; \
})
/* --------------------- Please tidy below here --------------------- */
#ifndef find_next_bit
+8 -2
View File
@@ -15,11 +15,14 @@
*
* Clang < 8 can't fold constants through static inlines, causing this to
* fail. Simply skip it for incredibly old compilers.
*
* N.B. fn is intentionally not bracketed to allow us to test function-like
* macros too.
*/
#if !defined(CONFIG_CC_IS_CLANG) || CONFIG_CLANG_VERSION >= 80000
#define COMPILE_CHECK(fn, val, res) \
do { \
typeof((fn)(val)) real = (fn)(val); \
typeof(fn(val)) real = fn(val); \
\
if ( !__builtin_constant_p(real) ) \
BUILD_ERROR("'" STR(fn(val)) "' not compile-time constant"); \
@@ -34,10 +37,13 @@
* Check that Xen's runtime logic for fn(val) gives the expected answer. This
* requires using HIDE() to prevent the optimiser from collapsing the logic
* into a constant.
*
* N.B. fn is intentionally not bracketed to allow us to test function-like
* macros too.
*/
#define RUNTIME_CHECK(fn, val, res) \
do { \
typeof((fn)(val)) real = (fn)(HIDE(val)); \
typeof(fn(val)) real = fn(HIDE(val)); \
\
if ( real != (res) ) \
panic("%s: %s(%s) expected %u, got %u\n", \
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.