Commit 424cbc39 authored by Nick Connolly's avatar Nick Connolly Committed by Tomasz Zawadzki
Browse files

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: default avatarNick Connolly <nick.connolly@mayadata.io>
Change-Id: Iff76640b34223649de531250ad40471d829512c7
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6317


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@mellanox.com>
parent 0e9ee176
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -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);
}