The Case for Rust (in the base system)

I found this photo of Brian Kernighan holding John Lions famous book "A commentary on the UNIX operating system". You can see the book is not very thick! Unix was a small, well-designed system back then. There is a page on that book here:- https://en.wikipedia.org/wiki/A_Commentary_on_the_UNIX_Operating_System

1706945815897.png

Now, just imagine how thick the book would be today if you attempted to write a similar book on the linux kernel! And then think about adding the chapters on the parts written in rust. You would probably end up with a big stack of books!

Hopefully the freebsd kernel might still fit into one book!
 
Now, just imagine how thick the book would be today if you attempted to write a similar book for the linux kernel! And then think about them adding the chapters on the parts written in rust :). They would probably need a fork-lift to lift it!
Sorry to say, but that just reeks of FUD. I see absolutely no technical reason why code written in Rust should be generally larger. It's somewhat likely to be even smaller whenever you need concepts you'd have to do yourself in C. The size of the binaries produced is a different topic, for userspace code they're very often much larger just because required libs are linked statically ... which is IMHO indeed a concern, but naturally wouldn't apply to a kernel.

On the general complaint about "bloat" you'll read every other day, it's as simple as this, you can't have more features out of thin air. Nobody would be satisfied running a Unix system from the 70s nowadays.
 
Sorry to say, but that just reeks of FUD. I see absolutely no technical reason why code written in Rust should be generally larger. It's somewhat likely to be even smaller whenever you need concepts you'd have to do yourself in C. The size of the binaries produced is a different topic, for userspace code they're very often much larger just because required libs are linked statically ... which is IMHO indeed a concern, but naturally wouldn't apply to a kernel.

On the general complaint about "bloat" you'll read every other day, it's as simple as this, you can't have more features out of thin air. Nobody would be satisfied running a Unix system from the 70s nowadays.
Hahaha, well, fair enough! Maybe I'm being unfair :)
 
Re: exceptions. Worth mentioning that Google doesn't allow exceptions in C++ code. The main reason is existing layers of non exception safe code (the overwhelming majority of which have been written while this rule was already in effect, but anyway).

Exceptions as a method of control flow is indeed gross. Apart from stylistic reasons performance can also suffer badly. Here are the results of some microbenchmarking on C++ code paths with exceptions taken and not taken (and rand(3) to compare):
Code:
       4.3 nsec/call        4.3 user        0.0 sys: rand
       2.2 nsec/call        2.2 user        0.0 sys: random
       6.4 nsec/call        6.4 user        0.0 sys: floatrand
    4071.1 nsec/call     4079.1 user        0.0 sys: cpp_testhrow_throw_48
    3748.0 nsec/call     3746.3 user        0.0 sys: cpp_testhrow_throw_24
    3589.1 nsec/call     3595.2 user        0.0 sys: cpp_testhrow_throw_12
    3477.7 nsec/call     3475.6 user        0.0 sys: cpp_testhrow_throw_4
    3223.4 nsec/call     3219.2 user        0.0 sys: cpp_testhrow_throw
       4.0 nsec/call        4.0 user        0.0 sys: cpp_testhrow_no_throw
       3.2 nsec/call        3.2 user        0.0 sys: cpp_testhrow_no_possible_throw
       1.5 nsec/call        1.5 user        0.0 sys: cpp_testhrow_no_cleanup_no_throw
       1.0 nsec/call        1.0 user        0.0 sys: cpp_testhrow_no_cleanup_no_possible_throw

A factor of 1000 for following the code path with the exception thrown. This is a 11th gen i7 using FreeBSD-current's clang 17.

Still, personally I use them (for actual errors) because they are an excellent way to transport diagnostic information such as error messages to a place where you want to present it to the user,
 
Re: exceptions. Worth mentioning that Google doesn't allow exceptions in C++ code. The main reason is existing layers of non exception safe code (the overwhelming majority of which have been written while this rule was already in effect, but anyway).
Not sure whether this plays an actual role in Google's code, but I'd always opt for "exception unsafe" code when RAII (which is required for exception safety) would force me to clutter my object model with purely technical classes not serving any "business purpose"...

Exceptions as a method of control flow is indeed gross. Apart from stylistic reasons performance can also suffer badly. Here are the results of some microbenchmarking on C++ code paths with exceptions taken and not taken (and rand(3) to compare):
Also an interesting aspect! Although this probably depends a lot on actual implementation, I would expect the cost to be much less in languages targeting some "virtual machine" like Java and C#...

Still, personally I use them (for actual errors) because they are an excellent way to transport diagnostic information such as error messages to a place where you want to present it to the user,
If by "actual errors" you do mean this class of unexpected (and therefore typically fatal) cases, that's your typical "global exception handler" where all you do is indeed log (or present in some other way) error details.

