HNHacker News
TopNewBestAskShowJobs

netbsdusers

147 karma · joined July 15, 2024

submissionscomments
netbsdusers··on The earliest versions of the first C compiler known to exist
You can do the same with a modren C compiler - the extern and auto mean the same and int is still the default type.
netbsdusers··on The SeL4 Microkernel: An Introduction [pdf]
As far as I can tell (this isn't gospel, just something I've inferred as the only reasonable explanation from comparing the codebases), Apple reconstructed a Mach 2.5 style kernel, like NeXTSTEP had, from fresh codebases (OSF Mach and 4.4BSD-Lite2), perhaps because 4.3BSD was still encumbered at the time.

The Darwin 0.1 and 0.3 releases contain the old kernel, derived directly from NeXTSTEP, and that's the direct derivative of Mach 2.5. The later XNU appears to be a reconstruction of that kernel with unencumbered code and that's also when IOKit replaced DriverKit.

netbsdusers··on The SeL4 Microkernel: An Introduction [pdf]
NT and XNU never had microkernel origins - Cutler explicitly refuted this at a conference in the early 1990s (if anyone remembers which, kindly share) and NeXTSTEP forked Mach at version 2.5, which was not a microkernel (see https://cseweb.ucsd.edu/classes/wi11/cse221/papers/accetta86...). XNU retained this monolithic architecture (as did Tru64 and other systems that trace their heritage to Mach prior to its version 3).
netbsdusers··on The SeL4 Microkernel: An Introduction [pdf]
Drivers in userspace is not particularly microkernelly - most of the major monolithic kernels have supported this to some degree or another for years (it is easy in principle, just transmit I/O requests to userspace servers over some channel) while many historic microkernels (see e.g. Mach 3) did not do it. It hardly changes the architecture of the system at all.

It is moving the higher-level things into userland that is the harder problem, and the one that has been challenging for microkernels to do well.

netbsdusers··on The little book about OS development
For most OSes the amount of code that actually deals in processor minutiae is really quite small. Portable logic makes up the majority. Maybe an exception can be drawn for some very particular OSes like DOS or Windows 9x.

So you read a tutorial and it spends about 90% of its time talking about an area that really isn't that interesting compared to other areas. I just don't think that's very compelling at all.

I say this having my own hobby OS which I've ported to four architectures (m68k, amd64, aarch64, riscv). At the moment I'm working on a TCP/IP stack which has been really enjoyable and I've learnt a great deal in doing this already. Other fun areas have been virtual memory and page replacement, designing asychronous I/O facilities, and IPC mechanisms, as well as appropriate synchronisation for each (synchronisation alone is a very deep topic, and there's considerable scope for innovation with techniques like safe memory reclamation.) Others may differ, but in these I find a lot more of interest than x86 minutiae.

netbsdusers··on The little book about OS development
Unfortunately this book has the classic fault of osdev tutorials: lots of talking about x86 minutiae, very little osdev. X86 minutiae is not osdev. It is a vanishingly small portion of what even a basic OS has to deal with.
netbsdusers··on What would happen if we didn't use TCP or UDP?
DHCP services require this ability to receive and send UDP packets on raw sockets, barring a few advanced systems like Solaris that provide them with necessary facilities. Usually they install a BPF module on the socket to filter out uninteresting packets.

https://kb.isc.org/docs/aa-00379

netbsdusers··on Operating System in 1,000 Lines – Intro
> Yes I know Ada is not a good fit, but there has already been a Unix-like OS entirely implemented in a derivative of Pascal: TUNIS.

Isn't it? There is a very well-developed kernel written in ADA with SPARK and formally verified at that: https://ironclad.nongnu.org

And PASCAL-derived languages were very popular for operating systems in the 80s. To name a few: Apple's LISA OS, DEC's VAXELN, and OBERON. There were others as well that didn't quite make it, like DEC's MICA and Acorn's ARX.

netbsdusers··on Do Files want to be Actors?
>"Our operating systems want to do things asynchronously, on their own terms. They'll tell you when they're done. Maybe this is a new era. Maybe making syscalls from 1970s Unix directly is like a remote procedure call to another machine - a leaky abstraction, a feeble attempt to impose your old mental model onto a new reality."

I think the article fell off here. Linux has a profoundly synchronous I/O system. The I/O U-Ring works there by dispatching requests to a kernel-maintained pool of worker threads. There the submitted request are run synchronously.

So the I/O U-Ring is in fact the abstraction, "a feeble attempt to impose your [new] mental model onto an [old] reality", as the author might put it. The actual Linux I/O system is most trivially exposed to userland by the same old "1970s Unix" means of the traditional system calls.

