kernel

Macro global_lock

Source
macro_rules! global_lock {
    {
        $(#[$meta:meta])* $pub:vis
        unsafe(uninit) static $name:ident: $kind:ident<$valuety:ty> = $value:expr;
    } => { ... };
}
Expand description

Defines a global lock.

The global mutex must be initialized before first use. Usually this is done by calling GlobalLock::init in the module initializer.

§Examples

A global counter:

kernel::sync::global_lock! {
    // SAFETY: Initialized in module initializer before first use.
    unsafe(uninit) static MY_COUNTER: Mutex<u32> = 0;
}

fn increment_counter() -> u32 {
    let mut guard = MY_COUNTER.lock();
    *guard += 1;
    *guard
}

impl kernel::Module for MyModule {
    fn init(_module: &'static ThisModule) -> Result<Self> {
        // SAFETY: Called exactly once.
        unsafe { MY_COUNTER.init() };

        Ok(MyModule {})
    }
}

A global mutex used to protect all instances of a given struct:

use kernel::sync::{GlobalGuard, GlobalLockedBy};

kernel::sync::global_lock! {
    // SAFETY: Initialized in module initializer before first use.
    unsafe(uninit) static MY_MUTEX: Mutex<()> = ();
}

/// All instances of this struct are protected by `MY_MUTEX`.
struct MyStruct {
    my_counter: GlobalLockedBy<u32, MY_MUTEX>,
}

impl MyStruct {
    /// Increment the counter in this instance.
    ///
    /// The caller must hold the `MY_MUTEX` mutex.
    fn increment(&self, guard: &mut GlobalGuard<MY_MUTEX>) -> u32 {
        let my_counter = self.my_counter.as_mut(guard);
        *my_counter += 1;
        *my_counter
    }
}

impl kernel::Module for MyModule {
    fn init(_module: &'static ThisModule) -> Result<Self> {
        // SAFETY: Called exactly once.
        unsafe { MY_MUTEX.init() };

        Ok(MyModule {})
    }
}