I'd like to add the thought that if your whole process exits anyways on fatal errors (which of course isn't always the case, think of a service distributing requests across a thread pool), a much simpler scheme than exceptions would serve the same purpose: one single setjmp(3) that gets passed a pointer to some well known "global error" struct.
 
I remember trying to debug a deeply nested stack of exceptions in one of my forays into java. It was hard to see exceptions as an improvement on previous error handling techniques!

Yes not all the new stuff that's been added in (linux .. cough cough) is "bloat". I really like the cgroup mechanism for example, that's a powerful tool.

I am wondering, since Linus said linux developers are going to start writing drivers and maybe whole subsystems in rust... and since freebsd ports some of those things into itself from linux.. perhaps the bsd's will eventually have to do the rust integration in the bsd kernels too?
 
I remember trying to debug a deeply nested stack of exceptions in one of my forays into java. It was hard to see exceptions as an improvement on previous error handling techniques!
Try to make some sense of what you get from some exception thrown deep inside async paths in .NET 😣

Yes I'm aware I'm strongly opinionated on that subject .... I really think error handling should be as explicit as possible in the vast majority of cases.

I am wondering, since Linus said linux developers are going to start writing drivers and maybe whole subsystems in rust... and since freebsd ports some of those things into itself from linux.. perhaps the bsd's will eventually have to do the rust integration in the bsd kernels too?
Not that Rust in the kernel was completely unthinkable, but as far as I understood it, that's nothing currently discussed?
 
... I'm aware I'm strongly opinionated on that subject .... I really think error handling should be as explicit as possible in the vast majority of cases.
I agree. Programming error path is just as important as coding goodpath, and errorpath often ends up being at least as large a proportion as goodpath in the final program. You can't just write goodpath and say its done. In my view, if you haven't written errorpath, you haven't finished. Of course you can "short circuit" some of it by using assertions.
 
It is not logically possible to proof the absence of some piece of code on the Internet. All I can say is that I have never seen a C include file that would add exception handling and from my reading of the spec it looks impossible.
Its quite funny. Depending on which argument a Rust developer is going for, half will say that exceptions are supported and half will say that they aren't by the language.

"catch unwind can capture a panic and allow a graceful handling of the error."

"Rust doesn’t have exceptions"

Which is fine. But neither of these two conflicting strategies are as effective as C++ or as clean as C.
 
Its quite funny. Depending on which argument a Rust developer is going for, half will say that exceptions are supported and half will say that they aren't by the language.

"catch unwind can capture a panic and allow a graceful handling of the error."

"Rust doesn’t have exceptions"

Which is fine. But neither of these two conflicting strategies are as effective as C++ or as clean as C.
Thanks for these links! I don't see a contradiction here at all, but I'm amazed that Rust is designed exactly like I think is the sane way (seriously, I didn't know about that before): Have some central mechanism for "fatal" errors (so, they call these "panics"), but for the vast majority of "normal" errors, provide a Result type very similar to what I mentioned above. (Note to self: finally allocate some spare time for "hands on" ... there are indeed many things about Rust design I found to fully agree with)

Of course, if the mechanism for the fatal errors involves "unwinding" (like with a "long jump"), there's technically a way to offer "catching" that (which does not make it an exception that could be catched anywhere on its way up the stack), so why not expose this to the user (with appropriate warnings and advice). Funnily, I implemented a pretty similar thing not too long ago in C: https://github.com/Zirias/poser/blo...9c4393695e615debe/src/lib/core/service.c#L460 (it's different in offering the "catch" before unwinding is performed).
 
So. C is a low-level systems programming language. The earliest versions of the unix kernel were written in assembler. They wanted to port unix to other architectures, so they designed C as a language to re-write the unix kernel in, with the design goal of leaving as little of the machine-specific assembler within the kernel as possible. Once they had re-written the kernel in C, unix became readily portable to other machine types, and that is a major reason why it was succesful. See this paper https://www.bell-labs.com/usr/dmr/www/chist.html .

At the time the whole unix kernel was only of the order of thousands or maybe 10's of thousands of lines of code. The John Lions "commentary on unix kernel" book contains the source of the version 6 kernel and is less than half an inch thick. Unix was a small portable system, created by a small team.

C has been successful over the years because the language has remained small and stable, consider the contrast with C++. If you want hashtables, exceptions etc as first-class language features, you need a higher level language, not C. If you want to do those kind of things in C, you write actual C code to do them. The ansi C standard doesn't mention hashtables or exceptions, as far as I am aware.

Add more features to C at your peril, for that is the path towards C++. C has remained successful because the specification has remained concise and feature creep has been resisted by the wise heads of the C standards comittee.

