Provided by: freebsd-manpages_12.2-1_all bug

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.