lilos v1.0 released

After five years of development, something like seven art projects, one commercial product, and many changes to the dark corners of the Rust language, I’ve decided lilos is ready for a 1.0 release!

Some parts I’m excited about include:

  • As of this release, the lilos APIs are entirely cancellation-safe.

  • This release contains contributions from five other people, bringing the total number of contributors to seven! (Want to be number eight? Come say hi!)

  • Thanks to one of those contributors, the operating system tests are now running in CI on QEMU!

(For anyone who’s new, lilos is a tiny embedded operating system that uses Rust async to allow complex multitasking on very limited microcontrollers without requiring dynamic memory allocation. Read more about lilos on my project page, where I link to the docs and provide a curated collection of blog posts on the topic.)

See the release notes if you’re curious about what’s changed. If you’ve got firmware written for an earlier version of lilos (particularly the 0.3.x series) and would like to update (you don’t have to!), those release notes will guide you through the process. There have been some breaking API changes, but I promise they’re all improvements.

The server chose violence

I’m continuing to reflect on the past four years with Hubris — April Fool’s Day was, appropriately enough, the fourth anniversary of the first Hubris user program, and today is the fourth anniversary of the first kernel code. (I wrote the user program first to help me understand what the kernel’s API wanted to look like.)

Of all of Hubris’s design decisions, there’s one that gets a “wait what” response more often than any other. It’s also proving to be a critical part of the system’s overall robustness. In this post, I’ll take a look at our 13th and oddest syscall, REPLY_FAULT.

Who killed the network switch?

We found a neat bug in Hubris this week. Like many bugs, it wasn’t a bug when it was originally written — correct code became a bug as other things changed around it.

I thought the bug itself, and the process of finding and fixing it, provided an interesting window into our development process around Hubris. It’s very rare for us to find a bug in the Hubris kernel, mostly because it’s so small. So I jumped at the opportunity to write this one down.

This is a tale of how two features, each useful on its own, can combine to become a bug. Read on for details.

I made a thing to help you make a thing out of a keypad

I do a lot of electronics projects in my spare time, and I tend to try to make reusable parts to save myself effort in the future. Because I have to order ingredients in certain quantities, I often wind up with more than I need for my project.

So I’ve opened a Tindie store, called Overengineered Widget Laboratories. Right now there’s one product in the store, called Keypad:GO. See, I built a sculpture last summer that needed to interact with people through a phone-style keypad. The keypad interface part of it seemed like something other people could use, so I made a few extras. This is a very easy way to interface a keypad or small keyboard to an embedded electronics project, because it handles all the basics for you — matrix scanning, debouncing, key matrix collisions, etc.

It will also help you reverse engineer the keypad’s circuit, because often cheap keypads arrive without good documentation. In the tiny flash of the embedded microcontroller, I’ve packed a setup wizard that will walk you through the process of setting up the keypad of your choice. All you need is a terminal program. This is honestly my favorite part, and I demonstrate it in the video below.

Making my website faster

Since I started running this site in 2011, I’ve adhered to some principles to make it fast, cheap, and privacy-respecting.

  • As few third-party cross-domain requests as possible – ideally, none.
  • No trackers (which tends to follow naturally from the above).
  • Use Javascript but don’t require it – the site should work just fine with it disabled, only with some features missing.
  • No server-side code execution – everything is static files.

Out of respect for my readers who don’t have a fancy gigabit fiber internet connection, I test the website primarily on slower, high-latency connections – either a real one, or a simulated 2G connection using Firefox’s dev tools.

I was doing an upgrade of my httpd2 software recently and was frustrated at how long the site took to deliver, despite my performance optimizations in the Rust server code. To fix this, I had to work at a much higher level of the stack – where it isn’t about how many instructions are executed or how much memory is allocated, but instead how much data is transferred, when, and in what order.

On a simulated 2G connection, I was able to get load times down from 11.20 seconds to 3.44 seconds, and the total amount of data transferred reduced from about 630 kB to about 200 kB. This makes the site faster for everyone, whether you’re rocking gigabit fiber or struggling to get packets through.

In this post I’ll walk through how I analyzed the problem, and what changes I made to improve the site.