Feature Configuration
Relevant source files
This document explains the feature-based configuration system in the kernel_guard crate, specifically focusing on the preempt feature and its impact on guard availability and functionality. For information about implementing the required traits when using features, see Implementing KernelGuardIf.
Overview
The kernel_guard crate uses Cargo features to provide conditional functionality that adapts to different system requirements. The primary feature is preempt, which enables kernel preemption control capabilities in guard implementations. This feature system allows the crate to be used in both simple interrupt-only scenarios and more complex preemptive kernel environments.
Feature Definitions
The crate defines its features in the Cargo manifest with a minimal configuration approach:
| Feature | Default | Purpose |
|---|---|---|
| preempt | Disabled | Enables kernel preemption control in applicable guards |
| default | Empty | No features enabled by default |
Sources: Cargo.toml(L14 - L16)
Preempt Feature Behavior
Feature Impact on Guard Implementations
The preempt feature primarily affects two guard types: NoPreempt and NoPreemptIrqSave. When this feature is enabled, these guards will attempt to disable and re-enable kernel preemption around critical sections.
Compilation-Time Feature Resolution
flowchart TD COMPILE["Compilation Start"] FEATURE_CHECK["preempt featureenabled?"] PREEMPT_ENABLED["Preemption ControlActive"] PREEMPT_DISABLED["Preemption ControlNo-Op"] NOPRE_IMPL["NoPreempt::acquire()calls KernelGuardIf::disable_preempt"] NOPRE_REL["NoPreempt::release()calls KernelGuardIf::enable_preempt"] NOPRE_NOOP["NoPreempt::acquire()no operation"] NOPRE_NOOP_REL["NoPreempt::release()no operation"] COMBO_IMPL["NoPreemptIrqSave::acquire()calls disable_preempt + IRQ disable"] COMBO_REL["NoPreemptIrqSave::release()IRQ restore + enable_preempt"] COMBO_IRQ["NoPreemptIrqSave::acquire()IRQ disable only"] COMBO_IRQ_REL["NoPreemptIrqSave::release()IRQ restore only"] COMPILE --> FEATURE_CHECK FEATURE_CHECK --> PREEMPT_DISABLED FEATURE_CHECK --> PREEMPT_ENABLED PREEMPT_DISABLED --> COMBO_IRQ PREEMPT_DISABLED --> COMBO_IRQ_REL PREEMPT_DISABLED --> NOPRE_NOOP PREEMPT_DISABLED --> NOPRE_NOOP_REL PREEMPT_ENABLED --> COMBO_IMPL PREEMPT_ENABLED --> COMBO_REL PREEMPT_ENABLED --> NOPRE_IMPL PREEMPT_ENABLED --> NOPRE_REL
Sources: src/lib.rs(L149 - L161) src/lib.rs(L163 - L179)
Guard Behavior Matrix
The following table shows how each guard type behaves based on feature configuration:
| Guard Type | preempt Feature Disabled | preempt Feature Enabled |
|---|---|---|
| NoOp | No operation | No operation |
| IrqSave | IRQ disable/restore only | IRQ disable/restore only |
| NoPreempt | No operation | Preemption disable/enable viaKernelGuardIf |
| NoPreemptIrqSave | IRQ disable/restore only | Preemption disable + IRQ disable/restore |
Implementation Details
NoPreempt Guard Feature Integration
Sources: src/lib.rs(L149 - L161) src/lib.rs(L200 - L217)
NoPreemptIrqSave Combined Behavior
The NoPreemptIrqSave guard demonstrates the most complex feature-dependent behavior, combining both IRQ control and optional preemption control:
sequenceDiagram
participant UserCode as "User Code"
participant NoPreemptIrqSave as "NoPreemptIrqSave"
participant KernelGuardIf as "KernelGuardIf"
participant archlocal_irq_ as "arch::local_irq_*"
UserCode ->> NoPreemptIrqSave: new()
NoPreemptIrqSave ->> NoPreemptIrqSave: acquire()
alt preempt feature enabled
NoPreemptIrqSave ->> KernelGuardIf: disable_preempt()
Note over KernelGuardIf: Kernel preemption disabled
else preempt feature disabled
Note over NoPreemptIrqSave: Skip preemption control
end
NoPreemptIrqSave ->> archlocal_irq_: local_irq_save_and_disable()
archlocal_irq_ -->> NoPreemptIrqSave: irq_state
Note over NoPreemptIrqSave,archlocal_irq_: Critical section active
UserCode ->> NoPreemptIrqSave: drop()
NoPreemptIrqSave ->> NoPreemptIrqSave: release(irq_state)
NoPreemptIrqSave ->> archlocal_irq_: local_irq_restore(irq_state)
alt preempt feature enabled
NoPreemptIrqSave ->> KernelGuardIf: enable_preempt()
Note over KernelGuardIf: Kernel preemption restored
else preempt feature disabled
Note over NoPreemptIrqSave: Skip preemption control
end
Sources: src/lib.rs(L163 - L179) src/lib.rs(L220 - L237)
Integration Requirements
Feature Dependencies
When the preempt feature is enabled, user code must provide an implementation of the KernelGuardIf trait using the crate_interface mechanism. The relationship between feature activation and implementation requirements is:
| Configuration | User Implementation Required |
|---|---|
| preemptdisabled | None |
| preemptenabled | Must implementKernelGuardIftrait |
Runtime Interface Resolution
The crate uses crate_interface::call_interface! macros to dynamically dispatch to user-provided implementations at runtime. This occurs only when the preempt feature is active:
flowchart TD FEATURE_ENABLED["preempt featureenabled"] MACRO_CALL["crate_interface::call_interface!(KernelGuardIf::disable_preempt)"] RUNTIME_DISPATCH["Runtime InterfaceResolution"] USER_IMPL["User Implementationof KernelGuardIf"] ACTUAL_DISABLE["Actual PreemptionDisable Operation"] FEATURE_DISABLED["preempt featuredisabled"] COMPILE_SKIP["Conditional CompilationSkips Call"] NO_OPERATION["No PreemptionControl"] COMPILE_SKIP --> NO_OPERATION FEATURE_DISABLED --> COMPILE_SKIP FEATURE_ENABLED --> MACRO_CALL MACRO_CALL --> RUNTIME_DISPATCH RUNTIME_DISPATCH --> USER_IMPL USER_IMPL --> ACTUAL_DISABLE
Sources: src/lib.rs(L153 - L154) src/lib.rs(L158 - L159) src/lib.rs(L167 - L168) src/lib.rs(L176 - L177)
Configuration Examples
Basic Usage Without Preemption
[dependencies]
kernel_guard = "0.1"
In this configuration, NoPreempt and NoPreemptIrqSave guards will only control IRQs, making them functionally equivalent to IrqSave for the IRQ portion.
Full Preemptive Configuration
[dependencies]
kernel_guard = { version = "0.1", features = ["preempt"] }
This configuration enables full preemption control capabilities, requiring the user to implement KernelGuardIf.