diff --git a/bootstrap.conf b/bootstrap.conf index d24a71432c..e7ea9c9bb5 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -35,6 +35,7 @@ clock-time close connect configmake +count-leading-zeros count-one-bits crypto/md5 crypto/sha256 diff --git a/src/internal.h b/src/internal.h index f6a88b2c96..30445c1267 100644 --- a/src/internal.h +++ b/src/internal.h @@ -62,6 +62,7 @@ # include "c-strcase.h" # include "ignore-value.h" +# include "count-leading-zeros.h" /* On architectures which lack these limits, define them (ie. Cygwin). * Note that the libvirt code should be robust enough to handle the @@ -382,6 +383,12 @@ /* round up value to the closest multiple of size */ # define VIR_ROUND_UP(value, size) (VIR_DIV_UP(value, size) * (size)) +/* Round up to the next closest power of 2. It will return rounded number or 0 + * for 0 or number more than 2^31 (for 32bit unsigned int). */ +# define VIR_ROUND_UP_POWER_OF_TWO(value) \ + ((value) > 0 && (value) <= 1U << (sizeof(unsigned int) * 8 - 1) ? \ + 1U << (sizeof(unsigned int) * 8 - count_leading_zeros((value) - 1)) : 0) + /* Specific error values for use in forwarding programs such as * virt-login-shell; these values match what GNU env does. */ diff --git a/tests/utiltest.c b/tests/utiltest.c index 8950cf2f30..2dbd291290 100644 --- a/tests/utiltest.c +++ b/tests/utiltest.c @@ -143,6 +143,44 @@ testParseVersionString(const void *data ATTRIBUTE_UNUSED) +struct testRoundData { + unsigned int input; + unsigned int output; +}; + +static struct testRoundData roundData[] = { + { 0, 0 }, + { 1, 1 }, + { 1000, 1024 }, + { 1024, 1024 }, + { 1025, 2048 }, + { UINT_MAX, 0 }, +}; + +static int +testRoundValueToPowerOfTwo(const void *data ATTRIBUTE_UNUSED) +{ + unsigned int result; + size_t i; + + for (i = 0; i < ARRAY_CARDINALITY(roundData); i++) { + result = VIR_ROUND_UP_POWER_OF_TWO(roundData[i].input); + if (roundData[i].output != result) { + if (virTestGetDebug() > 0) { + fprintf(stderr, "\nInput number [%u]\n", roundData[i].input); + fprintf(stderr, "Expected number [%u]\n", roundData[i].output); + fprintf(stderr, "Actual number [%u]\n", result); + } + + return -1; + } + } + + return 0; +} + + + static int mymain(void) @@ -162,6 +200,7 @@ mymain(void) DO_TEST(IndexToDiskName); DO_TEST(DiskNameToIndex); DO_TEST(ParseVersionString); + DO_TEST(RoundValueToPowerOfTwo); return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }