{"id":20446299,"url":"https://github.com/rust-embedded/critical-section","last_synced_at":"2025-05-15T03:06:55.996Z","repository":{"id":40523156,"uuid":"365854323","full_name":"rust-embedded/critical-section","owner":"rust-embedded","description":"Pluggable critical section","archived":false,"fork":false,"pushed_at":"2024-12-03T10:21:51.000Z","size":116,"stargazers_count":133,"open_issues_count":3,"forks_count":20,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-04-14T04:58:59.894Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rust-embedded.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-09T21:47:16.000Z","updated_at":"2025-04-12T02:54:38.000Z","dependencies_parsed_at":"2023-01-21T05:46:51.198Z","dependency_job_id":"34d49e68-b02d-4729-94d8-ca0ea31c25ed","html_url":"https://github.com/rust-embedded/critical-section","commit_stats":{"total_commits":87,"total_committers":10,"mean_commits":8.7,"dds":0.3793103448275862,"last_synced_commit":"af414be744bce85a611fe64e87e17a1ac41929fb"},"previous_names":["embassy-rs/critical-section"],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fcritical-section","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fcritical-section/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fcritical-section/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fcritical-section/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rust-embedded","download_url":"https://codeload.github.com/rust-embedded/critical-section/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254264766,"owners_count":22041793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-15T10:19:07.350Z","updated_at":"2025-05-15T03:06:50.981Z","avatar_url":"https://github.com/rust-embedded.png","language":"Rust","readme":"# critical-section\n[![crates.io](https://img.shields.io/crates/d/critical-section.svg)](https://crates.io/crates/critical-section)\n[![crates.io](https://img.shields.io/crates/v/critical-section.svg)](https://crates.io/crates/critical-section)\n[![Documentation](https://docs.rs/critical-section/badge.svg)](https://docs.rs/critical-section)\n\nThis project is developed and maintained by the [HAL team][team].\n\nA critical section that works everywhere!\n\nWhen writing software for embedded systems, it's common to use a \"critical section\"\nas a basic primitive to control concurrency. A critical section is essentially a\nmutex global to the whole process, that can be acquired by only one thread at a time.\nThis can be used to protect data behind mutexes, to [emulate atomics](https://crates.io/crates/portable-atomic) in\ntargets that don't support them, etc.\n\nThere's a wide range of possible implementations depending on the execution environment:\n- For bare-metal single core, disabling interrupts in the current (only) core.\n- For bare-metal multicore, disabling interrupts in the current core and acquiring a hardware spinlock to prevent other cores from entering a critical section concurrently.\n- For bare-metal using a RTOS, using library functions for acquiring a critical section, often named \"scheduler lock\" or \"kernel lock\".\n- For bare-metal running in non-privileged mode, calling some system call is usually needed.\n- For `std` targets, acquiring a global `std::sync::Mutex`.\n\nLibraries often need to use critical sections, but there's no universal API for this in `core`. This leads\nlibrary authors to hard-code them for their target, or at best add some `cfg`s to support a few targets.\nThis doesn't scale since there are many targets out there, and in the general case it's impossible to know\nwhich critical section implementation is needed from the Rust target alone. For example, the `thumbv7em-none-eabi` target\ncould be cases 1-4 from the above list.\n\nThis crate solves the problem by providing this missing universal API.\n\n- It provides functions `acquire`, `release` and `with` that libraries can directly use.\n- 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.\n\n## Usage in `no-std` binaries.\n\nFirst, add a dependency on a crate providing a critical section implementation. Enable the `critical-section-*` Cargo feature if required by the crate.\n\nImplementations are typically provided by either architecture-support crates, HAL crates, and OS/RTOS bindings, including:\n\n* The [`cortex-m`] crate provides an implementation for all single-core Cortex-M microcontrollers via its `critical-section-single-core` feature\n* The [`riscv`] crate provides an implementation for all single-hart RISC-V microcontrollers via its `critical-section-single-hart` feature\n* The [`msp430`] crate provides an implementation for all MSP430 microcontrollers via its `critical-section-single-core` feature\n* The [`rp2040-hal`] crate provides a multi-core-safe critical section for the RP2040 microcontroller via its `critical-section-impl` feature\n* The [`avr-device`] crate provides an implementation for all AVR microcontrollers via its `critical-section-impl` feature\n* The [`esp-hal`] crate provides an implementation for ESP32 microcontrollers which is used by the ESP HALs\n* The [`embassy-rp`] crate provides a multi-core-safe critical section for the RP2040 microcontroller via its `critical-section-impl` feature\n* The [`nrf-softdevice`] crate provides a critical section that's compatible with the nRF soft-device firmware via its `critical-section-impl` feature\n\n[`cortex-m`]: https://crates.io/crates/cortex-m\n[`riscv`]: https://crates.io/crates/riscv\n[`msp430`]: https://crates.io/crates/msp430\n[`rp2040-hal`]: https://crates.io/crates/rp2040-hal\n[`avr-device`]: https://crates.io/crates/avr-device\n[`esp-hal`]: https://crates.io/crates/esp-hal\n[`embassy-rp`]: https://docs.embassy.dev/embassy-rp\n[`nrf-softdevice`]: https://docs.embassy.dev/nrf-softdevice\n\nFor example, for single-core Cortex-M targets, you can use:\n\n```toml\n[dependencies]\ncortex-m = { version = \"0.7.6\", features = [\"critical-section-single-core\"]}\n```\n\nThen you can use `critical_section::with()`.\n\n```rust\nuse core::cell::Cell;\nuse critical_section::Mutex;\n\nstatic MY_VALUE: Mutex\u003cCell\u003cu32\u003e\u003e = Mutex::new(Cell::new(0));\n\ncritical_section::with(|cs| {\n    // This code runs within a critical section.\n\n    // `cs` is a token that you can use to \"prove\" that to some API,\n    // for example to a `Mutex`:\n    MY_VALUE.borrow(cs).set(42);\n});\n\n# #[cfg(not(feature = \"std\"))] // needed for `cargo test --features std`\n# mod no_std {\n#     struct MyCriticalSection;\n#     critical_section::set_impl!(MyCriticalSection);\n#     unsafe impl critical_section::Impl for MyCriticalSection {\n#         unsafe fn acquire() -\u003e () {}\n#         unsafe fn release(token: ()) {}\n#     }\n# }\n```\n\n## Usage in `std` binaries.\n\nAdd the `critical-section` dependency to `Cargo.toml` enabling the `std` feature. This makes the `critical-section` crate itself\nprovide an implementation based on `std::sync::Mutex`, so you don't have to add any other dependency.\n\n```toml\n[dependencies]\ncritical-section = { version = \"1.1\", features = [\"std\"]}\n```\n\n## Usage in libraries\n\nIf you're writing a library intended to be portable across many targets, simply add a dependency on `critical-section`\nand use `critical_section::free` and/or `Mutex` as usual.\n\n**Do not** add any dependency supplying a critical section implementation. Do not enable any `critical-section-*` Cargo feature.\nThis has to be done by the end user, enabling the correct implementation for their target.\n\n**Do not** enable any Cargo feature in `critical-section`.\n\n## Usage in `std` tests for `no-std` libraries.\n\nIf you want to run `std`-using tests in otherwise `no-std` libraries, enable the `std` feature in `dev-dependencies` only.\nThis way the main target will use the `no-std` implementation chosen by the end-user's binary, and only the test targets\nwill use the `std` implementation.\n\n```toml\n[dependencies]\ncritical-section = \"1.1\"\n\n[dev-dependencies]\ncritical-section = { version = \"1.1\", features = [\"std\"]}\n```\n\n## Providing an implementation\n\nCrates adding support for a particular architecture, chip or operating system should provide a critical section implementation.\nIt is **strongly recommended** to gate the implementation behind a feature, so the user can still use another implementation\nif needed (having two implementations in the same binary will cause linking to fail).\n\nAdd the dependency, and a `critical-section-*` feature to your `Cargo.toml`:\n\n```toml\n[features]\n# Enable critical section implementation that does \"foo\"\ncritical-section-foo = [\"critical-section/restore-state-bool\"]\n\n[dependencies]\ncritical-section = { version = \"1.0\", optional = true }\n```\n\nThen, provide the critical implementation like this:\n\n```rust\n# #[cfg(not(feature = \"std\"))] // needed for `cargo test --features std`\n# mod no_std {\n// This is a type alias for the enabled `restore-state-*` feature.\n// For example, it is `bool` if you enable `restore-state-bool`.\nuse critical_section::RawRestoreState;\n\nstruct MyCriticalSection;\ncritical_section::set_impl!(MyCriticalSection);\n\nunsafe impl critical_section::Impl for MyCriticalSection {\n    unsafe fn acquire() -\u003e RawRestoreState {\n        // TODO\n    }\n\n    unsafe fn release(token: RawRestoreState) {\n        // TODO\n    }\n}\n# }\n```\n\n## Troubleshooting\n\n### Undefined reference errors\n\nIf you get an error like these:\n\n```not_rust\nundefined reference to `_critical_section_1_0_acquire'\nundefined reference to `_critical_section_1_0_release'\n```\n\nit is because you (or a library) are using `critical_section::with` without providing a critical section implementation.\nMake 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.\n\nThe error can also be caused by having the dependency but never `use`ing it. This can be fixed by adding a dummy `use`:\n\n```rust,ignore\nuse the_cs_impl_crate as _;\n```\n\n### Duplicate symbol errors\n\nIf you get errors like these:\n\n```not_rust\nerror: symbol `_critical_section_1_0_acquire` is already defined\n```\n\nit is because you have two crates trying to provide a critical section implementation. You can only\nhave one implementation in a program.\n\nYou can use `cargo tree --format '{p} {f}'` to view all dependencies and their enabled features. Make sure\nthat in the whole dependency tree, exactly one implementation is provided.\n\nCheck for multiple versions of the same crate as well. For example, check the `critical-section-single-core`\nfeature is not enabled for both `cortex-m` 0.7 and 0.8.\n\n## Why not generics?\n\nAn alternative solution would be to use a `CriticalSection` trait, and make all\ncode that needs acquiring the critical section generic over it. This has a few problems:\n\n- It would require passing it as a generic param to a very big amount of code, which\nwould be quite unergonomic.\n- It's common to put `Mutex`es in `static` variables, and `static`s can't\nbe generic.\n- It would allow mixing different critical section implementations in the same program,\nwhich would be unsound.\n\n## Minimum Supported Rust Version (MSRV)\n\nThis crate is guaranteed to compile on the following Rust versions:\n\n- If the `std` feature is not enabled: stable Rust 1.54 and up.\n- If the `std` feature is enabled: stable Rust 1.63 and up.\n\nIt might compile with older versions but that may change in any new patch release.\n\nSee [here](docs/msrv.md) for details on how the MSRV may be upgraded.\n\n## License\n\nThis work is licensed under either of\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or\n  \u003chttp://www.apache.org/licenses/LICENSE-2.0\u003e)\n- MIT license ([LICENSE-MIT](LICENSE-MIT) or \u003chttp://opensource.org/licenses/MIT\u003e)\n\nat your option.\n\n## Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you, as defined in the Apache-2.0 license, shall be\ndual licensed as above, without any additional terms or conditions.\n\n## Code of Conduct\n\nContribution to this crate is organized under the terms of the [Rust Code of\nConduct][CoC], the maintainer of this crate, the [HAL team][team], promises\nto intervene to uphold that code of conduct.\n\n[CoC]: CODE_OF_CONDUCT.md\n[team]: https://github.com/rust-embedded/wg#the-hal-team\n","funding_links":[],"categories":["Rust"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frust-embedded%2Fcritical-section","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frust-embedded%2Fcritical-section","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frust-embedded%2Fcritical-section/lists"}