Skip to content

Commit b5fa39e

Browse files
bors[bot]taiki-e
andauthored
Merge #31
31: Always provide atomic CAS for MSP430 and AVR r=taiki-e a=taiki-e This previously required unsafe cfg `portable_atomic_unsafe_assume_single_core`, but since all MSP430 and AVR are single-core, we can safely provide atomic CAS based on disabling interrupts. Thanks `@cr1901` for pointing out this in pftbest/msp430-atomic#6 (comment). Co-authored-by: Taiki Endo <te316e89@gmail.com>
2 parents a4aec1e + 668c029 commit b5fa39e

File tree

7 files changed

+567
-174
lines changed

7 files changed

+567
-174
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com
1010

1111
## [Unreleased]
1212

13+
- Always provide atomic CAS for MSP430 and AVR.
14+
15+
This previously required unsafe cfg `portable_atomic_unsafe_assume_single_core`, but since all MSP430 and AVR are single-core, we can safely provide atomic CAS based on disabling interrupts.
16+
1317
- Support `fence` and `compiler_fence` on MSP430.
1418

1519
- Update safety requirements for unsafe cfg `portable_atomic_unsafe_assume_single_core` to mention use of privileged instructions to disable interrupts.

README.md

Lines changed: 4 additions & 2 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 `AtomicF32` and `AtomicF64`. (optional)
1515
<!-- - Provide generic `Atomic<T>` type. (optional) -->
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, RISC-V without A-extension, MSP430, AVR) (optional, [single-core only](#optional-cfg))
17+
- Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, RISC-V without A-extension, MSP430, AVR) (optional and [single-core only](#optional-cfg) for ARM and RISC-V, always enabled for MSP430 and AVR)
1818
- Provide equivalents on the target that the standard library's atomic-related APIs cause LLVM errors. (fence/compiler_fence on MSP430)
1919
- Provide stable equivalents of the standard library 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).
2020
- Make features that require newer compilers, such as [fetch_max](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_max), [fetch_min](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_min), [fetch_update](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicPtr.html#method.fetch_update), and [stronger CAS failure ordering](https://github.com/rust-lang/rust/pull/98383) available on Rust 1.34+.
@@ -79,7 +79,9 @@ See [this list](https://github.com/taiki-e/portable-atomic/issues/10#issuecommen
7979

8080
Enabling this cfg for targets that have atomic CAS will result in a compile error.
8181

82-
ARMv6-M (thumbv6m), RISC-V without A-extension, MSP430, and AVR are currently supported. See [#26] for support of no-std pre-v6 ARM and multi-core systems.
82+
ARMv6-M (thumbv6m), RISC-V without A-extension are currently supported. See [#26] for support of no-std pre-v6 ARM and multi-core systems.
83+
84+
Since all MSP430 and AVR are single-core, we always provide atomic CAS for them without this cfg.
8385

8486
Feel free to submit an issue if your target is not supported yet.
8587

src/imp/interrupt/mod.rs

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//
1616
// AVR, which is single core[^avr1] and LLVM also generates code that disables
1717
// interrupts [^avr2] in atomic ops by default, is considered the latter.
18+
// MSP430 as well.
1819
//
1920
// [^avr1]: https://github.com/llvm/llvm-project/blob/llvmorg-15.0.0-rc1/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp#L1008
2021
// [^avr2]: https://github.com/llvm/llvm-project/blob/llvmorg-15.0.0-rc1/llvm/test/CodeGen/AVR/atomics/load16.ll#L5
@@ -138,7 +139,6 @@ impl AtomicBool {
138139
}
139140
}
140141

141-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
142142
#[inline]
143143
pub(crate) fn swap(&self, val: bool, _order: Ordering) -> bool {
144144
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -147,7 +147,6 @@ impl AtomicBool {
147147
with(|| unsafe { self.v.get().replace(val as u8) != 0 })
148148
}
149149

150-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
151150
#[inline]
152151
pub(crate) fn compare_exchange(
153152
&self,
@@ -171,7 +170,6 @@ impl AtomicBool {
171170
})
172171
}
173172

174-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
175173
#[inline]
176174
pub(crate) fn compare_exchange_weak(
177175
&self,
@@ -183,7 +181,6 @@ impl AtomicBool {
183181
self.compare_exchange(current, new, success, failure)
184182
}
185183

186-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
187184
#[inline]
188185
pub(crate) fn fetch_and(&self, val: bool, _order: Ordering) -> bool {
189186
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -196,7 +193,6 @@ impl AtomicBool {
196193
})
197194
}
198195

199-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
200196
#[inline]
201197
pub(crate) fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
202198
if val {
@@ -210,7 +206,6 @@ impl AtomicBool {
210206
}
211207
}
212208

213-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
214209
#[inline]
215210
pub(crate) fn fetch_or(&self, val: bool, _order: Ordering) -> bool {
216211
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -223,7 +218,6 @@ impl AtomicBool {
223218
})
224219
}
225220

226-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
227221
#[inline]
228222
pub(crate) fn fetch_xor(&self, val: bool, _order: Ordering) -> bool {
229223
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -317,7 +311,6 @@ impl<T> AtomicPtr<T> {
317311
}
318312
}
319313

320-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
321314
#[inline]
322315
pub(crate) fn swap(&self, ptr: *mut T, _order: Ordering) -> *mut T {
323316
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -326,7 +319,6 @@ impl<T> AtomicPtr<T> {
326319
with(|| unsafe { self.p.get().replace(ptr) })
327320
}
328321

329-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
330322
#[inline]
331323
pub(crate) fn compare_exchange(
332324
&self,
@@ -350,7 +342,6 @@ impl<T> AtomicPtr<T> {
350342
})
351343
}
352344

353-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
354345
#[inline]
355346
pub(crate) fn compare_exchange_weak(
356347
&self,
@@ -472,7 +463,6 @@ macro_rules! atomic_int {
472463
};
473464
(cas, $atomic_type:ident, $int_type:ident, $align:expr) => {
474465
impl $atomic_type {
475-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
476466
#[inline]
477467
pub(crate) fn swap(&self, val: $int_type, _order: Ordering) -> $int_type {
478468
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -481,7 +471,6 @@ macro_rules! atomic_int {
481471
with(|| unsafe { self.v.get().replace(val) })
482472
}
483473

484-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
485474
#[inline]
486475
pub(crate) fn compare_exchange(
487476
&self,
@@ -505,7 +494,6 @@ macro_rules! atomic_int {
505494
})
506495
}
507496

508-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
509497
#[inline]
510498
pub(crate) fn compare_exchange_weak(
511499
&self,
@@ -517,7 +505,6 @@ macro_rules! atomic_int {
517505
self.compare_exchange(current, new, success, failure)
518506
}
519507

520-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
521508
#[inline]
522509
pub(crate) fn fetch_add(&self, val: $int_type, _order: Ordering) -> $int_type {
523510
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -530,7 +517,6 @@ macro_rules! atomic_int {
530517
})
531518
}
532519

533-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
534520
#[inline]
535521
pub(crate) fn fetch_sub(&self, val: $int_type, _order: Ordering) -> $int_type {
536522
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -543,7 +529,6 @@ macro_rules! atomic_int {
543529
})
544530
}
545531

546-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
547532
#[inline]
548533
pub(crate) fn fetch_and(&self, val: $int_type, _order: Ordering) -> $int_type {
549534
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -556,7 +541,6 @@ macro_rules! atomic_int {
556541
})
557542
}
558543

559-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
560544
#[inline]
561545
pub(crate) fn fetch_nand(&self, val: $int_type, _order: Ordering) -> $int_type {
562546
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -569,7 +553,6 @@ macro_rules! atomic_int {
569553
})
570554
}
571555

572-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
573556
#[inline]
574557
pub(crate) fn fetch_or(&self, val: $int_type, _order: Ordering) -> $int_type {
575558
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -582,7 +565,6 @@ macro_rules! atomic_int {
582565
})
583566
}
584567

585-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
586568
#[inline]
587569
pub(crate) fn fetch_xor(&self, val: $int_type, _order: Ordering) -> $int_type {
588570
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -595,7 +577,6 @@ macro_rules! atomic_int {
595577
})
596578
}
597579

598-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
599580
#[inline]
600581
pub(crate) fn fetch_max(&self, val: $int_type, _order: Ordering) -> $int_type {
601582
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -608,7 +589,6 @@ macro_rules! atomic_int {
608589
})
609590
}
610591

611-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
612592
#[inline]
613593
pub(crate) fn fetch_min(&self, val: $int_type, _order: Ordering) -> $int_type {
614594
// SAFETY: any data races are prevented by disabling interrupts (see
@@ -647,34 +627,30 @@ atomic_int!(load_store_atomic, AtomicI16, i16, 2);
647627
atomic_int!(load_store_atomic, AtomicU16, u16, 2);
648628

649629
#[cfg(not(target_pointer_width = "16"))]
650-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
651630
atomic_int!(load_store_atomic, AtomicI32, i32, 4);
652631
#[cfg(not(target_pointer_width = "16"))]
653-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
654632
atomic_int!(load_store_atomic, AtomicU32, u32, 4);
655633
#[cfg(target_pointer_width = "16")]
656-
#[cfg(any(test, all(feature = "fallback", portable_atomic_unsafe_assume_single_core)))]
634+
#[cfg(any(test, feature = "fallback"))]
657635
atomic_int!(load_store_critical_session, AtomicI32, i32, 4);
658636
#[cfg(target_pointer_width = "16")]
659-
#[cfg(any(test, all(feature = "fallback", portable_atomic_unsafe_assume_single_core)))]
637+
#[cfg(any(test, feature = "fallback"))]
660638
atomic_int!(load_store_critical_session, AtomicU32, u32, 4);
661639

662640
#[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))]
663-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
664641
atomic_int!(load_store_atomic, AtomicI64, i64, 8);
665642
#[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))]
666-
#[cfg(any(test, portable_atomic_unsafe_assume_single_core))]
667643
atomic_int!(load_store_atomic, AtomicU64, u64, 8);
668644
#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
669-
#[cfg(any(test, all(feature = "fallback", portable_atomic_unsafe_assume_single_core)))]
645+
#[cfg(any(test, feature = "fallback"))]
670646
atomic_int!(load_store_critical_session, AtomicI64, i64, 8);
671647
#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
672-
#[cfg(any(test, all(feature = "fallback", portable_atomic_unsafe_assume_single_core)))]
648+
#[cfg(any(test, feature = "fallback"))]
673649
atomic_int!(load_store_critical_session, AtomicU64, u64, 8);
674650

675-
#[cfg(any(test, all(feature = "fallback", portable_atomic_unsafe_assume_single_core)))]
651+
#[cfg(any(test, feature = "fallback"))]
676652
atomic_int!(load_store_critical_session, AtomicI128, i128, 16);
677-
#[cfg(any(test, all(feature = "fallback", portable_atomic_unsafe_assume_single_core)))]
653+
#[cfg(any(test, feature = "fallback"))]
678654
atomic_int!(load_store_critical_session, AtomicU128, u128, 16);
679655

680656
#[cfg(test)]

src/imp/mod.rs

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,12 @@ mod fallback;
9898
// On AVR, we always use critical section based fallback implementation.
9999
// AVR can be safely assumed to be single-core, so this is sound.
100100
// https://github.com/llvm/llvm-project/blob/llvmorg-15.0.0-rc1/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp#L1008
101+
// MSP430 as well.
101102
#[cfg(any(
102103
all(test, target_os = "none"),
103104
portable_atomic_unsafe_assume_single_core,
104-
target_arch = "avr"
105+
target_arch = "avr",
106+
target_arch = "msp430",
105107
))]
106108
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(any(test, portable_atomic_no_atomic_cas)))]
107109
#[cfg_attr(
@@ -147,12 +149,6 @@ mod interrupt;
147149
pub(crate) use self::core_atomic::{
148150
AtomicBool, AtomicI16, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU8, AtomicUsize,
149151
};
150-
// MSP430
151-
#[cfg(not(portable_atomic_unsafe_assume_single_core))]
152-
#[cfg(target_arch = "msp430")]
153-
pub(crate) use self::msp430::{
154-
AtomicBool, AtomicI16, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU8, AtomicUsize,
155-
};
156152
// RISC-V without A-extension
157153
#[cfg(not(portable_atomic_unsafe_assume_single_core))]
158154
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
@@ -162,15 +158,13 @@ pub(crate) use self::riscv::{
162158
AtomicBool, AtomicI16, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU8, AtomicUsize,
163159
};
164160
// no core Atomic{Isize,Usize,Bool,Ptr}/Atomic{I,U}{8,16} & assume single core => critical section based fallback
165-
#[cfg(any(portable_atomic_unsafe_assume_single_core, target_arch = "avr"))]
166-
#[cfg_attr(
167-
portable_atomic_no_cfg_target_has_atomic,
168-
cfg(any(portable_atomic_no_atomic_cas, target_arch = "avr"))
169-
)]
170-
#[cfg_attr(
171-
not(portable_atomic_no_cfg_target_has_atomic),
172-
cfg(any(not(target_has_atomic = "ptr"), target_arch = "avr"))
173-
)]
161+
#[cfg(any(
162+
portable_atomic_unsafe_assume_single_core,
163+
target_arch = "avr",
164+
target_arch = "msp430"
165+
))]
166+
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_cas))]
167+
#[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "ptr")))]
174168
pub(crate) use self::interrupt::{
175169
AtomicBool, AtomicI16, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU8, AtomicUsize,
176170
};
@@ -210,7 +204,11 @@ pub(crate) use self::core_atomic::{AtomicI32, AtomicU32};
210204
pub(crate) use self::riscv::{AtomicI32, AtomicU32};
211205
// no core Atomic{I,U}32 & no CAS & assume single core => critical section based fallback
212206
#[cfg(any(not(target_pointer_width = "16"), feature = "fallback"))]
213-
#[cfg(portable_atomic_unsafe_assume_single_core)]
207+
#[cfg(any(
208+
portable_atomic_unsafe_assume_single_core,
209+
target_arch = "avr",
210+
target_arch = "msp430"
211+
))]
214212
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_cas))]
215213
#[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "ptr")))]
216214
pub(crate) use self::interrupt::{AtomicI32, AtomicU32};
@@ -251,7 +249,11 @@ pub(crate) use self::fallback::{AtomicI64, AtomicU64};
251249
not(any(target_pointer_width = "16", target_pointer_width = "32")),
252250
feature = "fallback"
253251
))]
254-
#[cfg(portable_atomic_unsafe_assume_single_core)]
252+
#[cfg(any(
253+
portable_atomic_unsafe_assume_single_core,
254+
target_arch = "avr",
255+
target_arch = "msp430"
256+
))]
255257
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_cas))]
256258
#[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "ptr")))]
257259
pub(crate) use self::interrupt::{AtomicI64, AtomicU64};
@@ -316,7 +318,11 @@ pub(crate) use self::s390x::{AtomicI128, AtomicU128};
316318
pub(crate) use self::fallback::{AtomicI128, AtomicU128};
317319
// no core Atomic{I,U}128 & no CAS & assume_single_core => critical section based fallback
318320
#[cfg(feature = "fallback")]
319-
#[cfg(portable_atomic_unsafe_assume_single_core)]
321+
#[cfg(any(
322+
portable_atomic_unsafe_assume_single_core,
323+
target_arch = "avr",
324+
target_arch = "msp430"
325+
))]
320326
#[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_cas))]
321327
#[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "ptr")))]
322328
pub(crate) use self::interrupt::{AtomicI128, AtomicU128};

0 commit comments

Comments
 (0)