Skip to content

Commit b5fbe46

Browse files
committed
Add unsafe-assume-single-core and related Cargo features.
1 parent dfbad88 commit b5fbe46

File tree

7 files changed

+91
-80
lines changed

7 files changed

+91
-80
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
with:
5252
event_name: ${{ github.event_name }}
5353
# Exclude serde and critical-section features because the MSRV when it is enabled depends on the MSRV of them
54-
args: -vvv --feature-powerset --depth 2 --optional-deps --exclude-features serde,critical-section,__do_not_enable
54+
args: -vvv --feature-powerset --depth 2 --optional-deps --exclude-features serde,critical-section,unsafe-assume-single-core,s-mode,disable-fiq
5555
tidy:
5656
uses: taiki-e/workflows/.github/workflows/tidy.yml@main
5757
with:

Cargo.toml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,16 @@ std = []
5353
# See documentation for more: https://github.com/taiki-e/portable-atomic#optional-features-require-cas
5454
require-cas = []
5555

56-
# DO NOT USE. This is NOT public API. Only used for testing our test infrastructures.
57-
# TODO: remove when adding real non-additive features.
58-
__do_not_enable = []
56+
# Assume the target is single core, to enable implementations based on disabling interrupts.
57+
# IMPORTANT: This feature is unsafe. See the documentation for the safety contract:
58+
# https://github.com/taiki-e/portable-atomic#optional-features-unsafe-assume-single-core
59+
unsafe-assume-single-core = []
60+
61+
# For RISC-V targets, generate code for S mode to disable interrupts.
62+
s-mode = []
63+
64+
# For ARM targets, also disable FIQs when disabling interrupts.
65+
disable-fiq = []
5966

6067
# Note: serde and critical-section are public dependencies.
6168
[dependencies]