The real change with the I/O U-Ring is that it offers a way to submit work in bulk and finally introduces to Linux a form of I/O that appears to the program to be truly asynchronous.

(And it's not without some fair cause that file I/O is implemented as synchronous code. It's hard to do it asynchronously when it's a complex operation with many steps, where you are interacting with a page cache, not only for file contents but even caching the very metadata that describes how to get from an offset into a file to the block numbers where the data is stored. Windows has a famously profoundly asynchronous I/O system and even there actual file I/O is done just the same with synchronous logic ran in a worker thread, or copied directly from the cache if the requested data is already there.)

netbsdusers··on BSD kqueue is a mountain of technical debt (2021)
No it isn't. Letting files be poll/select/epoll'd isn't free either. They don't get support for that by magic. A poll operation has to be coded, and this is just as a much a "point of friction" then as supporting kqueue. (It bears mentioning as well that on at least DragonFly BSD and OpenBSD, they have reimplemented poll()/select() to use kqueue's knotes mechanism, and so now you only have to write a VOP_KQFILTER implementation and not a VOP_POLL too.)
netbsdusers··on BSD kqueue is a mountain of technical debt (2021)
Five points in reply:

1. Signalfd is a mountain of technical debt. It's not like a file at all. It reads entirely different things depending on which process is reading from a single common open file description, and it interacts with epoll in a most bizarre way, in that the process that added the signalfd to the poll set is the one whose signals will notify readiness - even if that process then closed the epoll and signalfd.

2. Signalfd is a mountain of technical debt because they built it over signals. Signals are of two forms: the one is asynchronous, the other synchronous. The one should be replaced with a generic message queue in a technical debt free design. The other is debatable. (Mach and also Fuchsia have an "Exception Port" instead, a message port someone can read from to deal with exceptions incurred by some thread.)

3. Regarding: > epoll can automatically monitor any kind of kernel resource without having to be modified, due to its composable design

Well, so can kqueue - EVFILT_READ/EVFILT_WRITE will work just as well on any file, be it a socket, an eventfd, or even another kqueue (though I don't think anyone who isn't dealing with technical debt should be adding kqueues to kqueues, nor epolls to epolls.) No need to modify kqueue! But in either case, though, you've got to modify something. Whether that's trying to fit signals into a file and getting signalfd, or whether it's adding a signal event filter and getting EVFILT_SIGNAL, something has to be done.

4. FreeBSD's process descriptors predate Linux's pidfds. They are also better and less technically indebted because they are pure capabilities (they were invented as part of the Capsicum object-capability model based security architecture for FreeBSD) while pidfds are not: what you can do with a pidfd is decided on based on the ambient authority of the process trying to, say, signal a pidfd, and not on rights intrinsic to the fact of having a pidfd. In fact, these pidfds are not even like traditional Unix open file descriptions, whose rights are based on the credential of who opened them. This makes privilege-separation architectures impossible with pidfds, but I digress.

5. The author ignored the actual points people argued against epoll with, viz. that 1) epoll's edge triggering behaviour is useless, and 2) that epoll's conflation of file descriptor with open file description is a terribly leaky abstraction:

https://idea.popcount.org/2017-02-20-epoll-is-fundamentally-... https://idea.popcount.org/2017-03-20-epoll-is-fundamentally-...

netbsdusers··on IBM RISC System/6000 Family
They have even cooler capabilities - A single XCOFF library can act as both shared and static libraries
netbsdusers··on Blocking code is a leaky abstraction
I am surprised by some of the comments claiming to find it very hard to make an async API out of a sync one.

I write a hobby kernel with a profoundly asynchronous I/O system. Since it's nice to have synchronous I/O in some places (reading in data in response to a page fault, for example, or providing the POSIX read/write functions), I have to turn it into synchronous I/O in some cases.

Asynchronous I/O notifies its completion in a configurable-per-I/O-packet (called "IOP") way. The default is to signal an event object. You can wait on an event object and when it's signalled, you're woken up. The result is that synchronously sending an IOP is hardly any more work than:

  iop_send(iop);
  wait_for_event(iop->completion_event);
  return iop->result;
I would be surprised to hear of any system where you can't do similar. Surely any environment has at least semaphores available, and you can just have the async I/O completion signal that semaphore when it's done?
netbsdusers··on OpenVMM – A New VMM for Windows and Linux, Written in Rust
It's the in-thing at the moment so it certainly attracts attention. Make sure to claim to be "Blazing fast [Rocket Emoji]" in the README too for good measure.
netbsdusers··on Asterinas: OS kernel written in Rust and providing Linux-compatible ABI
For kernels (and I suspect database engines might be added to the list, since they seem to have similar requirements to be both scalable and deal with massive amounts of shared state, but I'm not overly familiar with them) is where it gets particularly difficult.

Several kernels for example use type-stable memory, memory that is guaranteed to only hold objects of a particular type, though perhaps only providing that guarantee for as long as you hold an RCU read-lock (this is the case in Linux with SLAB_TYPESAFE_BY_RCU). It is possible in some cases to be able to safely deal with references to objects where the "lifetime" of the referent has ended, but where by dint of it being guaranteed to be the same type of object, you can still do what you want to do.

This comes in handy when you have a problem that commonly appears in kernels where you need to invert a typical lock ordering (a classic case is that the page fault codepath might want to lock, say, VM object then page queue, but the page-replacement codepath will want to lock page-queue then VM object.)

Unfortunately it's hard to think of how the preconditions for these tricks could be formally expressed.

netbsdusers··on Asterinas: OS kernel written in Rust and providing Linux-compatible ABI
They lack essential things for a kernel that could be used in production, viz. not kernel panicing during out-of-memory conditions, not an easy thing to retrofit when you have designed without consideration of it. It will probably take a bit more than 2 and a half months to rectify that.

https://github.com/asterinas/asterinas/issues/669

netbsdusers··on Asterinas: OS kernel written in Rust and providing Linux-compatible ABI
It's just what we used to call a "layered architecture".
netbsdusers··on Intel and AMD form advisory group to reshape x86 ISA
It's exactly because of licencing that the situation with RISC-V is a world of proprietary SoCs with no consistency, as opposed to the open system that is an x86 PC. (That the ISA is or isn't open is trifling and matters to neither user nor kernel developer.) Essentially every single board requires its very own custom port of your preferred OS.

I will wait for x86's doom, but it will take patience. After all, people have been saying it's dying and will be replaced by some RISC alternative for over 30 years now.

netbsdusers··on Safe C++
> Rust was invented with an elevator firmware use cases in mind. The inventor happened to work for Mozilla, so it got traction in the lower level parts of Firefox next.

TechSpot is referring (without attribution) to an interview the MIT Technology Review did with Hoare, and tacked on a claim that Rust was invented "to prevent issues such as his elevator breaking down" that isn't there in the source material. Elevator firmware is not systems software in any case, and the Rust manual Hoare authored states:

> Rust's goals arise from the context of writing large programs that interact with the internet -- both servers and clients -- and are thus much more concerned with safety and concurrency than older generations of program.

https://github.com/graydon/rust-prehistory/blob/master/doc/r...

The language described there relies on a much larger runtime than Rust today does. It is no systems language. Later it even grew things like the @ garbage-collected pointers.

Those would eventually go away as it turned out that people writing apps don't want to think about memory at all (and are better served by using a real apps language) and Rust instead started embracing its potential as a systems language:

> Although Rust didn't start out that way, one of the most interesting applications of Rust has been very low-level programming, even down to the level of kernels. The interest in this application of Rust was something of a surprise to us, but in hindsight it makes perfect sense. Low-level control over memory management isn't something that most applications software, especially on the server side, wants; most of that software has migrated over to languages like Java, Ruby, and JavaScript that trade control and performance for convenience by making memory management automatically, and dynamically, managed by the runtime. The remaining class of software, most of which is written in C and C++, is software that must manage memory manually in order to achieve some combination of performance, simplicity, and/or the ability to self-host. The prospect of using a new language for this class of software, which includes OS kernels, game engines, and browser engines among others, is what is fueling the growth of the nascent Rust community.

https://pcwalton.github.io/_posts/2013-06-02-removing-garbag...

For a lot of systems software, and I am thinking of system service managers ("init systems") in particular, failing and restarting is not viable. OOM conditions must be recoverable. Rust has recognised this and is trying to correct the course they went down in its early days of ignoring this, being unimportant for an apps language, but vital for a systems language.

One feature they have taken to is throwing panics on OOM conditions:

https://github.com/rust-lang/rust/issues/43596

These "panics" can unwind the stack and be caught with panic::catch_unwind, but with the proviso of only "sometimes". If you take that at face value, then it's not a very useful feature. The implication in the issue linked above however is that this could become a viable way to recover from OOM conditions. And the mechanism proposed there is indistinguishable from exceptions other than that it's insisted that it has nothing to do with exceptions and that you can't rely on it catching panics for you.

netbsdusers··on Safe C++
> Exceptions are a poor way to signal out-of-memory states. If containers panicked on out-of-memory, we’d enormously reduce the cleanup paths in most functions.

What exactly is the difference between a panic and an exception? According to everything I've been able to read about Rust's panic mechanism, it's just that "panics shouldn't be used for normal errors", which is just a prescription on the normative use of the construct. A pretended difference. Can anyone clarify whether there actually is a real difference? Or when "Panic" is said here, does the author mean something that cannot be meaningfully recovered from? That would be a change most inappropriate!

One of the most prominent birthmarks that Rust was stamped with when it was born as an apps (not systems) language was its standard library being designed without regard to the possibility of reacting to out-of-memory conditions by anything other than aborting. Now that it's trying to pivot from solely an apps language to a systems language for some time, there seems to be work underway to correct that deficiency.

C++ for its part is not burdened with that mistake. There is remarkable attention paid in the STL to the possibility of an out-of-memory condition and allowing a complete recovery from the same. This is a useful feature that systems software often requires.

netbsdusers··on Why Oxide Chose Illumos
> Talking about "technological and political issues" without mentioning any

I don't know why you think none were mentioned - to name one, they link a GitHub issue created against the systemd repository by a Googler complaining that systemd is inappropriately using Google's NTP servers, which at the time were not a public service, and kindly asking for systemd to stop using them.

This request was refused and the issue was closed and locked.

Behaviour like this from the systemd maintainers can only appear bizarre, childish, and unreasonable to any unprejudiced observer, putting their character and integrity into question and casting doubt on whether they should be trusted with the maintenance of software so integral to at least a reasonably large minority of modern Linux systems.

netbsdusers··on Windows NT vs. Unix: A design comparison
> the developers just took the entire TCP/IP stacks from BSD, and call it a day since BSD license does allows for that.

They didn't, but I don't know why you're putting a sinister spin on this either way. Of course the licence allows for that. It was the express intention of the authors of the BSD networking stack that it be used far and wide.

They went to considerable effort to extract the networking code into an independent distribution (BSD Net/1) which could be released under the BSD licence independently of the rest of the code (parts of which were encumbered at the time). They wanted it to be used.

netbsdusers··on Windows NT vs. Unix: A design comparison
I think rumours of NT's terminal illness have been greatly exaggerated. There are numerous new developments I am hearing about from it, like the adoption of RCU and the memory partitions.

It's not clear to me how processor groups inhibit scaling. It's even sensible to constrict the movement of threads willy-nilly between cores in a lot of cases (because of NUMA locality, caches, etc.) And it looks like there's an option to not confine your program to a single processor group, too.

netbsdusers··on Windows NT vs. Unix: A design comparison
I think (but am not sure) that WSL was a consolation prize of the cancelled Project Astoria, the initiative from the dying days of Windows Phone to support running Android apps on Windows. Implementing this with virtualisation would have been more painful and less practical on the smartphones of the day.
netbsdusers··on Windows NT vs. Unix: A design comparison
Filesystem io (and probably more) is not async at the kernel level in Linux. (Just imagine trying to express the complexity of it in continuations or some sort od state machine!) As such io_uring takes the form of a kernel thread pool. Disk block io by contrast is much easier to be fundamentally async since its almost always a case of submitting a request to an HBA and waiting for an interrupt.
netbsdusers··on Windows NT vs. Unix: A design comparison
The second system for Cutler was really Mica - he discusses its outrageous scope in his recent interview with Dave Plummer.
netbsdusers··on Windows NT vs. Unix: A design comparison
All kernels execute threads. It's just that very old unixes had a unity of thread and process (and Linux having emulated that later introduced an unprecedented solution to bring in support for posix threads). The other unixes for their part all have a typical process and threads distinction today and have had for a while.
netbsdusers··on Windows NT vs. Unix: A design comparison
Posix AIO is just an interface. Windows also relies on thread pools for some async io (I.e. when reading files when all the data necessary to generate a disk request isn't in cache - good luck writing that as purely asynchronous)
netbsdusers··on Windows NT vs. Unix: A design comparison
What exactly was "hybrid" about the OS/2 kernel? "Hybrid" has always been basically a made up concept, but in OS/2 it seems especially bizarre to apply it to what's obviously a monolithic kernel, even one that bears a lot of similarity with older unix.
netbsdusers··on Managarm: Pragmatic microkernel-based OS with asynchronous I/O
NT is no microkernel, nor has it ever been. It has always been monolithic.
← PreviousPage 2 of 3Next →