khelp,
    khelp_init_osd,
    khelp_destroy_osd,
    khelp_get_id, khelp_get_osd,
    khelp_add_hhook,
    khelp_remove_hhook,
    KHELP_DECLARE_MOD,
    KHELP_DECLARE_MOD_UMA —
    Kernel Helper Framework
#include
    <sys/khelp.h>
  
  #include
  <sys/module_khelp.h>
int
    khelp_init_osd(uint32_t
    classes, struct osd
    *hosd);
int
    khelp_destroy_osd(struct
    osd *hosd);
int32_t
    khelp_get_id(char
    *hname);
void *
    khelp_get_osd(struct
    osd *hosd, int32_t
    id);
int
    khelp_add_hhook(const
    struct hookinfo *hki,
    uint32_t flags);
int
    khelp_remove_hhook(const
    struct hookinfo *hki);
KHELP_DECLARE_MOD(hname,
    hdata,
    hhooks,
    version);
KHELP_DECLARE_MOD_UMA(hname,
    hdata,
    hhooks,
    version,
    ctor,
    dtor);
khelp provides a framework for managing
    khelp modules, which indirectly use the
    hhook(9)
    KPI to register their hook functions with hook points of interest within the
    kernel. Khelp modules aim to provide a structured way to dynamically extend
    the kernel at runtime in an ABI preserving manner. Depending on the
    subsystem providing hook points, a khelp module may
    be able to associate per-object data for maintaining relevant state between
    hook calls. The
    hhook(9)
    and khelp frameworks are tightly integrated and
    anyone interested in khelp should also read the
    hhook(9)
    manual page thoroughly.
khelp modules are represented within the
    khelp framework by a struct
    helper which has the following members:
struct helper {
	int (*mod_init) (void);
	int (*mod_destroy) (void);
#define	HELPER_NAME_MAXLEN 16
	char			h_name[HELPER_NAME_MAXLEN];
	uma_zone_t		h_zone;
	struct hookinfo		*h_hooks;
	uint32_t		h_nhooks;
	uint32_t		h_classes;
	int32_t			h_id;
	volatile uint32_t	h_refcount;
	uint16_t		h_flags;
	TAILQ_ENTRY(helper)	h_next;
};
 
Modules must instantiate a struct helper,
    but are only required to set the h_classes field, and
    may optionally set the h_flags,
    mod_init and mod_destroy fields
    where required. The framework takes care of all other fields and modules
    should refrain from manipulating them. Using the C99 designated initialiser
    feature to set fields is encouraged.
If specified, the mod_init function will be
    run by the khelp framework prior to completing the
    registration process. Returning a non-zero value from the
    mod_init function will abort the registration process
    and fail to load the module. If specified, the
    mod_destroy function will be run by the
    khelp framework during the deregistration process,
    after the module has been deregistered by the khelp
    framework. The return value is currently ignored. Valid
    khelp classes are defined in
    <sys/khelp.h>. Valid flags
    are defined in
    <sys/module_khelp.h>. The
    HELPER_NEEDS_OSD flag should be set in the h_flags
    field if the khelp module requires persistent
    per-object data storage. There is no programmatic way (yet) to check if a
    khelp class provides the ability for
    khelp modules to associate persistent per-object
    data, so a manual check is required.
The
    KHELP_DECLARE_MOD()
    and KHELP_DECLARE_MOD_UMA() macros provide
    convenient wrappers around the
    DECLARE_MODULE(9)
    macro, and are used to register a khelp module with
    the khelp framework.
    KHELP_DECLARE_MOD_UMA() should only be used by
    modules which require the use of persistent per-object storage i.e. modules
    which set the HELPER_NEEDS_OSD flag in their struct
    helper's h_flags field.
The first four arguments common to both
    macros are as follows. The hname argument specifies
    the unique
    ascii(7)
    name for the khelp module. It should be no longer
    than HELPER_NAME_MAXLEN-1 characters in length. The
    hdata argument is a pointer to the module's
    struct helper. The hhooks
    argument points to a static array of struct hookinfo
    structures. The array should contain a struct hookinfo
    for each
    hhook(9)
    point the module wishes to hook, even when using the same hook function
    multiple times for different
    hhook(9)
    points. The version argument specifies a version
    number for the module which will be passed to
    MODULE_VERSION(9).
    The
    KHELP_DECLARE_MOD_UMA()
    macro takes the additional ctor and
    dtor arguments, which specify optional
    uma(9)
    constructor and destructor functions. NULL should be passed where the
    functionality is not required.