README.md

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Portable atomic types including support for 128-bit atomics, atomic float, etc.
1414
- Provide `AtomicI128` and `AtomicU128`.
1515
- Provide `AtomicF32` and `AtomicF64`. ([optional, requires the `float` feature](#optional-features-float))
1616
- Provide atomic load/store for targets where atomic is not available at all in the standard library. (RISC-V without A-extension, MSP430, AVR)
17-
- Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 ARM, RISC-V without A-extension, MSP430, AVR, Xtensa, etc.) (always enabled for MSP430 and AVR, [optional](#optional-cfg) otherwise)
17+
- Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 ARM, RISC-V without A-extension, MSP430, AVR, Xtensa, etc.) (always enabled for MSP430 and AVR, [optional](#optional-features-critical-section) otherwise)
1818
- Provide stable equivalents of the standard library's atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108), [`AtomicBool::fetch_not`](https://github.com/rust-lang/rust/issues/98485).
1919
- Make features that require newer compilers, such as [`fetch_{max,min}`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_max), [`fetch_update`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_update), [`as_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.as_ptr), and [stronger CAS failure ordering](https://github.com/rust-lang/rust/pull/98383) available on Rust 1.34+.
2020
- Provide workaround for bugs in the standard library's atomic-related APIs, such as [rust-lang/rust#100650], `fence`/`compiler_fence` on MSP430 that cause LLVM error, etc.
@@ -89,21 +89,21 @@ See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic
8989
it is not natively available. When enabling it, you should provide a suitable critical section implementation
9090
for the current target, see the [critical-section] documentation for details on how to do so.
9191

92-
`critical-section` support is useful to get atomic CAS when `--cfg portable_atomic_unsafe_assume_single_core` can't be used,
92+
`critical-section` support is useful to get atomic CAS when the [`unsafe-assume-single-core` feature](#optional-features-unsafe-assume-single-core) can't be used,
9393
such as multi-core targets, unprivileged code running under some RTOS, or environments where disabling interrupts
9494
needs extra care due to e.g. real-time requirements.
9595

9696
Note that with the `critical-section` feature, critical sections are taken for all atomic operations, while with
97-
`--cfg portable_atomic_unsafe_assume_single_core` some operations don't require disabling interrupts (loads and stores, but
97+
`unsafe-assume-single-core` some operations don't require disabling interrupts (loads and stores, but
9898
additionally on MSP430 `add`, `sub`, `and`, `or`, `xor`, `not`). Therefore, for better performance, if
9999
all the `critical-section` implementation for your target does is disable interrupts, prefer using
100-
`--cfg portable_atomic_unsafe_assume_single_core` instead.
100+
`unsafe-assume-single-core` instead.
101101

102102
Note:
103103
- The MSRV when this feature is enabled depends on the MSRV of [critical-section].
104104
- It is usually *not* recommended to always enable this feature in dependencies of the library.
105105

106-
Enabling this feature will prevent the end user from having the chance to take advantage of other (potentially) efficient implementations ([Implementations provided by `--cfg portable_atomic_unsafe_assume_single_core`, default implementations on MSP430 and AVR](#optional-cfg), implementation proposed in [#60], etc. Other systems may also be supported in the future).
106+
Enabling this feature will prevent the end user from having the chance to take advantage of other (potentially) efficient implementations ([Implementations provided by `unsafe-assume-single-core`, default implementations on MSP430 and AVR](#optional-features-unsafe-assume-single-core), implementation proposed in [#60], etc. Other systems may also be supported in the future).
107107

108108
The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature. (However, it may make sense to enable this feature by default for libraries specific to a platform where other implementations are known not to work.)
109109

@@ -116,49 +116,49 @@ See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic
116116
crate-uses-portable-atomic-as-feature = { version = "...", features = ["portable-atomic"] }
117117
```
118118

119-
## Optional cfg
120-
121-
One of the ways to enable cfg is to set [rustflags in the cargo config](https://doc.rust-lang.org/cargo/reference/config.html#targettriplerustflags):
122-
123-
```toml
124-
# .cargo/config.toml
125-
[target.<target>]
126-
rustflags = ["--cfg", "portable_atomic_unsafe_assume_single_core"]
127-
```
128-
129-
Or set environment variable:
130-
131-
```sh
132-
RUSTFLAGS="--cfg portable_atomic_unsafe_assume_single_core" cargo ...
133-
```
134-
135-
- <a name="optional-cfg-unsafe-assume-single-core"></a>**`--cfg portable_atomic_unsafe_assume_single_core`**<br>
119+
- <a name="optional-features-unsafe-assume-single-core"></a>**`unsafe-assume-single-core`**<br>
136120
Assume that the target is single-core.
137-
When this cfg is enabled, this crate provides atomic CAS for targets where atomic CAS is not available in the standard library by disabling interrupts.
121+
When this feature is enabled, this crate provides atomic CAS for targets where atomic CAS is not available in the standard library by disabling interrupts.
138122

139-
This cfg is `unsafe`, and note the following safety requirements:
140-
- Enabling this cfg for multi-core systems is always **unsound**.
123+
This feature is `unsafe`, and note the following safety requirements:
124+
- Enabling this feature for multi-core systems is always **unsound**.
141125
- This uses privileged instructions to disable interrupts, so it usually doesn't work on unprivileged mode.
142-
Enabling this cfg in an environment where privileged instructions are not available, or if the instructions used are not sufficient to disable interrupts in the system, it is also usually considered **unsound**, although the details are system-dependent.
126+
Enabling this feature in an environment where privileged instructions are not available, or if the instructions used are not sufficient to disable interrupts in the system, it is also usually considered **unsound**, although the details are system-dependent.
143127

144128
The following are known cases:
145-
- On pre-v6 ARM, this disables only IRQs by default. For many systems (e.g., GBA) this is enough. If the system need to disable both IRQs and FIQs, you need to pass the `--cfg portable_atomic_disable_fiq` together.
146-
- On RISC-V without A-extension, this generates code for machine-mode (M-mode) by default. If you pass the `--cfg portable_atomic_s_mode` together, this generates code for supervisor-mode (S-mode). In particular, `qemu-system-riscv*` uses [OpenSBI](https://github.com/riscv-software-src/opensbi) as the default firmware.
129+
- On pre-v6 ARM, this disables only IRQs by default. For many systems (e.g., GBA) this is enough. If the system need to disable both IRQs and FIQs, you need to enable the `disable-fiq` feature together.
130+
- On RISC-V without A-extension, this generates code for machine-mode (M-mode) by default. If you enable the `s-mode` together, this generates code for supervisor-mode (S-mode). In particular, `qemu-system-riscv*` uses [OpenSBI](https://github.com/riscv-software-src/opensbi) as the default firmware.
147131

148132
See also [the `interrupt` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/interrupt/README.md).
149133

150-
Consider using the [`critical-section` feature](#optional-features-critical-section) for systems that cannot use this cfg.
134+
Consider using the [`critical-section` feature](#optional-features-critical-section) for systems that cannot use this feature.
151135

152-
This is intentionally not an optional feature. (If this is an optional feature, dependencies can implicitly enable the feature, resulting in the use of unsound code without the end-user being aware of it.)
136+
It is **very strongly discouraged** to enable this feature in libraries that depend on `portable-atomic`. The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature. (However, it may make sense to enable this feature by default for libraries specific to a platform where it is guaranteed to always be sound, for example in a hardware abstraction layer targeting a single-core chip.)
153137

154138
ARMv6-M (thumbv6m), pre-v6 ARM (e.g., thumbv4t, thumbv5te), RISC-V without A-extension, and Xtensa are currently supported.
155139

156-
Since all MSP430 and AVR are single-core, we always provide atomic CAS for them without this cfg.
140+
Since all MSP430 and AVR are single-core, we always provide atomic CAS for them without this feature.
157141

158-
Enabling this cfg for targets that have atomic CAS will result in a compile error.
142+
Enabling this feature for targets that have atomic CAS will result in a compile error.
159143

160144
Feel free to submit an issue if your target is not supported yet.
161145

146+
## Optional cfg
147+
148+
One of the ways to enable cfg is to set [rustflags in the cargo config](https://doc.rust-lang.org/cargo/reference/config.html#targettriplerustflags):
149+
150+
```toml
151+
# .cargo/config.toml
152+
[target.<target>]
153+
rustflags = ["--cfg", "portable_atomic_no_outline_atomics"]
154+
```
155+
156+
Or set environment variable:
157+
158+
```sh
159+
RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ...
160+
```
161+
162162
- <a name="optional-cfg-no-outline-atomics"></a>**`--cfg portable_atomic_no_outline_atomics`**<br>
163163
Disable dynamic dispatching by run-time CPU feature detection.
164164

build.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ fn main() {
1515
println!("cargo:rerun-if-changed=no_atomic.rs");
1616
println!("cargo:rerun-if-changed=version.rs");
1717

18+
#[cfg(feature = "unsafe-assume-single-core")]
19+
println!("cargo:rustc-cfg=portable_atomic_unsafe_assume_single_core");
20+
#[cfg(feature = "s-mode")]
21+
println!("cargo:rustc-cfg=portable_atomic_s_mode");
22+
#[cfg(feature = "disable-fiq")]
23+
println!("cargo:rustc-cfg=portable_atomic_disable_fiq");
24+
1825
let target = &*env::var("TARGET").expect("TARGET not set");
1926
let target_arch = &*env::var("CARGO_CFG_TARGET_ARCH").expect("CARGO_CFG_TARGET_ARCH not set");
2027
let target_os = &*env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS not set");

src/imp/interrupt/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@
33
This module is used to provide atomic CAS for targets where atomic CAS is not available in the standard library.
44

55
- On MSP430 and AVR, they are always single-core, so this module is always used.
6-
- On ARMv6-M (thumbv6m), pre-v6 ARM (e.g., thumbv4t, thumbv5te), RISC-V without A-extension, and Xtensa, they could be multi-core, so this module is used when `--cfg portable_atomic_unsafe_assume_single_core` is enabled.
6+
- On ARMv6-M (thumbv6m), pre-v6 ARM (e.g., thumbv4t, thumbv5te), RISC-V without A-extension, and Xtensa, they could be multi-core, so this module is used when the `unsafe-assume-single-core` feature is enabled.
77

88
The implementation uses privileged instructions to disable interrupts, so it usually doesn't work on unprivileged mode.
9-
Enabling this cfg in an environment where privileged instructions are not available, or if the instructions used are not sufficient to disable interrupts in the system, it is also usually considered **unsound**, although the details are system-dependent.
9+
Enabling this feature in an environment where privileged instructions are not available, or if the instructions used are not sufficient to disable interrupts in the system, it is also usually considered **unsound**, although the details are system-dependent.
1010

11-
Consider using the [`critical-section` feature](../../../README.md#optional-features-critical-section) for systems that cannot use `--cfg portable_atomic_unsafe_assume_single_core`.
11+
Consider using the [`critical-section` feature](../../../README.md#optional-features-critical-section) for systems that cannot use the `unsafe-assume-single-core` feature.
1212

13-
For some targets, the implementation can be changed by explicitly enabling cfg.
13+
For some targets, the implementation can be changed by explicitly enabling features.
1414

1515
- On ARMv6-M, this disables interrupts by modifying the PRIMASK register.
1616
- On pre-v6 ARM, this disables interrupts by modifying the I (IRQ mask) bit of the CPSR.
17-
- On pre-v6 ARM with `--cfg portable_atomic_disable_fiq`, this disables interrupts by modifying the I (IRQ mask) bit and F (FIQ mask) bit of the CPSR.
17+
- On pre-v6 ARM with the `disable-fiq` feature, this disables interrupts by modifying the I (IRQ mask) bit and F (FIQ mask) bit of the CPSR.
1818
- On RISC-V (without A-extension), this disables interrupts by modifying the MIE (Machine Interrupt Enable) bit of the `mstatus` register.
19-
- On RISC-V (without A-extension) with `--cfg portable_atomic_s_mode`, this disables interrupts by modifying the SIE (Supervisor Interrupt Enable) bit of the `sstatus` register.
19+
- On RISC-V (without A-extension) with the `s-mode` feature, this disables interrupts by modifying the SIE (Supervisor Interrupt Enable) bit of the `sstatus` register.
2020
- On MSP430, this disables interrupts by modifying the GIE (Global Interrupt Enable) bit of the status register (SR).
2121
- On AVR, this disables interrupts by modifying the I (Global Interrupt Enable) bit of the status register (SREG).
2222
- On Xtensa, this disables interrupts by modifying the PS special register.

0 commit comments

Comments
 (0)