So over the past few years I’ve been working on kernel code. As much as I love FreeBSD, I’m not working on its kernel. Rather, I’ve been working on my own kernel, building something which (hopefully) will be at least a tiny bit amazing.
Scheduling. I’ve basically taken FreeBSD’s ULE scheduler, rewritten it in Mage, and then I had to do some major modifications. Scheduling is done in two levels – userland and application. The primary scheduler determines which userland receives CPU time, and the secondary scheduler determines which application within the active userland receives CPU time. Since both levels are using ULE, I am confident CPU time will be shared fairly and contentions will be handled about the same as on FreeBSD.
Userlands. Each logged in user receives their own fully isolated userland, instead of the typical approach of sharing a single userland for all users. This is done to (hopefully) improve system security. Applications which read the scheduler table will only see applications within the current userland (except for the system user). Attempting to gather memory information, such as available versus used memory will only report what is used by the current userland. This also means user’s applications will not be able read or write the memory of other userlands, with the exception of system’s userland.
Application Idle Loop has been (almost) entirely eradicated. Kernel messages and input messages no longer require an application to have an idle loop to receive such messages. This means more CPU time for applications which aren’t idling. I’ve done this by requiring applications to have implementations for the kernel’s various message interfaces. The kernel and its kservs will spin off a new thread with all the information about the message they wish to send, then switch that thread’s ownership to the user of the destination application. The thread then executes the application’s message handler class appropriate for the message being delivered. If the application does not have an implementation to handle a specific message, this whole process is skipped.
Microkernel. Yes, I’m making a microkernel! This means only core functionality will be present in the kernel core, and nearly everything else has its own kserv (kernel server). This takes advantage of the isolated userlands, only the kernel core lives in kernel-land (ring0) and all the kservs run in the userland for “system” user. In case you were wondering, I do not have a “root” user, it is called “system” instead. No, this is not supposed to be a fully POSIX compliant kernel like FreeBSD.
Crash testing is performed for every kserv. This is basically just manually inputting wrong information and seeing what happens. Sometimes I have to simulate a complete kserv crash. I’m testing core’s ability to restart a kserv without reloading anything from disk. It’s a bit of a challenge sometimes, too. Network.kserv is almost too robust to crash manually, possibly due to most of its code having come from FreeBSD and reimplemented in Mage. Storage.kserv is the most highly tested kserv, for obvious reasons. Storage.kserv is nearly bulletproof.
I’m learning a lot about kernel design doing this, and it’s a lot of fun. It’s tricky, too, because I’m also developing the language this thing is primarily written in. That means it’s sometimes difficult to determine the root cause of a bug – is it in the kernel, the Mage runtime component, or the Mage runtime library? All in all, this is quite an interesting adventure into the foray of computer science, covering both kernel design and language design. So far, I’ve been having a lot of fun, and a lot of headaches.