DEFINE_IFUNC(9) FreeBSD Kernel Developer's Manual DEFINE_IFUNC(9)
NAME
DEFINE_IFUNC - define a kernel function with an implementation selected
at run-time
SYNOPSIS
#include <machine/ifunc.h>
DEFINE_IFUNC(qual, ret_type, name, args);
DESCRIPTION
ifuncs are a linker feature which allows the programmer to define
functions whose implementation is selected at boot-time or module load-
time. The DEFINE_IFUNC macro can be used to define an ifunc. The
selection is performed by a resolver function, which returns a pointer to
the selected function. ifunc resolvers are invoked very early during the
machine-dependent initialization routine, or at load time for dynamically
loaded modules. Resolution must occur before the first call to an ifunc.
ifunc resolution is performed after CPU features are enumerated and after
the kernel's environment is initialized. The typical use-case for an
ifunc is a routine whose behavior depends on optional CPU features. For
example, newer generations of a given CPU architecture may provide an
instruction to optimize a common operation. To avoid the overhead of
testing for the CPU feature each time the operation is performed, an
ifunc can be used to provide two implementations for the operation: one
targeting platforms with the extra instruction, and one for older
platforms.
Because DEFINE_IFUNC is a macro that defines a dynamically typed
function, its usage looks somewhat unusual. The qual parameter is a list
of zero or more C function qualifiers to be applied to the ifunc. This
parameter is typically empty or the static qualifier. ret_type is the
return type of the ifunc. name is the name of the ifunc. args is a
parenthesized, comma-separated list of the parameter types of the
function, as they would appear in a C function declaration.
The DEFINE_IFUNC usage must be followed by the resolver function body.
The resolver must return a function with return type ret_type and
parameter types args. The resolver function is defined with the
`resolver' gcc-style function attribute, causing the corresponding elf(5)
function symbol to be of type STT_GNU_IFUNC instead of STT_FUNC. The
kernel linker invokes the resolver to process relocations targeting ifunc
calls and PLT entries referencing such symbols.
EXAMPLES
ifunc resolvers are executed early during boot, before most kernel
facilities are available. They are effectively limited to checking CPU
feature flags and tunables.
static size_t
fast_strlen(const char *s __unused)
{
size_t len;
/* Fast, but may not be correct in all cases. */
__asm("movq $42,%0\n" : "=r" (len));
return (len);
}
static size_t
slow_strlen(const char *s)
{
const char *t;
for (t = s; *t != '\0'; t++);
return (t - s);
}
DEFINE_IFUNC(, size_t, strlen, (const char *))
{
int enabled;
enabled = 1;
TUNABLE_INT_FETCH("debug.use_fast_strlen", &enabled);
if (enabled && (cpu_features & CPUID_FAST_STRLEN) != 0)
return (fast_strlen);
else
return (slow_strlen);
}
This defines a strlen() function with an optimized implementation for
CPUs that advertise support.
SEE ALSO
elf(5)
NOTES
ifuncs are not supported on all architectures. They require both
toolchain support, to emit function symbols of type STT_GNU_IFUNC, and
kernel linker support to invoke ifunc resolvers during boot or during
module load.
FreeBSD 13.1-RELEASE-p6 May 18, 2019 FreeBSD 13.1-RELEASE-p6
man2web Home...