Stream: t-lang/wg-unsafe-code-guidelines

Topic: volatile and libm


gnzlbg (Jul 05 2019 at 14:22, on Zulip):

So libm uses volatile all over the place to force side-effects, e.g.,

if condition {
     // set overflow flags:
     (&(x * x) as *const  ).read_volatile();
}
gnzlbg (Jul 05 2019 at 14:23, on Zulip):

If x * x overflows, some flags in a register might be set. libm wants to set those flags, so it does things like this

gnzlbg (Jul 05 2019 at 14:24, on Zulip):

It has a macro called force_eval! for it, which is defined as:

macro_rules! force_eval {
    ($e:expr) => {
        unsafe {
            ::core::ptr::read_volatile(&$e);
        }
    };
}
gnzlbg (Jul 05 2019 at 14:28, on Zulip):

Spot the problem:

// mod foo:
unsafe fn foo() -> i32 { 0 }

// mod bar:
force_eval!(foo());  // look ma, no unsafe { }
gnzlbg (Jul 05 2019 at 14:30, on Zulip):

AFAICT the only way to do a volatile load on a reference, is to go via a pointer first, so there is no way to do that without unsafe code =/

Shnatsel (Jul 05 2019 at 18:13, on Zulip):

Oh. Now I know what I'm doing in Underhanded Rust competition if they ever hold another one.

Shnatsel (Jul 05 2019 at 18:14, on Zulip):

I'm putting something unsafe under lazy_static!

gnzlbg (Jul 05 2019 at 22:58, on Zulip):

if lazy static allows you to call unsafe code without using unsafe, then that sounds like a cool thing

Lokathor (Jul 06 2019 at 08:03, on Zulip):

"cool"

Nicole Mazzuca (Jul 07 2019 at 06:27, on Zulip):

wait, what is wrong with that?

Nicole Mazzuca (Jul 07 2019 at 06:28, on Zulip):

that gets turned into read_volatile(&(foo())) -> read_volatile(&0) -> 0

gnzlbg (Jul 07 2019 at 19:12, on Zulip):

@Nicole Mazzuca you could call the macro with { unsafe_fn(); expr } and you wouldn't need an unsafe block for calling unsafe_fn

gnzlbg (Jul 07 2019 at 19:14, on Zulip):

beyond that, there is nothing wrong with that; the point I tried to make is that this shouldn't be unsafe, the reason why this is unsafe is because we don't have volatile_read methods implemented for &T, so one has to cast to a raw pointer, and then dereference the raw pointer

Nicole Mazzuca (Jul 07 2019 at 22:15, on Zulip):

oh, got it; yeah, makes sense now

RalfJ (Jul 11 2019 at 15:20, on Zulip):

beyond that, there is nothing wrong with that; the point I tried to make is that this shouldn't be unsafe, the reason why this is unsafe is because we don't have volatile_read methods implemented for &T, so one has to cast to a raw pointer, and then dereference the raw pointer

OTOH it is very easy to write a safer wrapper in a library

RalfJ (Jul 11 2019 at 15:20, on Zulip):

this does not have to be a libcore thing

Lokathor (Jul 11 2019 at 19:09, on Zulip):

simple safe-wrapping operations for core types that can be in core should be in core. As a person who has spent all week working on a core only safe wrapping crate, I would be happy if core went around finding other useful core-compatible safe-wrapping stuff and just absorbing it so that everyone can benefit instead of trying to convince people to use a crate they've never heard of

Last update: Nov 20 2019 at 11:25UTC