Live data from Hacker News

Using Rust for an Undergraduate OS Course

rust-class.org

1–10 of 72 posts

Re: Using Rust for an Undergraduate OS Course

#2
"The Rust compiler normally disallows any code with race conditions"

Lol what? Unless tasks cannot communicate at all, or they are scheduled entirely deterministically, how can the compiler eliminate race conditions? How can a compiler even determine what is a race conditions and what is intended non-determinstic behaviour.

Re: Using Rust for an Undergraduate OS Course

#3

"The Rust compiler normally disallows any code with race conditions" Lol what? Unless tasks cannot communicate at all, or they are scheduled entirely deterministically, how can the compiler eliminate race conditions? How can a compiler even determine what is a race conditions and what is intended non-determinstic behaviour.

Usually we say data races to be clear. Rust has full support for shared memory, but the compiler ensures that you are not accessing it without locking if it's mutable. (If the memory is immutable you can access it without a lock.)

You can of course have races in message passing, or the disk, or the network, etc.

Re: Using Rust for an Undergraduate OS Course

#4

"The Rust compiler normally disallows any code with race conditions" Lol what? Unless tasks cannot communicate at all, or they are scheduled entirely deterministically, how can the compiler eliminate race conditions? How can a compiler even determine what is a race conditions and what is intended non-determinstic behaviour.

The "default" communication primitive is message passing; and Rust has linear types, so passing anything from one task to another will disallow the use of that thing in the first task. e.g.

  let value = something();
  channel.send(value);
  // I can no longer use `value` here, it was moved into the .send call
