Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking issue for #[cfg(target_has_atomic = ...)] #32976

Open
alexcrichton opened this Issue Apr 14, 2016 · 82 comments

Comments

Projects
None yet
@alexcrichton
Copy link
Member

alexcrichton commented Apr 14, 2016

bors added a commit that referenced this issue May 5, 2016

Auto merge of #33048 - Amanieu:integer_atomics, r=alexcrichton
Add integer atomic types

Tracking issue: #32976
RFC: rust-lang/rfcs#1543

The changes to AtomicBool in the RFC are not included, they are in a separate PR (#32365).

bors added a commit that referenced this issue May 6, 2016

Auto merge of #33048 - Amanieu:integer_atomics, r=alexcrichton
Add integer atomic types

Tracking issue: #32976
RFC: rust-lang/rfcs#1543

The changes to AtomicBool in the RFC are not included, they are in a separate PR (#32365).

bors added a commit that referenced this issue May 6, 2016

Auto merge of #33048 - Amanieu:integer_atomics, r=alexcrichton
Add integer atomic types

Tracking issue: #32976
RFC: rust-lang/rfcs#1543

The changes to AtomicBool in the RFC are not included, they are in a separate PR (#32365).

bors added a commit that referenced this issue May 9, 2016

Auto merge of #33048 - Amanieu:integer_atomics, r=alexcrichton
Add integer atomic types

Tracking issue: #32976
RFC: rust-lang/rfcs#1543

The changes to AtomicBool in the RFC are not included, they are in a separate PR (#32365).

@sfackler sfackler removed the I-nominated label Sep 7, 2016

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Sep 7, 2016

This is still blocked on some reasonable way to talk about platform-specificity in a more granular way than what we currently support.

@Manishearth

This comment has been minimized.

Copy link
Member

Manishearth commented Oct 4, 2016

Is there any reason why AtomicU32 would be hard to stabilize? We need a way to store multi-word bitflags in an atomic thingy. AtomicUsize won't work here since it's too large on 64 bit.

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Oct 5, 2016

What do you mean by "too large"?

@Manishearth

This comment has been minimized.

Copy link
Member

Manishearth commented Oct 5, 2016

Let's say I have a 64-bit bucket of flags. I need two atomic u32s to represent it. I can't use two usizes because that's too large on 64 bit.

Alternatively, let's say I have a 32-bit bucket of flags. This is on a struct where size matters. I need a u32, not something larger on 64-bit.

I guess I could cfg() it and abstract over it. That solves the first problem but not the second.

@nagisa

This comment has been minimized.

Copy link
Contributor

nagisa commented Oct 5, 2016

@Manishearth 16-bit-usize targets would give you 16 bit atomic width. 100% savings over 32bit systems! (and potential loss of data)

There isn’t really much problem stabilising any of these IMO, but you’ll still have to CFG on target_has_atomic="32" in your code.

@Manishearth

This comment has been minimized.

Copy link
Member

Manishearth commented Oct 5, 2016

16-bit-usize targets would give you 16 bit atomic width.

ugh, these exist, right.

What do I have to do to get these stabilized? I'm okay with the cfgs.

I'm also okay with just u8 being stabilized, as long as I can pack it (not sure if this is possible with atomics)

@Manishearth

This comment has been minimized.

Copy link
Member

Manishearth commented Dec 15, 2016

What do I have to do to get these stabilized?

Any answer on this? cc @alexcrichton

The rfc looks like it's been completely implemented. IMO stabilizing it with target_has_atomic is fine, and we can add further granularity if we need in new rfcs.

@alexcrichton

This comment has been minimized.

Copy link
Member Author

alexcrichton commented Dec 16, 2016

@Manishearth state hasn't changed from before. The libs team is essentially waiting for a conclusion on the scenarios story before stabilizing.

@Manishearth

This comment has been minimized.

Copy link
Member

Manishearth commented Dec 16, 2016

That discussion has stalled. Last I checked it seemed to mostly have come to consensus on the general idea? Who are we waiting on for a conclusion here? What would the ETA on this be? How can I help?

It also seems like that's mostly orthogonal to this. We can stabilize this using cfgs, and add scenarios later. They seem to be pretty compatible.

@Manishearth

This comment has been minimized.

Copy link
Member

Manishearth commented Dec 16, 2016

(After discussing in IRC, it seems like there have been a lot of recent discussions about this, and the libs team is currently moving on pushing this forward.)

@archshift

This comment has been minimized.

Copy link

archshift commented Jan 15, 2017

Has there been any progress on this since?

@bholley

This comment has been minimized.

Copy link
Contributor

bholley commented Feb 4, 2017

Just FYI: Per [1], Gecko's Quantum CSS project is no longer blocked on this issue.

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1336646

@nagisa

This comment has been minimized.

Copy link
Contributor

nagisa commented May 7, 2017

We can stabilise AtomicU8 and AtomicI8 the same way we have stabilised AtomicBool – by using Atomic{I/U}Size operations everywhere.

@alexcrichton

This comment has been minimized.

Copy link
Member Author

alexcrichton commented Dec 12, 2018

@RalfJung correct, that's what convinced me personally that we can't do this on crates.io, which means if we want it at all we need it in the standard library (via LLVM intrinsics). I think we want it, so I'm convinced to put it into libstd :)

@Amanieu

This comment has been minimized.

Copy link
Contributor

Amanieu commented Dec 12, 2018

@RalfJung This lowering is done either within LLVM, or through a function in compiler_builtins.

The latter is currently only used on armv5te-unknown-linux-gnu at the moment, and uses this code. It could be argued that this is UB since intrinsics::atomic_load_unordered could be used to read out-of-bounds data, however this is guaranteed not to fault because it doesn't cross a page boundary.

@RalfJung

This comment has been minimized.

Copy link
Member

RalfJung commented Dec 12, 2018

@alexcrichton makes sense!

@Amanieu

It could be argued that this is UB

And the argument would be correct :)

is guaranteed not to fault because it doesn't cross a page boundary.

And as in the last N cases we have had this argument (and as I am sure you are aware, but not everybody else might be), that doesn't change anything about this being UB when we are talking about code written in Rust, MIR or LLVM IR. ;) (I am beginning to feel sorry for being so annoying about this, but LLVM is way too smart and getting smarter every day, so I am actively worried that such arguments will blow in our face some day.)

Is this a pattern supported/intended by LLVM? Is there advise from the LLVM devs for how to do this?

Is there any chance of LLVM ever inlining those compiler-builtins functions? Actually even having them in the same translation unit could be enough to cause problems, because LLVM could infer attributes on the functions to propagate information about what they do out to use sites.

One safer alternative would be to use inline assembly to implement such operations, that would most likely exclude any way for LLVM to notice that there are out-of-bounds accesses. But I am not sure if that's an option here.

@Amanieu

This comment has been minimized.

Copy link
Contributor

Amanieu commented Dec 12, 2018

The code is more-or-less based on the GCC implementation, which gets away with a normal atomic load.

Would changing the load to a volatile atomic load help in this case?

@alexcrichton

This comment has been minimized.

Copy link
Member Author

alexcrichton commented Dec 12, 2018

To add to what @RalfJung is saying, @Amanieu just because it works at the hardware layer doesn't mean it's UB in LLVM's IR. For example this function:

define i8 @bar() {
start:                                  
  %a = alloca i8                        
  store i8 0, i8* %a                    
  %b = call i8 @foo(i8* %a)             
  ret i8 %b                             
}                                       
                                        
define internal i8 @foo(i8*) {          
start:                                  
  %b = getelementptr i8, i8* %0, i32 1  
  %a = load i8, i8* %b                  
  ret i8 %a                             
}                                       

is sort of a simplisitic view but it's guaranteed to never fault because the out-of-bounds load will just load some byte of the return address on the call stacsk or something weird like that. When optimized, however, it yields:

define i8 @bar() local_unnamed_addr #0 {
start:
  ret i8 undef
}

(a showing that this is undefined behavior)

LLVM can't automatically deduce that all instances of this pattern is undefined behavior, in isolation foo optimized just fine. That's why compiler-builtins happens to work, we're forcing LLVM to have less knowledge about the inputs so it just-so-happens that it can't deduce that undefined behavior is happening.

All that's just to say that @RalfJung I think is totally correct here, a crates.io based implementation of smaller-sized atomics with larger-sized atomics I think is just a segfault waiting to happen. LLVM may not even detect it's UB today, but it's definitely UB at the LLVM IR layer (and probably the Rust layer) to read out of bounds on objects. Why exactly it's UB or what exactly happens is always up for grabs which is why it works most of the time, but this is fundamentally why we need LLVM's backend to do the lowering because the IR passes need to see that we're just modifying/loading one byte, not the bytes around it

@gnzlbg

This comment has been minimized.

Copy link
Contributor

gnzlbg commented Dec 13, 2018

The operations that @Amanieu wants to perform cannot be performed by a programming language generating LLVM-IR directly. Inline assembly appears to be the only way to perform these right now, so we could still expose them I think (@RalfJung ? I don't know whether compiler-builtins would work too).

In the meantime, I think it would be better to open an issue in the LLVM bugzilla about this, explaining why these operations are useful, why the LLVM-IR generated for them has undefined behavior, and how that requires us to use inline assembly (or modify compiler-builtins) instead. We should ask: what should we do? Should we use inline assembly / our own compiler built-ins ? Will LLVM expose intrinsics to allow these safely? etc.

It might be worth mentioning that this is not the only situation in which we need to perform reads out-of-bounds (see rust-lang/unsafe-code-guidelines#2).

@RalfJung

This comment has been minimized.

Copy link
Member

RalfJung commented Dec 13, 2018

Would changing the load to a volatile atomic load help in this case?

No. Volatile reads in practice have some positive effects on racy reads (but LLVM may change those rules any time as we are relying on de-facto behavior here). It doesn't change anything about the requirement that accesses must be in-bounds.

The proper way to fox this is (as @gnzlbg mentioned) to add an attribute to LLVM that can be set on reads/writes and that indicates that the access may be partially out-of-bounds. Then we need a matching intrinsic in Rust, and methods such as read_out_of_bounds and write_out_of_bounds on pointers. Considering we need this for concurrency, we'd also need to think about how to expose atomic out-of-bounds accesses in Rust. Anything else (anything just arguing based on page boundaries but not informing LLVM) will remain a hack. Given that this seems to be a useful pattern, I absolutely think we should lobby for LLVM to add such an attribute!

just because it works at the hardware layer doesn't mean it's UB in LLVM's IR. For example this function

Thanks for the example, I'll link to this when such discussions come up again in the future. :)

That's why compiler-builtins happens to work, we're forcing LLVM to have less knowledge about the inputs so it just-so-happens that it can't deduce that undefined behavior is happening.

That sounds way less confident than I had hoped...

When does compiler-builtins get linked with the real program? Is there a chance that LTO might inline compiler-builtins functions (which then would mean LLVM could deduce the UB)?

@nikic

This comment has been minimized.

Copy link
Contributor

nikic commented Dec 13, 2018

When does compiler-builtins get linked with the real program? Is there a chance that LTO might inline compiler-builtins functions (which then would mean LLVM could deduce the UB)?

As rtlib calls are only inserted at the SelectionDAG layer, while LTO still operates on LLVM IR, I don't believe there is any possibility of these getting inlined.

@alexcrichton

This comment has been minimized.

Copy link
Member Author

alexcrichton commented Dec 13, 2018

@nikic is correct, we explicitly don't LTO compiler-builtins as well (it's a very special crate). In that sense there's no worry for inlining compiler-builtins intrinsics.

@RalfJung

This comment has been minimized.

Copy link
Member

RalfJung commented Dec 13, 2018

Okay. I can live with that. We should keep it in mind though for the future, if/when compiler-builtins treatment ever changes.

So, yeah, I agree we should go forward with such "emulated" small-int atomics implemented via LLVM lowering or compiler-builtints.

@alexcrichton

This comment has been minimized.

Copy link
Member Author

alexcrichton commented Jan 7, 2019

For those following this thread, the stabilization proposal is now in FCP

alexcrichton added a commit to alexcrichton/rust that referenced this issue Jan 7, 2019

std: Stabilize fixed-width integer atomics
This commit stabilizes the `Atomic{I,U}{8,16,32,64}` APIs in the
`std::sync::atomic` and `core::sync::atomic` modules. Proposed in rust-lang#56753
and tracked in rust-lang#32976 this feature has been unstable for quite some time
and is hopefully ready to go over the finish line now!

The API is being stabilized as-is. The API of `AtomicU8` and friends
mirrors that of `AtomicUsize`. A list of changes made here are:

* A portability documentation section has been added to describe the
  current state of affairs.
* Emulation of smaller-size atomics with larger-size atomics has been
  documented.
* As an added bonus, `ATOMIC_*_INIT` is now scheduled for deprecation
  across the board in 1.34.0 now that `const` functions can be invoked
  in statics.

Note that the 128-bit atomic types are omitted from this stabilization
explicitly. They have far less platform support than the other atomic
types, and will likely require further discussion about their best
location.

Closes rust-lang#32976
Closes rust-lang#56753

alexcrichton added a commit to alexcrichton/rust that referenced this issue Jan 8, 2019

std: Stabilize fixed-width integer atomics
This commit stabilizes the `Atomic{I,U}{8,16,32,64}` APIs in the
`std::sync::atomic` and `core::sync::atomic` modules. Proposed in rust-lang#56753
and tracked in rust-lang#32976 this feature has been unstable for quite some time
and is hopefully ready to go over the finish line now!

The API is being stabilized as-is. The API of `AtomicU8` and friends
mirrors that of `AtomicUsize`. A list of changes made here are:

* A portability documentation section has been added to describe the
  current state of affairs.
* Emulation of smaller-size atomics with larger-size atomics has been
  documented.
* As an added bonus, `ATOMIC_*_INIT` is now scheduled for deprecation
  across the board in 1.34.0 now that `const` functions can be invoked
  in statics.

Note that the 128-bit atomic types are omitted from this stabilization
explicitly. They have far less platform support than the other atomic
types, and will likely require further discussion about their best
location.

Closes rust-lang#32976
Closes rust-lang#56753

alexcrichton added a commit to alexcrichton/rust that referenced this issue Jan 25, 2019

std: Stabilize fixed-width integer atomics
This commit stabilizes the `Atomic{I,U}{8,16,32,64}` APIs in the
`std::sync::atomic` and `core::sync::atomic` modules. Proposed in rust-lang#56753
and tracked in rust-lang#32976 this feature has been unstable for quite some time
and is hopefully ready to go over the finish line now!

The API is being stabilized as-is. The API of `AtomicU8` and friends
mirrors that of `AtomicUsize`. A list of changes made here are:

* A portability documentation section has been added to describe the
  current state of affairs.
* Emulation of smaller-size atomics with larger-size atomics has been
  documented.
* As an added bonus, `ATOMIC_*_INIT` is now scheduled for deprecation
  across the board in 1.34.0 now that `const` functions can be invoked
  in statics.

Note that the 128-bit atomic types are omitted from this stabilization
explicitly. They have far less platform support than the other atomic
types, and will likely require further discussion about their best
location.

Closes rust-lang#32976
Closes rust-lang#56753

Centril added a commit to Centril/rust that referenced this issue Jan 26, 2019

Rollup merge of rust-lang#57425 - alexcrichton:stabilize-atomics, r=s…
…fackler

std: Stabilize fixed-width integer atomics

This commit stabilizes the `Atomic{I,U}{8,16,32,64}` APIs in the
`std::sync::atomic` and `core::sync::atomic` modules. Proposed in rust-lang#56753
and tracked in rust-lang#32976 this feature has been unstable for quite some time
and is hopefully ready to go over the finish line now!

The API is being stabilized as-is. The API of `AtomicU8` and friends
mirrors that of `AtomicUsize`. A list of changes made here are:

* A portability documentation section has been added to describe the
  current state of affairs.
* Emulation of smaller-size atomics with larger-size atomics has been
  documented.
* As an added bonus, `ATOMIC_*_INIT` is now scheduled for deprecation
  across the board in 1.34.0 now that `const` functions can be invoked
  in statics.

Note that the 128-bit atomic types are omitted from this stabilization
explicitly. They have far less platform support than the other atomic
types, and will likely require further discussion about their best
location.

Closes rust-lang#32976
Closes rust-lang#56753

Centril added a commit to Centril/rust that referenced this issue Jan 26, 2019

Rollup merge of rust-lang#57425 - alexcrichton:stabilize-atomics, r=s…
…fackler

std: Stabilize fixed-width integer atomics

This commit stabilizes the `Atomic{I,U}{8,16,32,64}` APIs in the
`std::sync::atomic` and `core::sync::atomic` modules. Proposed in rust-lang#56753
and tracked in rust-lang#32976 this feature has been unstable for quite some time
and is hopefully ready to go over the finish line now!

The API is being stabilized as-is. The API of `AtomicU8` and friends
mirrors that of `AtomicUsize`. A list of changes made here are:

* A portability documentation section has been added to describe the
  current state of affairs.
* Emulation of smaller-size atomics with larger-size atomics has been
  documented.
* As an added bonus, `ATOMIC_*_INIT` is now scheduled for deprecation
  across the board in 1.34.0 now that `const` functions can be invoked
  in statics.

Note that the 128-bit atomic types are omitted from this stabilization
explicitly. They have far less platform support than the other atomic
types, and will likely require further discussion about their best
location.

Closes rust-lang#32976
Closes rust-lang#56753

bors added a commit that referenced this issue Jan 26, 2019

Auto merge of #57425 - alexcrichton:stabilize-atomics, r=sfackler
std: Stabilize fixed-width integer atomics

This commit stabilizes the `Atomic{I,U}{8,16,32,64}` APIs in the
`std::sync::atomic` and `core::sync::atomic` modules. Proposed in #56753
and tracked in #32976 this feature has been unstable for quite some time
and is hopefully ready to go over the finish line now!

The API is being stabilized as-is. The API of `AtomicU8` and friends
mirrors that of `AtomicUsize`. A list of changes made here are:

* A portability documentation section has been added to describe the
  current state of affairs.
* Emulation of smaller-size atomics with larger-size atomics has been
  documented.
* As an added bonus, `ATOMIC_*_INIT` is now scheduled for deprecation
  across the board in 1.34.0 now that `const` functions can be invoked
  in statics.

Note that the 128-bit atomic types are omitted from this stabilization
explicitly. They have far less platform support than the other atomic
types, and will likely require further discussion about their best
location.

Closes #32976
Closes #56753

@bors bors closed this in #57425 Jan 26, 2019

@macpp

This comment has been minimized.

Copy link

macpp commented Feb 2, 2019

Can i ask a question (just curious) ? It seems that constants like ATOMIC_I64_INIT are marked as stable since 1.34 and deprecated since 1.34 at the same time. Why stabilize something that is deprecated? It may be just my opinion, but i think that getting new stable feature that is deprecated from the beginning is rather strange...

@Amanieu

This comment has been minimized.

Copy link
Contributor

Amanieu commented Feb 2, 2019

Nice catch! I think we should just remove those constants.

@scottmcm

This comment has been minimized.

Copy link
Member

scottmcm commented Feb 3, 2019

That's convincing to me, @macpp -- opened #58089 to track it.

@jonas-schievink

This comment has been minimized.

Copy link
Member

jonas-schievink commented Mar 18, 2019

This is listed as the tracking issue for cfg_target_has_atomic, which is still unstable. Should this be reopened?

@sfackler sfackler reopened this Mar 25, 2019

@sfackler sfackler changed the title Tracking issue for adding more atomic integer types Tracking issue for #[cfg(target_has_atomic = ...)] Mar 25, 2019

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Mar 25, 2019

Yep - reopened.

@Centril Centril added the T-lang label Mar 26, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.