Z_POW2_CEIL: simplify implementation
Avoid potentially calling __builtin_clz() twice with non-constant values. Also add a test for it. Clang produces false positive vla warnings so disable them. GCC will spot real vla's already. Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
parent
92bc3e47c0
commit
f00573555b
|
@ -381,6 +381,9 @@ if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
|||
if(NOT ${ZEPHYR_TOOLCHAIN_VARIANT} STREQUAL "xcc")
|
||||
zephyr_cc_option(-fno-defer-pop)
|
||||
endif()
|
||||
else()
|
||||
# Clang produces false positive vla warnings
|
||||
zephyr_cc_option(-Wno-vla)
|
||||
endif()
|
||||
|
||||
zephyr_cc_option_ifdef(CONFIG_STACK_USAGE -fstack-usage)
|
||||
|
|
|
@ -595,15 +595,8 @@ do { \
|
|||
* @param x Nonzero unsigned long value
|
||||
* @return X rounded up to the next power of two
|
||||
*/
|
||||
#ifdef CONFIG_64BIT
|
||||
#define Z_POW2_CEIL(x) ((1UL << (63U - __builtin_clzl(x))) < x ? \
|
||||
1UL << (63U - __builtin_clzl(x) + 1U) : \
|
||||
1UL << (63U - __builtin_clzl(x)))
|
||||
#else
|
||||
#define Z_POW2_CEIL(x) ((1UL << (31U - __builtin_clz(x))) < x ? \
|
||||
1UL << (31U - __builtin_clz(x) + 1U) : \
|
||||
1UL << (31U - __builtin_clz(x)))
|
||||
#endif
|
||||
#define Z_POW2_CEIL(x) \
|
||||
((x) <= 2UL ? (x) : (1UL << (8 * sizeof(long) - __builtin_clzl((x) - 1))))
|
||||
|
||||
/**
|
||||
* @brief Check whether or not a value is a power of 2
|
||||
|
|
|
@ -22,7 +22,8 @@ target_sources(app PRIVATE
|
|||
src/main.c
|
||||
src/timeout_order.c
|
||||
src/multilib.c
|
||||
src/errno.c
|
||||
src/boot_delay.c
|
||||
src/irq_offload.c
|
||||
src/errno.c
|
||||
src/boot_delay.c
|
||||
src/irq_offload.c
|
||||
src/pow2.c
|
||||
)
|
||||
|
|
|
@ -52,6 +52,7 @@ extern void test_bitarray_alloc_free(void);
|
|||
extern void test_bitarray_region_set_clear(void);
|
||||
extern void test_nop(void);
|
||||
extern void test_ffs(void);
|
||||
extern void test_pow2_ceil(void);
|
||||
|
||||
/**
|
||||
* @defgroup kernel_common_tests Common Tests
|
||||
|
@ -168,7 +169,8 @@ void test_main(void)
|
|||
ztest_unit_test(test_ms_time_duration),
|
||||
ztest_unit_test(test_bounds_check_mitigation),
|
||||
ztest_unit_test(test_nop),
|
||||
ztest_unit_test(test_ffs)
|
||||
ztest_unit_test(test_ffs),
|
||||
ztest_unit_test(test_pow2_ceil)
|
||||
);
|
||||
|
||||
ztest_run_test_suite(common);
|
||||
|
|
77
tests/kernel/common/src/pow2.c
Normal file
77
tests/kernel/common/src/pow2.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2022 BayLibre SAS
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <ztest.h>
|
||||
#include <zephyr.h>
|
||||
|
||||
/**
|
||||
* @brief Test the Z_POW2_CEIL() macro
|
||||
*
|
||||
* @defgroup test_pow2_ceil Z_POW2_CEIL() tests
|
||||
*
|
||||
* @ingroup all_tests
|
||||
*
|
||||
* @{
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Verify compile-time constant results
|
||||
*
|
||||
* @ingroup test_pow2_ceil
|
||||
*
|
||||
* @details Check if static array allocations are sized as expected.
|
||||
*/
|
||||
|
||||
char static_array1[Z_POW2_CEIL(1)];
|
||||
char static_array2[Z_POW2_CEIL(2)];
|
||||
char static_array3[Z_POW2_CEIL(3)];
|
||||
char static_array4[Z_POW2_CEIL(4)];
|
||||
char static_array5[Z_POW2_CEIL(5)];
|
||||
char static_array7[Z_POW2_CEIL(7)];
|
||||
char static_array8[Z_POW2_CEIL(8)];
|
||||
char static_array9[Z_POW2_CEIL(9)];
|
||||
|
||||
BUILD_ASSERT(sizeof(static_array1) == 1);
|
||||
BUILD_ASSERT(sizeof(static_array2) == 2);
|
||||
BUILD_ASSERT(sizeof(static_array3) == 4);
|
||||
BUILD_ASSERT(sizeof(static_array4) == 4);
|
||||
BUILD_ASSERT(sizeof(static_array5) == 8);
|
||||
BUILD_ASSERT(sizeof(static_array7) == 8);
|
||||
BUILD_ASSERT(sizeof(static_array8) == 8);
|
||||
BUILD_ASSERT(sizeof(static_array9) == 16);
|
||||
|
||||
/**
|
||||
* @brief Verify run-time non-constant results
|
||||
*
|
||||
* @ingroup test_pow2_ceil
|
||||
*
|
||||
* @details Check if run-time non-constant results are as expected.
|
||||
* Use a volatile variable to prevent compiler optimizations.
|
||||
*/
|
||||
|
||||
static void test_pow2_ceil_x(unsigned long test_value,
|
||||
unsigned long expected_result)
|
||||
{
|
||||
volatile unsigned int x = test_value;
|
||||
unsigned int result = Z_POW2_CEIL(x);
|
||||
|
||||
zassert_equal(result, expected_result,
|
||||
"ZPOW2_CEIL(%lu) returned %lu, expected %lu",
|
||||
test_value, result, expected_result);
|
||||
}
|
||||
|
||||
void test_pow2_ceil(void)
|
||||
{
|
||||
test_pow2_ceil_x(1, 1);
|
||||
test_pow2_ceil_x(2, 2);
|
||||
test_pow2_ceil_x(3, 4);
|
||||
test_pow2_ceil_x(4, 4);
|
||||
test_pow2_ceil_x(5, 8);
|
||||
test_pow2_ceil_x(7, 8);
|
||||
test_pow2_ceil_x(8, 8);
|
||||
test_pow2_ceil_x(9, 16);
|
||||
}
|
Loading…
Reference in a new issue