Live data from Hacker News

Hobby x86 kernel written with Zig

github.com

191–200 of 229 posts

Re: Hobby x86 kernel written with Zig

#191

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…

Hi Jack, just wondering why not use Dlang since it's more stable than Zig and you can use the subset of D as better C if you wish to stay simple?

Re: Hobby x86 kernel written with Zig

#192
post #82

Earlier 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…

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

Re: Hobby x86 kernel written with Zig

#193
post #176

Earlier 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…

> 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-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

#194
post #180
post #50

Earlier 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...

Why is it good to force all your users to figure out how to set their text editors to do something different and unnecessary just because you refuse to do what essentially every other non toy language has always been able to do? How is a decision like that not a giant red flag of user hostility and bad judgement?

Re: Hobby x86 kernel written with Zig

#195
post #113

Earlier 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.

It's not a slogan; there's a published type safety proof of the core of Rust. You may not like the assumptions that underlie that proof, but it's unarguable that "safety" has a very concrete meaning in the context of the language.

Re: Hobby x86 kernel written with Zig

#196
post #176

Earlier 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…

OK. I mean, personally I would swallow a lot of ugly special cases before adding macros, but it's certainly in line with other people's aesthetic preferences and Rust's "C++ spirit" of a low-level language with high-level language features. I can see the logic in saying that since we need lots of fancy mechanisms for sound safety anyway, what's one more gonna hurt?

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

#197

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…

Love the fact that people are developing kernels in new languages!

Re: Hobby x86 kernel written with Zig

#198

Earlier 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…

> 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. > > If you're relying on internal details, you're most likely doing it wrong, even by the standards of 'unsafe'. There are ways to nail down these details where required, at which point they're not even "internal" details anymore, but this has to be opted-into explicitly, for sensible reasons.

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

#199
post #171

Earlier 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.

Very interesting talk! Thanks for the reference.

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:

https://news.ycombinator.com/item?id=18962177

Re: Hobby x86 kernel written with Zig

#200
post #192
post #82

Earlier 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

I'm not aware of any editor or auto-formatter that handle the case of https://news.ycombinator.com/item?id=21969323 correctly.
Post reply on HN