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:

FeatureDefaultPurpose
preemptDisabledEnables kernel preemption control in applicable guards
defaultEmptyNo 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 Typepreempt Feature Disabledpreempt Feature Enabled
NoOpNo operationNo operation
IrqSaveIRQ disable/restore onlyIRQ disable/restore only
NoPreemptNo operationPreemption disable/enable viaKernelGuardIf
NoPreemptIrqSaveIRQ disable/restore onlyPreemption 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:

ConfigurationUser Implementation Required
preemptdisabledNone
preemptenabledMust 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.

Sources: Cargo.toml(L14 - L16)  src/lib.rs(L21 - L26)