As for errno, that was a major fcuk-up in the unix system call library design. C itself can't be blamed for that.

Torvalds was asked in a recent interview why rust has been added to the linux kernel; he said it was because they didn't want to become stale and just keep doing the same old thing, they wanted to add something new. I suppose that's one reason. I'm sure there are commercial reasons behind the scenes, including the availability of rust developers. C isn't being taught so much in comp. sci. courses nowadays. It remains to be seen how successful the addition of rust will be. Personally I hope that freebsd doesn't go down the same path, certainly not at the current state of development of rust.

View: https://www.youtube.com/watch?v=YyRVOGxRKLg
That fact is that any language that turns text files (code) built into an executable or library binary file is valid.
The only problem I see is the project maintenance over the years so I wouldn't risk to start to develop something in a language that became a trend and later on it could be hard to find someone to maintain the project because that trend is over.
Just take a look at Cobol and Pascal, who remembers Pascal?
Find someone to continue a Pascal project nowadays.
 
Also an interesting aspect! Although this probably depends a lot on actual implementation, I would expect the cost to be much less in languages targeting some "virtual machine" like Java and C#...

Tradeoffs again. For a code path that has an exception throw but doesn't take the exceptional path at runtime you "only" pay a 2x performance penalty in current C++ compilers. But most other languages make both code paths more expensive. Among them, unfortunately, is Common Lisp when you use (unwind-protect ...).

Funnily, I implemented a pretty similar thing not too long ago in C: https://github.com/Zirias/poser/blob/71d7c33de3f726e9ef47f429c4393695e615debe/src/lib/core/service.c#L460 (it's different in offering the "catch" before unwinding is performed).

That's funny, Common Lisp's condition system also has that property. https://en.wikibooks.org/wiki/Commo... has an advanced,as defined by the programmer.

You can also consume an entire book on the Condition System, which in the context of this thread is probably a bad thing :)
 
I found this photo of John Lions holding up his famous book "A commentary on the UNIX operating system". You can see the book is not very thick! Unix was a small, well-designed system back then. There is a page on that book here:- https://en.wikipedia.org/wiki/A_Commentary_on_the_UNIX_Operating_System

View attachment 18123
Now, just imagine how thick the book would be today if you attempted to write a similar book on the linux kernel! And then think about adding the chapters on the parts written in rust. You would probably end up with a big stack of books!

Hopefully the freebsd kernel might still fit into one book!
That’s Brian Kernighan holding John Lions’ book.
 
Hopefully the freebsd kernel might still fit into one book!
It would be a very fat book! Compared to the v6 kernel with its ~9000 lines, the FreeBSD stable/14 kernel has 13.3 millions lines . Even if you remove about 4.3 million lines of /sys/dev, it is 1000 times larger than the v6 kernel. So to get a similar level of detailed explanation as the lions book we are taking about a book with 120,000 pages even if printed in 3 columns as the original!
 
I myself don't using, but Pascal doesn't seems to be dead yet;). lang/fpc
There are some dependencies, a littele, though.
There is yet older language, doesn't seem to have dependencies, though.
lang/algol68g
Even COBOL still existing in ports having maintainer.
lang/gnu-cobol
And Fortran has multiple upstreams even now.
Oh, of course, LISP.

If there are not at all real needs, their maintainers and upstream should have been stepped down.

The most important thing in this thread shoul be "can Rust be required and used such a loooooooooong term?".
Rust should demonstrate "it surely is possible!" to get enough consensus with whom strongly objecting.

If there can be RELIABLE ENOUGH compilers (translators) for, for example, C to Rust, COBOL to Rust, Fortran (77, 9*, plus, ratfor,...) to Rust, just like ancient C generated assembler output and call assembler, making consensus could be much easier. But creating such translator should be difficult especially for languages for system proguramming that are forced to use mutually unsafe volatiles, in my humble opinion.
 
A friend who works with LLVM and MLIR, etc. has this to say about Rust:
Modern C++ is pretty good for systems programming. Between external tools like clang-tidy and clangd, there’s a lot of great tooling available. The new MLIR-based Clang-IR (Facebook) will support lifetime checking which is a lot like the Rust borrow checker.

I think what happened was that Rust was invented in 2006 but C++/Clang/LLVM kept developing through the decade to offer most of what Rust offered. Like x86, where Intel did a lot of hard work on an ugly problem, C++/Clang/LLVM just solved problems as opposed to Rust/RISC-V trying to be perfect.

