I think until they get into the mass production market, risc-v will be fairly expensive compared to the Rpi. Take a look at the full stack Hifive Unleashed ($1000) or the cheaper Hifive1 (revb): https://www.sifive.com/boards
Well, Hifive Unleashed is a dev board with tons of features for developer, a market where $1000 is pretty okay price. It has DDR4 ECC RAM,
RPi is another story: it's a single board computer with exposed GPIO and used to be shipped with ancient GPU.
Hifive1 is more of a competitor to Arduino if you can call it that. They even have the same pinout for expansion.
They are quite pricy, like you said, due to early adopter fee. However, you gotta understand that SiFive develop their cores and unlike Arduino RPi can't just slap something that is already produced and ready to be mounted on a board.
I've been trying to use the Sipeed Maixduino. It's much like the hifive1 except it uses the Kendryte K210, which is a fully supported RV64GC dual-core. It even supports supervisor and user modes. It's also relatively cheap. The problem is that documentation is lacking, so I'm having to reverse engineer their BSP: https://maixduino.sipeed.com/en/
Using virtio to demonstrate how set a pixel looks unjustifiably complicated. Queues, requests, responses!.. By contrast, using the framebuffer in Linux is a breeze. (Doing this in DOS was easier still.)
I'm writing this from the OS's perspective. Linux abstracts this away, but we have to do it to get the same abstraction. You can see under the user space portion how simple it is to grab a framebuffer, which is then mapped into user space. Then we have full access to RGBA values.
I'm not even sure what Linus was referring to when he talked about memory allocations in C++ being hidden. Aren't the only options either an malloc (kmalloc) call or a `new` operator call?
I believe he was referring to encapsulation of allocations in constructors, and implicit invocations of the copy operator and constructor. He may have also been referring to a lot of how STL works, though the STL is pretty explicit about its allocations & behaviour.
Yeah, maybe he was referring to constructors. That might make sense, since something like "MyType t;" could allocate.
I guess in the kernel context the STL (or whatever was around in 1992) would not be used though.
It's not constructors per se. It's what people put in to them. So MyType t also allocates in C, right (it'd be a stack allocation of sizeof(MyType) bytes)? But the difference is in C++ that could cause a bazillion heap allocations.
The problem gets magnified when you pass around these objects by value, thereby invoking copy constructors that also do those allocations, and doing value assignment, where you could have all those allocations happen again.
His comments predate r-value references, and a lot of stuff that r-value references have improved would be exactly the kinds of things where he saw a problem (though he'd hate the r-value solution).
I would think that overridable constructors and destructors are the alluded problem. Rust doesn't have the first and the later is slightly more constrained.
I wouldn't say that Rust is similar in this regard, nor do I think it is really a fair criticism of C++. It's more a fair criticism of certain C++ design idioms that are popular in certain circles. If you talk to people who do systems programming in C++ (particularly embedded systems), you'll find this isn't a common problem.
Rust is quite explicit about allocations and reallocations. This makes the language slightly harder to use and increases it's verbosity, but on the plus side the behavior of the code is always predictable and the compiler will catch uses that in another language but be accepted and suggests the correct incantation. Rust won't choose between static or dynamic dispatch for you, the code you wrote does.
I think this is the right approach for a performant language and a good compromise in usability. The only thing missing would be to have lints letting you know when using other constructs would be a better trade-off, like switching from dynamic dispatch to static dispatch when there's only one possible caller.
Yeah, I'm really confused by the two subthreads saying Rust doesn't have hidden allocations. The standard library is full of them, and even with `no_std` there is the possibility of a "global" allocator (GlobalAlloc) to be able to do hidden allocations without an explicit allocator. Box, Vec, etc rely on that even in `no_std` code.
The only way to have explicit allocations in Rust is to not use libstd (but this isn't special in the context of writing OSes anyway) and disallow using the GlobalAlloc trait, as well as any third-party libraries that rely on it. Unfortunately both the explicit allocator LocalAlloc and the global allocator GlobalAlloc, as well as all the types that rely on GlobalAlloc, are defined in the same library liballoc, so keeping one and removing the others requires patching liballoc.
As far as other non-C languages go, Zig has an explicit allocator that neeeds to be threaded through any function that wants to allocate, which would likely satisfy Linus's requirement.
Can't you just as easily do the same in C with functions and a struct? If so, I have to imagine Linus is referring to something different (I thought it was generally about things like copy constructors where what's going on is more hidden and possibly complicated than an assignment would naively indicate).
Then again, I don't commonly use any of the languages in question, so maybe I'm missing the point entirely.
Foo foo; // Foo::Foo allocates
z = x + y; // operator+ allocates
w = x; // operator= allocates
foo += *bar; // operator* allocates
Rust can do most of those things, but it's not encouraged and significantly less pervasive, especially in the kind of code you'd want to use in a kernel in the first place.
The gp is slightly incorrect: in Rust you cannot override the constructor so that it allocates more than the struct itself. You can extend + and allocate in it, which is why it is treated in theory and practice as if it were a method call, because it is. You cannot override the assignment operator, it will always be either a conceptual move of ownership or a memcopy at worst, never a method call with any arbitrary number of heap allocations. Same for the dereferencing operator, it cannot be overriden. This is the reason we say there are no hidden allocations in Rust. In every language you might have allocations in a method call. Some languages consider assignment to be one for example, Rust doesn't.
Of the examples given, Rust can only do the first one, overrides + because it is treated as just another method call. Assignments struct constructors and dereferencing always do what they look like they are doing as they cannot be overriden.
You can also use asm blocks (or string literals casted to function pointers) to wreak all kinds of havok. Oddly, noone seems particularly concerned about that.
Discussing the suitability of Rust for OS development (based on the comments of the developer of a major OS) seems completely on topic when discussing writing an OS in Rust.
I could be wrong but I interpreted the down votes as about incorrectly equating of Rust and C++ allocations. There are a few replies that address this better then I can (I'm limited here in that I grok Rust but not C++) but I believe the comment would have been more correct to draw similarities between C and Rust explicit allocation then C++ and Rust.
Linus can keep his opinion for himself and whatever direction he wants to drive Linux.
Symbian, Windows, macOS, Android, ChromeOS, Arduino, ARM mbed are all examples of OSes that have C++ at the kernel, or very least at the drivers layer.
So basically the question as it's asked doesn't make sense as I understand Rust and if someone took that to be intentional could be interpreted as language FUD (which could then deserve a down vote). An update to prevent the spread of misinformation about the language would be cool.
PS. I've only been using Rust on the daily for the last 8 months so I am by no means an expert. If there is a reason for your assertions that I'm missing I'd like to know. Thnx!
36 comments
[ 5.5 ms ] story [ 81.4 ms ] threadAnxiously waiting for the day I can purchase a riscV raspberry pi like SoC with fully oss hardware and Ready for Linux.
RPi is another story: it's a single board computer with exposed GPIO and used to be shipped with ancient GPU.
Hifive1 is more of a competitor to Arduino if you can call it that. They even have the same pinout for expansion.
They are quite pricy, like you said, due to early adopter fee. However, you gotta understand that SiFive develop their cores and unlike Arduino RPi can't just slap something that is already produced and ready to be mounted on a board.
https://lore.kernel.org/lkml/Pine.LNX.4.58.0401192241080.231...
" any compiler or language that likes to hide things like memory allocations behind your back just isn't a good choice for a kernel "
This was about C++ . So,given that Rust is similar to C++ , How does this quote applies to Rust?
Edit: I am getting downvoted for this post. Downvoters,any reasons?
Edit: or even something like "a = b"
The problem gets magnified when you pass around these objects by value, thereby invoking copy constructors that also do those allocations, and doing value assignment, where you could have all those allocations happen again.
His comments predate r-value references, and a lot of stuff that r-value references have improved would be exactly the kinds of things where he saw a problem (though he'd hate the r-value solution).
I think this is the right approach for a performant language and a good compromise in usability. The only thing missing would be to have lints letting you know when using other constructs would be a better trade-off, like switching from dynamic dispatch to static dispatch when there's only one possible caller.
gotta explain what's the difference between
andThe only way to have explicit allocations in Rust is to not use libstd (but this isn't special in the context of writing OSes anyway) and disallow using the GlobalAlloc trait, as well as any third-party libraries that rely on it. Unfortunately both the explicit allocator LocalAlloc and the global allocator GlobalAlloc, as well as all the types that rely on GlobalAlloc, are defined in the same library liballoc, so keeping one and removing the others requires patching liballoc.
As far as other non-C languages go, Zig has an explicit allocator that neeeds to be threaded through any function that wants to allocate, which would likely satisfy Linus's requirement.
Then again, I don't commonly use any of the languages in question, so maybe I'm missing the point entirely.
Sure in theory. But in practice most consider such a behavior a code small or straight bug an d fix it.
So there is a difference in practice.
You can also use asm blocks (or string literals casted to function pointers) to wreak all kinds of havok. Oddly, noone seems particularly concerned about that.
Hence why Linus is allowing Rust for certain Kernel aspects whereas he has previously rejected C++: https://www.theregister.com/2020/07/13/rust_code_in_linux_ke...
Symbian, Windows, macOS, Android, ChromeOS, Arduino, ARM mbed are all examples of OSes that have C++ at the kernel, or very least at the drivers layer.
Android and ChromeOS use a fork of Linux kernel, with legacy drivers written in C. What GNU/Linux users would call regular drivers.
Project Treble drivers are written in a mix of C++ and Java.
ChromeOS uses a mix of C++ and Rust for its drivers.
Linux fans have to come to grips that its place on Android and ChromeOS is only a convenience for a POSIX like kernel.
Rust allocations are I believe closer to C then C++ and Linus has already supported Rust: https://www.theregister.com/2020/07/13/rust_code_in_linux_ke...
So basically the question as it's asked doesn't make sense as I understand Rust and if someone took that to be intentional could be interpreted as language FUD (which could then deserve a down vote). An update to prevent the spread of misinformation about the language would be cool.
PS. I've only been using Rust on the daily for the last 8 months so I am by no means an expert. If there is a reason for your assertions that I'm missing I'd like to know. Thnx!