critical-section — Crate 詳細
critical-section
環境ごとに差し替え可能なクリティカルセクション API crate。no_std ライブラリが、Cortex-M の割り込み禁止、RP2040 のマルチコア対応ロック、RTOS のカーネルロック、std の Mutex などの実装差を意識せず、critical_section::with() や Mutex を使って共有データを保護できるようにします。
A pluggable, cross-platform critical-section API for Rust. It lets portable libraries use critical_section::with(), acquire/release, and a critical-section-based Mutex while the final target-support crate supplies the concrete implementation.
概要
critical-section は、組み込み Rust で共有データを保護するための 共通 API を提供する crate です。ライブラリは critical_section::with() や critical_section::Mutex を使ってクリティカルセクション内の処理を書き、最終バイナリ側が Cortex-M、RISC-V、RP2040、RTOS、std など実行環境に合った実装を 1 つだけ供給します。
使い分けの考え方
- ライブラリ crate:
critical-sectionに依存するだけにし、stdやcritical-section-*feature は有効化しない。実装選択は最終ユーザーのバイナリに任せる。 - no_std バイナリ:
cortex-m、riscv、rp2040-hal、embassy-rp、nrf-softdeviceなど、ターゲットに合った実装提供 crate の feature を 1 つだけ有効化する。 - std バイナリ / host test:
critical-sectionのstdfeature を有効化すると、std::sync::Mutexベースの実装を使える。no_std ライブラリのテストでは dev-dependencies 側だけで有効化するのが安全。
注意点
critical_section::with() を使うのに実装が 1 つもリンクされていない場合は _critical_section_1_0_acquire / _critical_section_1_0_release の undefined reference が発生します。逆に複数の crate が実装を提供すると duplicate symbol になります。依存ツリー全体で実装は ちょうど 1 つ になるように feature を整理してください。
コード例
PC 上のサンプルや no_std ライブラリの host test では std feature を dev-dependencies 側だけで有効化すると扱いやすいです。
use core::cell::Cell;use critical_section::Mutex;
// Cargo.toml:// critical-section = { version = "1.2", features = ["std"] }//// std feature を有効化すると、critical-section crate 自身が// std::sync::Mutex ベースの実装を提供します。static COUNTER: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
fn main() { critical_section::with(|cs| { let current = COUNTER.borrow(cs).get(); COUNTER.borrow(cs).set(current + 1); });
critical_section::with(|cs| { assert_eq!(COUNTER.borrow(cs).get(), 1); });}単一コア Cortex-M では cortex-m crate の critical-section-single-core feature を使う構成例です。実プロジェクトではターゲット MCU/HAL/RTOS に合った実装を 1 つだけ有効化します。
#![no_std]#![no_main]
use core::cell::Cell;use cortex_m_rt::entry;use critical_section::Mutex;use panic_halt as _;
// Cargo.toml の例:// cortex-m = { version = "0.7", features = ["critical-section-single-core"] }// cortex-m-rt = "0.7"// critical-section = "1.2"// panic-halt = "0.2"//// ライブラリ側は critical-section のみを使い、// 実際の実装は最終バイナリ側で 1 つだけ選択します。static VALUE: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));
#[entry]fn main() -> ! { critical_section::with(|cs| { VALUE.borrow(cs).set(42); });
loop { cortex_m::asm::wfi(); }}