(There is some subtlety here; some values don't move when passed around by value, like primitive numeric types, but in general, anything that could cause a race condition (i.e. pointers) moves.)

However, this isn't the end of the concurrency story; as mentioned in that article there is the `unsafe {}` escape hatch which lets you do things that could cause crashes/race conditions/etc. that the compiler wouldn't normally allow (`unsafe` is basically the programmer saying "trust me, I know what I'm doing" to the compiler).

This unsafe hatch allows one to implement shared memory with safe wrappers[1], Arc (Atomic Reference Counted) for immutable shared memory (without any locks[2]) and RWArc and MutexArc for lock-protected mutable shared memory.

[1]: http://static.rust-lang.org/doc/master/extra/arc/index.html

[2]: Rust has very good immutability support, so it can express "this value can never be modified" in the type system, so we can have shared memory without locks entirely safely, because we know that there is no modification possible and so no race conditions possible.

(I'm answering the data races question, which may be a non-sequitur if you're asking about race conditions in general, as pcwalton points out.)

Re: Using Rust for an Undergraduate OS Course

#5
post #4

"The Rust compiler normally disallows any code with race conditions" Lol what? Unless tasks cannot communicate at all, or they are scheduled entirely deterministically, how can the compiler eliminate race conditions? How can a compiler even determine what is a race conditions and what is intended non-determinstic behaviour.

The "default" communication primitive is message passing; and Rust has linear types, so passing anything from one task to another will disallow the use of that thing in the first task. e.g. let value = something(); channel.send(value); // I can no longer use `value` here, it was moved into the .send call (There is some subtlety here; some values don't move when passed around by value, like primitive numeric types, bu…

Two tasks A and B both send a message to task C. Does the message from A or the message from B get received by task C first? That's a race condition.

"A race condition or race hazard is the behavior of an electronic or software system where the output is dependent on the sequence or timing of other uncontrollable events."

"It becomes a bug when events do not happen in the order the programmer intended."

http://en.wikipedia.org/wiki/Race_condition

If I thought that the message A would definitely get there first - who knows why but that's what I thought when I wrote the code - this is a race condition and a bug.

Please explain to me - how does the compiler prevent this race condition and bug?

Re: Using Rust for an Undergraduate OS Course

#6
> Go. Go is a systems programming language

Not those kinds of "systems". It is funny, it seems initially it was meant to be those kind of "systems", and then it pivoted as we like to say, to become a "distributed-server-network-backend systems" not "hardware-kernel-OS" kind of systems. And then creators kinds of winged it and remarked how "well, that's what we meant when we said systems".

As for Rust, yeah, there are already a few projects trying to build a kernel or drivers in Rust. Here is one for example:

https://github.com/charliesome/rustboot

Re: Using Rust for an Undergraduate OS Course

#7
post #3

"The Rust compiler normally disallows any code with race conditions" Lol what? Unless tasks cannot communicate at all, or they are scheduled entirely deterministically, how can the compiler eliminate race conditions? How can a compiler even determine what is a race conditions and what is intended non-determinstic behaviour.

Usually we say data races to be clear. Rust has full support for shared memory, but the compiler ensures that you are not accessing it without locking if it's mutable. (If the memory is immutable you can access it without a lock.) You can of course have races in message passing, or the disk, or the network, etc.

...but you can still have races with locking.

Data races don't mean data corruption. It simply means the result is dependent on the scheduler or something else out of your control.

Two threads set a shared variable to different values. They both lock it before the set it. But that's still a data race, as which thread write first is dependent on the scheduler.

Re: Using Rust for an Undergraduate OS Course

#8
post #4

Earlier quoted context omitted.

The "default" communication primitive is message passing; and Rust has linear types, so passing anything from one task to another will disallow the use of that thing in the first task. e.g. let value = something(); channel.send(value); // I can no longer use `value` here, it was moved into the .send call (There is some subtlety here; some values don't move when passed around by value, like primitive numeric types, bu…

Two tasks A and B both send a message to task C. Does the message from A or the message from B get received by task C first? That's a race condition. "A race condition or race hazard is the behavior of an electronic or software system where the output is dependent on the sequence or timing of other uncontrollable events." "It becomes a bug when events do not happen in the order the programmer intended." http://en.wik…

As I edited in at the bottom of my answer, I slightly misinterpreted what you said and answered the question restricted to data races only.

Re: Using Rust for an Undergraduate OS Course

#9
post #4

Earlier quoted context omitted.

The "default" communication primitive is message passing; and Rust has linear types, so passing anything from one task to another will disallow the use of that thing in the first task. e.g. let value = something(); channel.send(value); // I can no longer use `value` here, it was moved into the .send call (There is some subtlety here; some values don't move when passed around by value, like primitive numeric types, bu…

Two tasks A and B both send a message to task C. Does the message from A or the message from B get received by task C first? That's a race condition. "A race condition or race hazard is the behavior of an electronic or software system where the output is dependent on the sequence or timing of other uncontrollable events." "It becomes a bug when events do not happen in the order the programmer intended." http://en.wik…

It doesn't. It prevents data races.

(But that said, there was some experimentation a couple of years ago with "channel contracts" in Rust, which allow you to solve that problem in many scenarios by explicitly enumerating the state transitions in your channel. We have the mechanisms still in place to do this as a library if we want to.)

Re: Using Rust for an Undergraduate OS Course

#10
post #4

Earlier quoted context omitted.

The "default" communication primitive is message passing; and Rust has linear types, so passing anything from one task to another will disallow the use of that thing in the first task. e.g. let value = something(); channel.send(value); // I can no longer use `value` here, it was moved into the .send call (There is some subtlety here; some values don't move when passed around by value, like primitive numeric types, bu…

Two tasks A and B both send a message to task C. Does the message from A or the message from B get received by task C first? That's a race condition. "A race condition or race hazard is the behavior of an electronic or software system where the output is dependent on the sequence or timing of other uncontrollable events." "It becomes a bug when events do not happen in the order the programmer intended." http://en.wik…

From your link:

C++11 introduced formal support for multithreading, and defined a data race strictly as a race condition between non-atomic variables. While race conditions in general will continue to exist, a "data race" must be avoided by the programmer, who must assure that only one thread at a time may access any variable if the access is for writing.

Post reply on HN