News for hackers. Stuff that matters.
Re:Rust: 128 bit integers preparing to be released by drfuchs on Sunday December 04, 2016 @01:03AM (#13098969)
The RFC doesn't seem to mention anything about the atomicity (or lack thereof) of loads and stores of variables of the 128-bit types. From the discussion, it seems that on a number of current architectures, they're not going to be atomic.

Does this cause any problems in the Rust view of the world? Will there be unanticipated issues for developers who have been getting along just fine so far unknowingly assuming that all operations are atomic, which they have been just by virtue of how the hardware works?

Re:Rust: 128 bit integers preparing to be released by the_duke on Sunday December 04, 2016 @03:37AM (#13099298)
I what drfuchs might be getting at is that 128bit integers would need two registers on a 64bit architecture. Or four on a 32 bit one.

LLVM supports arbitrary length integer types, regardless of the platform. Rust already has u64 and i64 on 32bit architectures.

But even if something fits in one register, a variable isn't thread safe anyway.

Rust DOES NOT allow a mutable reference to exist simultaneously with non-mutable ones.

For thread safety, you always need special types, which Rust provides:

https://doc.rust-lang.org/std/sync/atomic/

https://doc.rust-lang.org/std/sync/struct.Arc.html

Re:Rust: 128 bit integers preparing to be released by drfuchs on Sunday December 04, 2016 @04:37AM (#13099394)
Thanks, but to be even more explicit, I'm thinking of a lower level than thread safety and the nice atomic references Rust provides in "safe" code: Consider a systems-y program that handles signals, or even hardware interrupts, or mmaps a chunk of shared memory. Any Read of a 32-bit variable will produce a value that was Written previously, no matter what; the hardware guarantees it. But a Read of a 128-bit variable may result in a value that has the high 64 bits from one earlier Write, and the low 64 bits from a more recent Write that was interrupted (or vice-versa). That's different than what many folks have ever experienced, messes up some algorithms, and is sure confusing the first time you see it.

True, this won't come up in a run-of-the-mill program, but if Rust is going to supplant C for OS work, or DataBase implementations, this is an issue to be aware of.

Succinctly: If you're in unsafe code, using 128-bit integers, you may experience behavior you've never seen before.

Re:Rust: 128 bit integers preparing to be released by Manishearth on Sunday December 04, 2016 @04:57AM (#13099445)
All the Rust OSes written right now use pretty tightly scoped unsafe code. The OS isn't just unsafe-blocks-everywhere.

The compiler would force you to use an atomic. Once you realize no AtomicUint128 atomic exists, you may try to explicitly use unsafe to make things work, but even then that requires a lot more explicitness than just an unsafe block. You will realize your mistake some point here.

Unsafe in Rust doesn't just turn off all the checks. It gives you the power to circumvent the checks, but these circumventions are still individually explicit.

Anyway, u128 doesn't worsen this situation. You could already make thread safety mistakes with wider value types if you really really wanted to, just like u128.

Re:Rust: 128 bit integers preparing to be released by Senji on Sunday December 04, 2016 @05:21AM (#13099490)
What stops you from manually entering a critical region yourself before you do the assignment?
Re:Rust: 128 bit integers preparing to be released by Manishearth on Sunday December 04, 2016 @10:15AM (#13100192)
Could you elaborate on what you mean here? The compiler stops you from trying to mutate things when they're not uniquely owned or atomic (or behind a mutex). When you have a non-unique reference you need to use a bunch of unsafe function calls to force mutation on it.
Re:Rust: 128 bit integers preparing to be released by seeekr on Sunday December 04, 2016 @12:59PM (#13100903)
Not GP, but iiuc he is just stating: In order to prevent these kinds of race conditions you can just use any regular locking mechanism. (As you could with many other cases where you'd like to introduce atomicity manually.)
Re:Rust: 128 bit integers preparing to be released by Manishearth on Sunday December 04, 2016 @03:07PM (#13101529)
Right, and the compiler forces you to do so.
Re:Rust: 128 bit integers preparing to be released by the_duke on Sunday December 04, 2016 @06:00AM (#13099564)
All valid points that one needs to consider when writing low level code.

The good thing about Rust is that you actively have to circumvent the languages safety checks with unsafe code to run into those problems.

And if you are using unsafe code, you should be aware of such low level considerations anyway, and would refrain from using types when not appropriate.

The consistency problems you describe apply to any datastructure after all.

Re:Rust: 128 bit integers preparing to be released by snovv_crash on Sunday December 04, 2016 @04:48AM (#13099420)
That kind of non-safe memory sharing doesn't exist in Rust, unless you explicitly mark code as 'unsafe'. If you want to write a variable, nobody else is allowed to read it until you are finished, and this is enforced at compile time via the language design. The same is true for all data structures.
Re:Rust: 128 bit integers preparing to be released by dbaupp on Sunday December 04, 2016 @01:22AM (#13099012)
One of Rust's strongest features is its ability to outlaw data races. In this case, the 128-bit types only provide mutations that take &mut self, that is, a unique unaliased pointer, meaning there's no way to concurrently mutate and hence they are automatically atomic, in a sense.
Re:Rust: 128 bit integers preparing to be released by chrisseaton on Sunday December 04, 2016 @06:35AM (#13099651)
Does Rust run a memory barrier when ownership is transferred? How does it ensure that the previous owner has finished all its writes when a new owner take over?
Re:Rust: 128 bit integers preparing to be released by stjepang on Sunday December 04, 2016 @06:50AM (#13099689)
To transfer ownership, you would wrap the object in Mutex<T>, send it via Sender<T>, use some other synchronization primitive, or simply pass it over at the moment the thread is spawned.

It's up to the synchronization primitives to ensure memory barriers are executed, not the language. So e.g. a Mutex<T> would execute a memory barrier when locking and unlocking. Rust then allows you to pass ownership in a trusted manner only, i.e. through those primitives.

Of course, you can also create an unsafe block and say: "Rust, trust me, I know what I'm doing, don't bother me, and these are the invariants I want you to enforce in safe code..." Mutexes are implemented this way.

Re:Rust: 128 bit integers preparing to be released by dardie on Sunday December 04, 2016 @06:58AM (#13099703)
It's built into the type system and checked statically at compile time. In rust, there can only be one 'owner' of a stored value. Ownership can be transferred, borrowed by multiple readers, or borrowed by a single writer. This ensures (at compile time) that there at any given time there is only ever one single writer OR multiple readers. Rust programs are guaranteed to be free of race conditions at compile-time. The above covers the vast majority of situations, but for cases where this is too restrictive their are other language constructs such as reference-counted types.
Re:Rust: 128 bit integers preparing to be released by chrisseaton on Sunday December 04, 2016 @07:53AM (#13099813)
Right - I get that the compiler ensures it is only accessed by one thread at a time.

But what I was asking was at runtime, when ownership transfers how does Rust ensure that writes to the value by the previous owner appear to the new owner before the transfer of ownership appears to the new owner?

You can statically guarantee that only one thread owns the object, but you can't statically guarantee the order in which the processor will apply the instructions your compiler generates, without barriers.

But the other person answered - you need to ensure that there is an explicit memory barrier yourself when you transfer the object.

Re:Rust: 128 bit integers preparing to be released by bretthoerner on Sunday December 04, 2016 @08:15AM (#13099875)
> you need to ensure that there is an explicit memory barrier yourself when you transfer the object

To add to/clarify this: I don't think you can transfer an object to another thread in safe Rust code without a primitive that will handle the barriers for you. Static ownership tracing doesn't actually know what threads are, because it doesn't even need to.

Re:Rust: 128 bit integers preparing to be released by pcwalton on Sunday December 04, 2016 @11:37AM (#13100496)
> But the other person answered - you need to ensure that there is an explicit memory barrier yourself when you transfer the object.

The channels do this.

Re:Rust: 128 bit integers preparing to be released by staticassertion on Sunday December 04, 2016 @10:15AM (#13100190)
> you need to ensure that there is an explicit memory barrier yourself when you transfer the object.

To be clear, you need to write the code yourself, but the compiler won't let you transfer ownership between threads without doing so.

There is no way to compile your code without proving to the compiler that you're data race free.

Re:Rust: 128 bit integers preparing to be released by Manishearth on Sunday December 04, 2016 @10:19AM (#13100204)
All of the standard library primitives that let you view writes from other threads (mutexes and mpsc senders) have memory barriers in them at some point.

The language itself doesn't know about memory barriers. It gives you the tools for enforcing thread safety provided your synchronization abstractions have memory barriers in the right place.

Re:Rust: 128 bit integers preparing to be released by steveklabnik on Sunday December 04, 2016 @01:06AM (#13098975)
Rust has separate atomic types for doing atomic operations, so currently, none of them are.

So, if you wanted an atomic type, you'd find it here: https://doc.rust-lang.org/stable/std/sync/atomic/index.html

In other words, no, it shouldn't be a problem, at least in my understanding.

Re:Rust: 128 bit integers preparing to be released by drfuchs on Sunday December 04, 2016 @01:35AM (#13099045)
Right, but the point is that to date, being careless about asking for an atomic type explicitly would not lead to buggy behavior. But now it will, so some folks are going to be stumped when they use their old habits and get flakey results. Not that there's anything to be done, other than warning folks that they can't just widen their integer types and expect it to work without checking for this case.
Re:Rust: 128 bit integers preparing to be released by cesarb on Sunday December 04, 2016 @07:42AM (#13099787)
> Right, but the point is that to date, being careless about asking for an atomic type explicitly would not lead to buggy behavior.

That's already the case: simply reading a 64-bit integer in a 32-bit processor is not atomic, and that's already possible today.

But that's not a problem in Rust. How would you access the same 128-bit integer from more than one thread?

- You pass the thread a copy of the value: the thread's copy can't be accessed by any other thread, so whether or not it's atomic doesn't matter.

- You pass the thread a mutable reference (&mut) to the value: one of Rust's rules is that there can be only one &mut to a memory location, and while that &mut exists, nothing else can read or modify the value. Therefore it's the same case: only one thread can access the value, so whether or not it's atomic doesn't matter.

- You pass the thread a non-mutable reference (&) to the value: another of Rust's rules is that while any non-mutable reference exists, nothing can modify the value, so the reads not being atomic don't matter.

- You wrap the value in something like a Mutex: the Mutex has a lock which prevents concurrent accesses in the middle of a write.

- You use an Atomic version of the 128-bit integer: this one doesn't exist, so can't be used.

The main reason for all the interest in Rust is that the compiler protects you from many kinds of mistakes. Accessing the same variable from more than one thread, without using a lock or an atomic, is one of the things the compiler protects you from.

Re:Rust: 128 bit integers preparing to be released by Tuna-Fish on Sunday December 04, 2016 @03:42AM (#13099306)
The situation where the atomicity of integer operations matter is when there are multiple references to a single memory location, at least one of which is mutable.

The entire basis of the memory protection model of Rust is that it makes the above impossible in safe code. If you attempt to create such a situation, the compiler will fail to compile your code. Every single integer operation could stop being atomic and not a single line of safe rust would break.

Re:Rust: 128 bit integers preparing to be released by steveklabnik on Sunday December 04, 2016 @01:42AM (#13099055)
In Rust, you don't get buggy behavior in this kind of case: your program fails to compile.