Rust heads into the kernel?
Rust heads into the kernel?
Posted Apr 21, 2021 22:59 UTC (Wed) by roc (subscriber, #30627)In reply to: Rust heads into the kernel? by josh
Parent article: Rust heads into the kernel?
Posted Apr 22, 2021 8:31 UTC (Thu)
by pbonzini (subscriber, #60935)
[Link]
Posted Apr 22, 2021 19:03 UTC (Thu)
by josh (subscriber, #17465)
[Link] (1 responses)
I'm assuming that you mean "a single machine word" on a 64-bit system, because on a 32-bit system you can't store a general u32 and something else in the same 32-bit word.
Rust, today, has the property that a type is always stored the same way no matter where you put it, even when taking advantage of niches and similar. That's important because if you have a Result<T, Errno>, if it's an Ok you can get a &T from it, and if it's an Err you can get a &Errno from it. So, that &Errno needs to actually reference a thing that looks like an Errno in memory, not something that's been tweaked to use different enum values.
That works fine for a reference or box or other type that cannot have a value in the range 0-4095 (once we have the ability to declare that "not in the first page of memory" niche). An Errno can use that niche.
However, if you have some type T that has a niche that isn't 0-4095 (random example: a "userspace pointer" that can't point into kernel memory but *can* potentially be 0-4095), such that T's valid values and Errno's valid values would overlap, you can't tweak the Errno's values to store them in T's niche. That would mean you couldn't get a valid reference to an Errno, because it needs translation before extracting it.
In the specific case of a u32, the easiest solution is just to let Rust store the u32 and the Errno alongside each other, and they should take up no more than a 64-bit word.
To solve the general case of niches that would require transforming the values of Errno when storing/extracting them, we could handle that in two ways, one at the library level or one at the language level:
At a library level, we could just have a dedicated type (not Result) that stores an Errno and another type, which *doesn't* let you get a &Errno from it, and instead only lets you get an Errno. (Errno itself is smaller than a machine word, so we might as well just use its value.) We could then teach that dedicated type to store the errno in the niche of the T, and re-extract it later. That would solve the specific problem, with some effort, but would require writing code specifically to handle that transformation.
Or, at a language level, we can add a concept of "types that you can't have a direct reference to", make a version of Errno with that attribute, and then allow such types to take advantage of arbitrary niches in other types. Because you can't have a reference to those types, they don't have to be stored in a way that looks exactly like they'd be stored if standalone. You'd typically use it for types that are so cheap to copy (because they're smaller than a machine word) that the inability to reference them isn't an issue.
That language-level approach is the kind of thing that you can teach the Rust language to do *once*, and then it can automatically do the kinds of optimizations that in C you'd have to manually manage in each data structure.
Posted Apr 23, 2021 0:43 UTC (Fri)
by roc (subscriber, #30627)
[Link]
Rust heads into the kernel?
Rust heads into the kernel?
Rust heads into the kernel?