The
    khelp_get_id()
    function returns the numeric identifier for the
    khelp module with name
  hname.
The
    khelp_get_osd()
    function is used to obtain the per-object data pointer for a specified
    khelp module. The hosd
    argument is a pointer to the underlying subsystem object's
    struct osd. This is provided by the
    hhook(9)
    framework when calling into a khelp module's hook
    function. The id argument specifies the numeric
    identifier for the khelp module to extract the data
    pointer from hosd for. The id is
    obtained using the khelp_get_id() function.
The
    khelp_add_hhook()
    and
    khelp_remove_hhook()
    functions allow a khelp module to dynamically
    hook/unhook
    hhook(9)
    points at run time. The hki argument specifies a
    pointer to a struct hookinfo which encapsulates the
    required information about the
    hhook(9)
    point and hook function being manipulated. The HHOOK_WAITOK flag may be
    passed in via the flags argument of
    khelp_add_hhook() if
    malloc(9)
    is allowed to sleep waiting for memory to become available.
Most of the work required to allow khelp
    modules to do useful things relates to defining and instantiating suitable
    hhook(9)
    points for khelp modules to hook into. The only
    additional decision a subsystem needs to make is whether it wants to allow
    khelp modules to associate persistent per-object
    data. Providing support for persistent data storage can allow
    khelp modules to perform more complex functionality
    which may be desirable. Subsystems which want to allow Khelp modules to
    associate persistent per-object data with one of the subsystem's data
    structures need to make the following two key changes:
  - Embed a struct osd pointer in the structure
      definition for the object.
- Add calls to khelp_init_osd() andkhelp_destroy_osd() to the subsystem code paths
      which are responsible for respectively initialising and destroying the
      object.
The
    khelp_init_osd()
    function initialises the per-object data storage for all currently loaded
    khelp modules of appropriate classes which have set
    the HELPER_NEEDS_OSD flag in their h_flags field. The
    classes argument specifies a bitmask of
    khelp classes which this subsystem associates with.
    If a khelp module matches any of the classes in the
    bitmask, that module will be associated with the object. The
    hosd argument specifies the pointer to the object's
    struct osd which will be used to provide the
    persistent storage for use by khelp modules.
The
    khelp_destroy_osd()
    function frees all memory that was associated with an object's
    struct osd by a previous call to
    khelp_init_osd(). The hosd
    argument specifies the pointer to the object's struct
    osd which will be purged in preparation for destruction.
khelp modules are protected from being
    prematurely unloaded by a reference count. The count is incremented each
    time a subsystem calls khelp_init_osd() causing
    persistent storage to be allocated for the module, and decremented for each
    corresponding call to khelp_destroy_osd(). Only when
    a module's reference count has dropped to zero can the module be
  unloaded.
The khelp_init_osd() function returns zero
    if no errors occurred. It returns ENOMEM if a khelp
    module which requires per-object storage fails to allocate the necessary
    memory.
The khelp_destroy_osd() function only
    returns zero to indicate that no errors occurred.
The khelp_get_id() function returns the
    unique numeric identifier for the registered khelp
    module with name hname. It return -1 if no module with
    the specified name is currently registered.
The khelp_get_osd() function returns the
    pointer to the khelp module's persistent object
    storage memory. If the module identified by id does
    not have persistent object storage registered with the object's
    hosd struct osd, NULL is
    returned.
The khelp_add_hhook() function returns
    zero if no errors occurred. It returns ENOENT if it could not find the
    requested
    hhook(9)
    point. It returns ENOMEM if
    malloc(9)
    failed to allocate memory. It returns EEXIST if attempting to register the
    same hook function more than once for the same
    hhook(9)
    point.
The khelp_remove_hhook() function returns
    zero if no errors occurred. It returns ENOENT if it could not find the
    requested
    hhook(9)
    point.
A well commented example Khelp module can be found at:
    /usr/share/examples/kld/khelp/h_example.c
The Enhanced Round Trip Time (ERTT)
    h_ertt(4)
    khelp module provides a more complex example of what
    is possible.
Development and testing of this software were made possible in
    part by grants from the FreeBSD Foundation and Cisco University Research
    Program Fund at Community Foundation Silicon Valley.
The khelp kernel helper framework first
    appeared in FreeBSD 9.0.
The khelp framework was first released in
    2010 by Lawrence Stewart whilst studying at Swinburne University of
    Technology's Centre for Advanced Internet Architectures, Melbourne,
    Australia. More details are available at:
http://caia.swin.edu.au/urp/newtcp/