The Sysinit Framework Sysinit is the framework for a generic call sort and dispatch mechanism. FreeBSD currently uses it for the dynamic initialization of the kernel. Sysinit allows FreeBSD's kernel subsystems to be reordered, and added, removed, and replaced at kernel link time when the kernel or one of its modules is loaded without having to edit a statically ordered initialization routing and recompile the kernel. This system also allows kernel modules, currently called KLD's, to be separately compiled, linked, and initialized at boot time and loaded even later while the system is already running. This is accomplished using the kernel linker and linker sets. Terminology Linker Set A linker technique in which the linker gathers statically declared data throughout a program's source files into a single contiguously addressable unit of data. Sysinit Operation Sysinit relies on the ability of the linker to take static data declared at multiple locations throughout a program's source and group it together as a single contiguous chunk of data. This linker technique is called a linker set. Sysinit uses two linker sets to maintain two data sets containing each consumer's call order, function, and a pointer to the data to pass to that function. Sysinit uses two priorities when ordering the functions for execution. The first priority is a subsystem ID giving an overall order Sysinit's dispatch of functions. Current predeclared ID's are in <sys/kernel.h> in the enum list sysinit_sub_id. The second priority used is an element order within the subsystem. Current predeclared subsystem element orders are in <sys/kernel.h> in the enum list sysinit_elem_order. There are currently two uses for Sysinit. Function dispatch at system startup and kernel module loads, and function dispatch at system shutdown and kernel module unload. Using Sysinit Interface Headers <sys/kernel.h> Macros SYSINIT(uniquifier, subsystem, order, func, ident) SYSUNINIT(uniquifier, subsystem, order, func, ident) Startup The SYSINIT() macro creates the necessary sysinit data in Sysinit's startup data set for Sysinit to sort and dispatch a function at system startup and module load. SYSINIT() takes a uniquifier that Sysinit uses identify the particular function dispatch data, the subsystem order, the subsystem element order, the function to call, and the data to pass the function. All functions must take a constant pointer argument. For example: #include <sys/kernel.h> void foo_null(void *unused) { foo_doo(); } SYSINIT(foo_null, SI_SUB_FOO, SI_ORDER_FOO, NULL); struct foo foo_voodoo = { FOO_VOODOO; } void foo_arg(void *vdata) { struct foo *foo = (struct foo *)vdata; foo_data(foo); } SYSINIT(foo_arg, SI_SUB_FOO, SI_ORDER_FOO, foo_voodoo); Shutdown The SYSUNINIT() macro behaves similarly to the SYSINIT() macro except that it adds the Sysinit data to Sysinit's shutdown data set. For example: #include <sys/kernel.h> void foo_cleanup(void *unused) { foo_kill(); } SYSUNINIT(foo_cleanup, SI_SUB_FOO, SI_ORDER_FOO, NULL); struct foo_stack foo_stack = { FOO_STACK_VOODOO; } void foo_flush(void *vdata) { } SYSUNINIT(foo_flush, SI_SUB_FOO, SI_ORDER_FOO, foo_stack);