Expand description


crates.io crates.io Documentation

This project is developed and maintained by the HAL team.

A critical section that works everywhere!

When writing software for embedded systems, it’s common to use a “critical section” as a basic primitive to control concurrency. A critical section is essentially a mutex global to the whole process, that can be acquired by only one thread at a time. This can be used to protect data behind mutexes, to emulate atomics in targets that don’t support them, etc.

There’s a wide range of possible implementations depending on the execution environment:

  • For bare-metal single core, disabling interrupts globally.
  • For bare-metal multicore, acquiring a hardware spinlock and disabling interrupts globally.
  • For bare-metal using a RTOS, it usually provides library functions for acquiring a critical section, often named “scheduler lock” or “kernel lock”.
  • For bare-metal running in non-privileged mode, usually some system call is needed.
  • For std targets, acquiring a global std::sync::Mutex.

Libraries often need to use critical sections, but there’s no universal API for this in core. This leads library authors to hardcode them for their target, or at best add some cfgs to support a few targets. This doesn’t scale since there are many targets out there, and in the general case it’s impossible to know which critical section implementation is needed from the Rust target alone. For example, the thumbv7em-none-eabi target could be cases 1-4 from the above list.

This crate solves the problem by providing this missing universal API.

  • It provides functions acquire, release and with that libraries can directly use.
  • It provides a way for any crate to supply an implementation. This allows “target support” crates such as architecture crates (cortex-m, riscv), RTOS bindings, or HALs for multicore chips to supply the correct implementation so that all the crates in the dependency tree automatically use it.


First, add a dependency on a crate providing a critical section implementation. Enable the critical-section-* Cargo feature if required by the crate.

cortex-m = { version = "0.7.6", features = ["critical-section-single-core"]}

Then you can use critical_section::with().

use core::cell::Cell;
use critical_section::Mutex;

static MY_VALUE: Mutex<Cell<u32>> = Mutex::new(Cell::new(0));

critical_section::with(|cs| {
    // This code runs within a critical section.

    // `cs` is a token that you can use to "prove" that to some API,
    // for example to a `Mutex`:

Usage in libraries

If you’re writing a library intended to be portable across many targets, simply add a dependency on critical-section and use critical_section::free and/or Mutex as usual.

Do not add any dependency supplying a critical section implementation. Do not enable any critical-section-* Cargo feature. This has to be done by the end user, enabling the correct implementation for their target.

Do not enable any Cargo feature in critical-section.

Providing an implementation

Crates adding support for a particular architecture, chip or operating system should provide a critical section implementation. It is strongly recommended to gate the implementation behind a feature, so the user can still use another implementation if needed (having two implementations in the same binary will cause linking to fail).

Add the dependency, and a critical-section-* feature to your Cargo.toml:

critical-section-foo = ["critical-section/restore-state-bool"]

critical-section = { version = "1.0", optional = true }

Then, provide the critical implementation like this:

// This is a type alias for the enabled `restore-state-*` feature.
// For example, it is `bool` if you enable `restore-state-bool`.
use critical_section::RawRestoreState;

struct MyCriticalSection;

unsafe impl critical_section::Impl for MyCriticalSection {
    unsafe fn acquire() -> RawRestoreState {
        // TODO

    unsafe fn release(token: RawRestoreState) {
        // TODO


Undefined reference errors

If you get an error like these:

undefined reference to `_critical_section_1_0_acquire'
undefined reference to `_critical_section_1_0_release'

it is because you (or a library) are using critical_section::with without providing a critical section implementation. Make sure you’re depending on a crate providing the implementation, and have enabled the critical-section-* feature in it if required. See the Usage section above.

The error can also be caused by having the dependency but never useing it. This can be fixed by adding a dummy use:

use the_cs_impl_crate as _;

Duplicate symbol errors

If you get errors like these:

error: symbol `_critical_section_1_0_acquire` is already defined

it is because you have two crates trying to provide a critical section implementation. You can only have one implementation in a program.

You can use cargo tree --format '{p} {f}' to view all dependencies and their enabled features. Make sure that in the whole dependency tree, exactly one implementation is provided.

Check for multiple versions of the same crate as well. For example, check the critical-section-single-core feature is not enabled for both cortex-m 0.7 and 0.8.

Why not generics?

An alternative solution would be to use a CriticalSection trait, and make all code that needs acquiring the critical section generic over it. This has a few problems:

  • It would require passing it as a generic param to a very big amount of code, which would be quite unergonomic.
  • It’s common to put Mutexes in static variables, and statics can’t be generic.
  • It would allow mixing different critical section implementations in the same program, which would be unsound.


This work is licensed under either of

at your option.


Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Code of Conduct

Contribution to this crate is organized under the terms of the Rust Code of Conduct, the maintainer of this crate, the HAL team, promises to intervene to uphold that code of conduct.


Set the critical section implementation.


Critical section token.

A mutex based on critical sections.

Opaque “restore state”.


Methods required for a critical section implementation.


Acquire a critical section in the current thread.

Release the critical section.

Execute closure f in a critical section.

Type Definitions

Raw, transparent “restore state”.