Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
DEFINE_IFUNC(9)		 BSD Kernel Developer's	Manual	       DEFINE_IFUNC(9)

     DEFINE_IFUNC -- define a kernel function with an implementation selected
     at	run-time

     #include <machine/ifunc.h>

     DEFINE_IFUNC(qual,	ret_type, name,	args);

     ifuncs are	a linker feature which allows the programmer to	define func-
     tions 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-de-
     pendent 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	exam-
     ple, newer	generations of a given CPU architecture	may provide an in-
     struction to optimize a common operation.	To avoid the overhead of test-
     ing for the CPU feature each time the operation is	performed, an ifunc
     can be used to provide two	implementations	for the	operation: one target-
     ing platforms with	the extra instruction, and one for older platforms.

     Because DEFINE_IFUNC is a macro that defines a dynamically	typed func-
     tion, 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 pa-
     rameter is	typically empty	or the static qualifier.  ret_type is the re-
     turn type of the ifunc.  name is the name of the ifunc.  args is a	paren-
     thesized, 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 parame-
     ter 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.

     ifunc resolvers are executed early	during boot, before most kernel	facil-
     ities are available.  They	are effectively	limited	to checking CPU	fea-
     ture 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);
		     return (slow_strlen);

     This defines a strlen() function with an optimized	implementation for
     CPUs that advertise support.


     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.

BSD				 May 18, 2019				   BSD


Want to link to this manual page? Use this URL:

home | help