Lastly, I’ve written Rust. You really have to over specify everything. The result is correct but ugly. Most of the time, 98%, people are doing obvious stuff and the compiler/language should be able to infer type/lifetime without your specifying it. Still static/strict just with defaults.
On some further questions he said
(lifetime analysis works with) Pretty sure any pointer. Rust elevates the borrow checker into the language with the concept of ownership. To me, that’s like NewSpeak, a very restrictive language where anything resembling WrongThought is prevented at all times.

"Don't you see that the whole aim of Newspeak is to narrow the range of thought? In the end we shall make thoughtcrime literally impossible, because there will be no words in which to express it.”
I love the reference to Orwell’s 1984! (Newspeak is the fictional language of Oceania, a totalitarian superstate.)

Now I don’t quite agree with him but I thought it was worth sharing.
 
Just take a look at Cobol and Pascal, who remembers Pascal?
Find someone to continue a Pascal project nowadays.

I was going to begin with a rebuke for mentioning Cobol and Pascal in one sentence, so entirely dissimilar are they.

I cut my teeth in NCR 315 then DOS/360 assembler patching broken Cobol binaries C. 1972 - but gladly never had to write in it.

To prove that exceptions (as commonly defined) maketh the rule, as it were ...

I earned my money as a professional software engineer with Delphi and Cobol not too long ago ;).

There's still plenty of Pascal derivatives out there. I've used FreePascal on FreeBSD since ~'96, mostly in Turbo Pascal syntax with a few quirks, and mostly compiled as stand-alone binaries which can be large with included units, but the code is fast, and clean viewed in assembler.

The FP documentation is excellent and has been well-supported on FreeBSD.

I'm hoping to release a very longterm Pascal project before I go - it's not system software though, so kinda off-topic here.

We shall expect mostly-C programmers to snigger and look down their noses! <&^}=
 
I myself don't using, but Pascal doesn't seems to be dead yet;). lang/fpc
...
The fact that compilers exist for certain languages doesn't prove that they are actually used in practice, either for commercial production use, for education, or for hobbyists. After all, a compiler exists for Intercal (the package is cunningly called Intercal, and the compiler called ick), yet people don't write Intercal code when they are sober. It's icky.

As far as I know, there is still significant production use of COBOL, FORTRAN and LISP, with COBOL diminishing, while FORTRAN continues to have a niche on supercomputers and scientific computation. Algol and PL/1 are in practice dead. Ada and Jovial are still used, for maintenance of existing systems (typically only within the defense industry).

I've not seen any programming done in Pascal or Modula in years, but I know largish systems in those languages used to exist, and they probably need continued maintenance.

There are lots of programming languages that are historic or crazy. As another example, IBM used to use a modified version of PL/1 called PL/S as a systems programming language. Compilers for it have never been available outside of IBM, and it stopped being used in the 70s. Yet, as late as 2010s, some IBMers were refurbishing PL/S compilers, not for serious use, but to play with historic artifacts (the source code of the "System R" database). The list of crazy languages (such as Intercal, which is a parody of the language wars of the 1970s) is long; I've looked a little bit at Malbolge and Brainfuck, which are both intentionally made as difficult as possible. In those languages, you don't worry about things like throwing exceptions, because even trying to increment an integer or adding two numbers is nearly impossible. But compilers for many of these languages continue to be maintained by hobbyists, mostly for amusement. Good for them!
 
The most important thing in this thread shoul be "can Rust be required and used such a loooooooooong term?".
Rust should demonstrate "it surely is possible!" to get enough consensus with whom strongly objecting.
I'd prefer to formalize that a bit. What I'd love to see is two things that are actually a bit related to each other:
  • A language standard document released by some independent¹ international standards body (like e.g. ISO)
  • More than just one implementation
Rust already showed it's a "good" language, popularity among professionals doesn't increase for "hype" reasons (I mean, we're not in the "web frontend realms" 😈). But durability could be proved with these two things, and of course, C fulfills both of them.

I have to admit I'm not too optimistic this will happen anytime soon and therefore I'm also pretty unsure it could be a hard precondition for inclusion in base, but hey, I can still pronounce a wish 😉

---
¹ here, by "independent" I mean not dominated by a single or very few entities like national governments or big corporations
 
I was going to begin with a rebuke for mentioning Cobol and Pascal in one sentence, so entirely dissimilar are they.

I cut my teeth in NCR 315 then DOS/360 assembler patching broken Cobol binaries C. 1972 - but gladly never had to write in it.

To prove that exceptions (as commonly defined) maketh the rule, as it were ...
I'm definitly no Cobol expert, luckily I had to do only some minor additions to the existing Cobol codebase. But it could happen at my former workplace to get "your hands dirty" ;). The codebase exists in one evolution or another since the 80s. Over time more and more parts got rewritten with Delphi.
 
Back
Top