Hi, author here! I've just finished writing the pre-emptive multitasking [0](only round robbin though, nothing fancy). I'm currently writing an ATA driver [1], the idea is to implement ext2. I used to do this in Rust but I switched to zig for maintainability and readability over Rust. It seems that with `comptime` I'm able to make a lot of things optimal. Overall I have to say kernel programming is _hard_ but very re…
Hobby x86 kernel written with Zig
191–200 of 229 posts
Re: Hobby x86 kernel written with Zig
#192Earlier quoted context omitted.
> including the vast majority of code editors by default Which ones exactly? Not really a problem I've encountered often except when someone tries to mix both spaces and tabs, and in general editors are built with the existence of this very common character in mind. People tend to hit the tab key to indent anyway, and one tab char meaning one level of indent is perfectly intuitive and allows users to individually con…
Many editors (including the venerable Vim and Emacs) indent and align with tabs by default, which means that if you want your code to look right you standardize tab width which in turn removes one of the only (meager) advantages tabs have over spaces: configuring the indentation width to match your personal taste. >Not really a problem I've encountered often except when someone tries to mix both spaces and tabs Mixin…
Re: Hobby x86 kernel written with Zig
#193Earlier quoted context omitted.
> I think -- and I could be wrong -- that Rust sacrifices more than it has to just to achieve that soundness, by also paying for "zero-cost abstractions," which, for my taste, is repeating C++'s biggest mistake, namely sacrificing complexity for the appearance of high-level abstraction that may look convincing when you read the finished code (perhaps more convincing in Rust than in C++), but falls apart when you try…
> The argument here seems to be that there is can be no real abstraction in low-level languages, so there's no point providing language features for abstraction. My argument is that low-level languages allow for low abstraction, i.e. there's little that they can abstract over, where by abstraction I mean hide internal implementation details in a way that when they change the consumer of the construct, or "abstraction…
Yes, for two main reasons: (1) type-safe printf; (2) #[derive]. Nothing is "absolutely essential" in any Turing-complete language, of course, but printf comes pretty close. The only real alternative would have been to use the builder pattern for formatting like C++ does (i.e. the Note that these are both cases (maybe the primary cases) in which OCaml has built-in ad-hoc solutions that feel very un-"systemsy". In OCaml, format strings are built in to the language, as are functions like PartialEq and Debug, the latter of which are implemented via magic built-in functions that call private internal reflection APIs. There was a desire to do better in Rust, as it was felt that these are the ugliest parts of OCaml, and so macros were part of Rust from the very early days.
Re: Hobby x86 kernel written with Zig
#194Earlier quoted context omitted.
Even weirder than that, it intentionally fails on \r\n newline, so windows text files straight up don't work by default.
Good! Even Windows Notepad, the extreme example of "not a code editor editor," supports \n newlines now: https://devblogs.microsoft.com/commandline/extended-eol-in-n...
Re: Hobby x86 kernel written with Zig
#195Earlier quoted context omitted.
> The point is that Zig doesn't even try to prevent UAF now I wouldn't say Zig exists at all right now, but just as it strives to one day be production-ready, it strives to prevent use-after-free. Safety is a stated goal for the language. > Hasn't this essentially been what C++ has been trying for memory safety for decades, without success? No. I'm talking about a mechanism that can detect various errors at runtime,…
> Rust, BTW, doesn't entirely guarantee memory-safety, either > We always make some compromises on soundness; the question is where the sweet-spots are. Excellent point. There are complex tradeoffs and the "rust is safe" slogan is just a slogan.
Re: Hobby x86 kernel written with Zig
#196Earlier quoted context omitted.
> The argument here seems to be that there is can be no real abstraction in low-level languages, so there's no point providing language features for abstraction. My argument is that low-level languages allow for low abstraction, i.e. there's little that they can abstract over, where by abstraction I mean hide internal implementation details in a way that when they change the consumer of the construct, or "abstraction…
> But let me just ask: are macros absolutely essential? Yes, for two main reasons: (1) type-safe printf; (2) #[derive]. Nothing is "absolutely essential" in any Turing-complete language, of course, but printf comes pretty close. The only real alternative would have been to use the builder pattern for formatting like C++ does (i.e. the Note that these are both cases (maybe the primary cases) in which OCaml has built-i…
BTW, Zig manages to do both things without macros and without any special cases in the compiler. TBF, Zig's approach was unfamiliar to me until I saw it in Zig, and it is Zig's "brilliant idea" (even if it had originated elsewhere), so it's OK if Rust simply didn't consider it; Rust certainly has its own brilliant idea.
Re: Hobby x86 kernel written with Zig
#197Hi, author here! I've just finished writing the pre-emptive multitasking [0](only round robbin though, nothing fancy). I'm currently writing an ATA driver [1], the idea is to implement ext2. I used to do this in Rust but I switched to zig for maintainability and readability over Rust. It seems that with `comptime` I'm able to make a lot of things optimal. Overall I have to say kernel programming is _hard_ but very re…
Re: Hobby x86 kernel written with Zig
#198Earlier quoted context omitted.
> If you aren't making a safe abstraction around your unsafe code, you're supposed to mark the surrounding function "unsafe" as well, and document its expected constraints in a 'Safety' comment block. Sure, but now we're back to the issue that it's unclear what constraints `unsafe` code actually has to hold, meaning ensuring your abstraction is safe is just about impossible to do with certainty (And OS kernel code is…
> Sure, but now we're back to the issue that it's unclear what constraints `unsafe` code actually has to hold The Rust Nomicon actually documents these constraints for each 'unsafe' operation. Code that can ensure that these constraints hold can be regarded as 'safe' and rely on an unsafe{ } block. Code that can't, should be marked unsafe and document its own constraints in turn. > You may think you have a safe inter…
It's not that simple, what I'm getting at is that 'unsafe' code is still required to meet all the constraints that 'safe' code has to meet, even though those constraints are not fully documented (Because in general, in 'safe' code there are lots of things that are impossible to do but not explicitly UB), and they have changed them in significant ways in the past. You can see an incomplete list of them here[0]. There has been work to nail these details down for years, with the most recent being this one[1], but in general I would argue there hasn't been much progress since I first looked into it years ago now. Fun fact, the first Rust issue I remember reading that touched on this (and evolved into basically everything going on today) is this[4] one, which was made exactly 4 years ago today (And I mean exact!).
The 'Safety' sections for 'unsafe' operations are actually just extra requirements for those particular API on top that you also have to keep in addition to whatever safe Rust constraints apply. And I would argue in general they're not actually exhaustive, and they're mostly just a "best guess" - it's not a breaking change to introduce or realize there are more constraints. Ex. A little more then a year ago, they added the info that a slice can't be larger than `isize::MAX`[2], and a few months ago was this[3] one, where they added that the pointer length must be from a single allocation.
My point is that when you're doing something like writing an OS kernel, you end up running into these types of issues and corner-cases because Ex. They determine what your allocator is allowed to produce, or if some particular pointer can be validly put into a slice.
> No, "other code" should not be marked unsafe because this would mean that relying on slices is inherently unsafe. Which is silly; the whole point of a "slice" type, contrasted with its "raw parts", is in the guarantees it provides. This is why slice::from_raw_parts is unsafe: not because if what it does, but what it states about the result.
Sure, my point is that this is at best unclear, and I would argue wildly misunderstood. We've basically made two definitions of 'unsafe' - one for code that has to perform one of the five 'unsafe' operations (Which is a clearly defined 'yes' or 'no', and also the one described by the Rust docs), and one for code that can potentially break some type of invariant the will potentially cause UB somewhere else in the program (even if the code in question is completely safe and can't on its own cause any problems).
The problem is that Rust only guarantees the type of safety that it does if you do the second, but yet lots of people (I would almost argue most...) assume the first is sufficient and 'unsafe' by itself ensures all your memory bugs are in `unsafe` code. The Rust docs even describes safe vs. unsafe as two completely different languages (which they are) which brings into question why you would write `unsafe` code when you don't even need any of the `unsafe` operations. You arguably want a separate keyword for this - one that marks a function `unsafe`, but doesn't actually allow you to perform any of the `unsafe` operations in it.
[0] https://doc.rust-lang.org/nomicon/what-unsafe-does.html [1] https://github.com/rust-lang/unsafe-code-guidelines [2] https://github.com/rust-lang/rust/commit/1975b8d21b21d5ede54... [3] https://github.com/rust-lang/rust/commit/1a254e4f434e0cbb9ff... [4] https://github.com/rust-lang/rfcs/issues/1447
Re: Hobby x86 kernel written with Zig
#199Earlier quoted context omitted.
the problem i encounter is when you try to break a long line into multiple lines. if you want to use tabs and align the continuation, you should be mixing spaces and tabs. for example ('-' is tab, '.' is space): --function_with_lots_of_arguments(arg1, arg2, arg3, --................................arg4, arg5, arg6); it can be done, but a lot of editors get it wrong and it requires paying attention to the whitespace. o…
Some food for thought: https://youtu.be/ZsHMHukIlJY?t=633 For example, this is the best way to define functions with argument lists long enough not to fit on a single line: fn doThing( argument1, argument2, argument3, ) { } Visually clear, doesn't have any spaces/tabs issues, produces minimal diffs when adding/removing/renaming arguments.
More food for thought:
The style in your example is more consistent with the way nearly every programmer formats code that has more than one statement. For example:
if( shouldDoThings ) {
doOneThing();
doAnotherThing();
doLastThing();
}
Why do we want to format statements that way, but function calls and expressions a different way? No one would write this: if (shouldDoThings) {doOneThing();
doAnotherThing();
doLastThing();}
I have a theory about that but will have to save it for another day.Somewhat related, the Rust coding style guidelines used to follow a heavily column-aligned style, but changed to indentation-only a year or two ago. I posted an example from the Servo source code with the old and new formats here:
Re: Hobby x86 kernel written with Zig
#200Earlier quoted context omitted.
Many editors (including the venerable Vim and Emacs) indent and align with tabs by default, which means that if you want your code to look right you standardize tab width which in turn removes one of the only (meager) advantages tabs have over spaces: configuring the indentation width to match your personal taste. >Not really a problem I've encountered often except when someone tries to mix both spaces and tabs Mixin…
So then it's the editor that's at fault. Most editors let you do a "run formatter on save", and zig has(had? at least it did last I played with it) a formatter that can do correct "indent with tabs and align with spaces" with only a minor tweak