Command Section

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

Command Section

man2web Home...