std: Enable atomic.fence emission on wasm32
This commit removes the `#[cfg]` guards in `atomic::fence` on wasm
targets. Since these guards were originally added the upstream wasm
specification for threads gained an `atomic.fence` instruction, so LLVM
no longer panics on these intrinsics.
Although there aren't a ton of tests in-repo for this right now I've
tested locally and all of these fences generate `atomic.fence`
instructions in wasm.
Closes#65687Closes#72997
This commit removes the `#[cfg]` guards in `atomic::fence` on wasm
targets. Since these guards were originally added the upstream wasm
specification for threads gained an `atomic.fence` instruction, so LLVM
no longer panics on these intrinsics.
Although there aren't a ton of tests in-repo for this right now I've
tested locally and all of these fences generate `atomic.fence`
instructions in wasm.
Closes#72997
Stabilize AtomicN::fetch_min and AtomicN::fetch_max
Some architectures (ARMv8.1 LSE and RISC-V) have specific instructions for atomic min/max which the compiler can only generate through explicit instrinsics.
Using a pure spin lock for a critical section in a preemptable thread
is always wrong, however short the critical section may be. The thread
might be preempted, which will cause all other threads to hammer
busily at the core for the whole quant. Moreover, if threads have
different priorities, this might lead to a priority inversion problem
and a deadlock. More generally, a spinlock is not more efficient than
a well-written mutex, which typically does several spin iterations at
the start anyway.
The advise about UP vs SMP is also irrelevant in the context of
preemptive threads.
Atomic as_mut_ptr
I encountered the following pattern a few times: In Rust we use some atomic type like `AtomicI32`, and an FFI interface exposes this as `*mut i32` (or some similar `libc` type).
It was not obvious to me if a just transmuting a pointer to the atomic was acceptable, or if this should use a cast that goes through an `UnsafeCell`. See https://github.com/rust-lang/rust/issues/66136#issuecomment-557802477
Transmuting the pointer directly:
```rust
let atomic = AtomicI32::new(1);
let ptr = &atomic as *const AtomicI32 as *mut i32;
unsafe {
ffi(ptr);
}
```
A dance with `UnsafeCell`:
```rust
let atomic = AtomicI32::new(1);
unsafe {
let ptr = (&*(&atomic as *const AtomicI32 as *const UnsafeCell<i32>)).get();
ffi(ptr);
}
```
Maybe in the end both ways could be valid. But why not expose a direct method to get a pointer from the standard library?
An `as_mut_ptr` method on atomics can be safe, because only the use of the resulting pointer is where things can get unsafe. I documented its use for FFI, and "Doing non-atomic reads and writes on the resulting integer can be a data race."
The standard library could make use this method in a few places in the WASM module.
cc @RalfJung as you answered my original question.
Split non-CAS atomic support off into target_has_atomic_load_store
This PR implements my proposed changes in https://github.com/rust-lang/rust/issues/32976#issuecomment-518542029 by removing `target_has_atomic = "cas"` and splitting `target_has_atomic` into two separate `cfg`s:
* `target_has_atomic = 8/16/32/64/128`: This indicates the largest width that the target can atomically CAS (which implies support for all atomic operations).
* ` target_has_atomic_load_store = 8/16/32/64/128`: This indicates the largest width that the target can support loading or storing atomically (but may not support CAS).
cc #32976
r? @alexcrichton
PR: documentation spin loop hint
The documentation for 'spin loop hint' explains that yield is better if the lock holder is running on the same CPU. I suggest that 'CPU or core' would be clearer.