#Better VGA api with volatile writes

15 messages · Page 1 of 1 (latest)

slate dust
#

A VGA buffer is pretty much a &'static mut [u16; 80 * 25]. The VGA buffer is at a constant address, so I would like to use volatile writes. But if I use the nice abstraction of the mutable reference to an array, I do not know how I can make reads/writes to it volatile.

The only thing I can think of doing right now is to make a ZST VGA struct that impls Index and IndexMut that does the volatile reads/writes. But I'm not sure how the IndexMut version would work given that I need to return a mutable reference to something. Would I also need a custom RefMut type that does volatile writes when written to (not sure if this is possible)?

subtle smelt
#

Are you sure you need volatile writes? Volatile is for when the write operation itself has a side effect, i.e. the number of write operations matters, not just what is written.

#

I think &'static [AtomicU16; 80 * 25] would probably do everything you need.

slate dust
#
  1. That seems like a pretty sensible type to use. Although I've never used an atomic before - should I just use a bunch of .store(...) ops? I don't know what ordering to use.
  2. So, rust won't ever optimize out a pointer write to some random address?
  3. The docs for volatile fns say "Volatile operations are intended to act on I/O memory, and are guaranteed to not be elided or reordered by the compiler across other volatile operations." My read of this says that you would need volatile operations if the number and/or specific order of pointer reads/writes matters, is this right?
subtle smelt
#

I don't know what ordering to use.
Ordering::Relaxed, the weakest ordering, is always fine unless you care about the relationship of this memory location's contents to other memory locations' contents, like if you are implementing a mutex, in which case the mutex had better be seen to be locked before writes to what it protects, and unlocked after.

#

So, rust won't ever optimize out a pointer write to some random address?
The only cases where a write could be optimized into not existing are if

  • the compiler has reason to believe the location already contains that value, or
  • you've already entered Undefined Behavior by a prior operation.
#

My read of this says that you would need volatile operations if the number and/or specific order of pointer reads/writes matters, is this right?
That's right.

#

One could argue that order matters here because the order in which displayed characters change matters to what actually goes out in the video signal. But if you actually care about that small effect, you can use Ordering::SeqCst.

slate dust
#

Alright, thank you for the info

sleek kelp
#

which is true in this case, no one ever reads the value

#

you should probably use volatile

slate dust
#

This person says that llvm treats atomic ops as volatile. Another person in the thread says it's only doable with inline asm. (which I would be okay with if it were the only option and if I could write a nice wrapper)
https://users.rust-lang.org/t/volatile-atomic-operations/103142/5

The Rust Programming Language Forum

From this earlier discussion on the topic, the answer is no. Edit: Although if I'm reading it correctly, to ensure the loads are not optimized out, now or in the future, they should use a non-relaxed ordering and two loads should not be adjacent (with no intervening code).

sleek kelp
#

this is a mess