lib/util/math.c: improve portability
__builtin_clzl takes an unsigned long argument which may be smaller than uint64_t on some platforms. GCC silently ignores the mismatch, returning the wrong answer at runtime. Use __builtin_clzll instead and add static assertions to detect the issue. Attribute 'target_clones' requires 'ifunc' support which only applies to ELF targets. Add check for defined(__ELF__). Signed-off-by: Nick Connolly <nick.connolly@mayadata.io> Change-Id: Iff76640b34223649de531250ad40471d829512c7 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6317 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Mellanox Build Bot Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
This commit is contained in:
parent
0e9ee17642
commit
424cbc3957
@ -33,12 +33,14 @@
|
||||
|
||||
#include "spdk/stdinc.h"
|
||||
#include "spdk/util.h"
|
||||
#include "spdk/assert.h"
|
||||
|
||||
/* The following will automatically generate several version of
|
||||
* this function, targeted at different architectures. This
|
||||
* is only supported by GCC 6 or newer. */
|
||||
#if defined(__GNUC__) && __GNUC__ >= 6 && !defined(__clang__) \
|
||||
&& (defined(__i386__) || defined(__x86_64__))
|
||||
&& (defined(__i386__) || defined(__x86_64__)) \
|
||||
&& defined(__ELF__)
|
||||
__attribute__((target_clones("bmi", "arch=core2", "arch=atom", "default")))
|
||||
#endif
|
||||
uint32_t
|
||||
@ -48,6 +50,7 @@ spdk_u32log2(uint32_t x)
|
||||
/* log(0) is undefined */
|
||||
return 0;
|
||||
}
|
||||
SPDK_STATIC_ASSERT(sizeof(x) == sizeof(unsigned int), "Incorrect size");
|
||||
return 31u - __builtin_clz(x);
|
||||
}
|
||||
|
||||
@ -55,7 +58,8 @@ spdk_u32log2(uint32_t x)
|
||||
* this function, targeted at different architectures. This
|
||||
* is only supported by GCC 6 or newer. */
|
||||
#if defined(__GNUC__) && __GNUC__ >= 6 && !defined(__clang__) \
|
||||
&& (defined(__i386__) || defined(__x86_64__))
|
||||
&& (defined(__i386__) || defined(__x86_64__)) \
|
||||
&& defined(__ELF__)
|
||||
__attribute__((target_clones("bmi", "arch=core2", "arch=atom", "default")))
|
||||
#endif
|
||||
uint64_t
|
||||
@ -65,5 +69,6 @@ spdk_u64log2(uint64_t x)
|
||||
/* log(0) is undefined */
|
||||
return 0;
|
||||
}
|
||||
return 63u - __builtin_clzl(x);
|
||||
SPDK_STATIC_ASSERT(sizeof(x) == sizeof(unsigned long long), "Incorrect size");
|
||||
return 63u - __builtin_clzll(x);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user