Long time no see! Let’s make a recap of 2025 on Maestro, shall we?
Giving updates about a project like Maestro is difficult. Implementing a new feature correctly is tedious due to the complexity of the codebase, and as such I cannot post blog articles very often.
I said in the past I wanted to have a goal for the end of 2025: be able to code on Maestro itself
Spoiler: I didn’t reach it. BUT, I’ve managed to make progress nonetheless. Let’s talk about it!
I have already talked about a few things I have done this year in a few other articles:
Refactoring blimp
Blimp is …
Long time no see! Let’s make a recap of 2025 on Maestro, shall we?
Giving updates about a project like Maestro is difficult. Implementing a new feature correctly is tedious due to the complexity of the codebase, and as such I cannot post blog articles very often.
I said in the past I wanted to have a goal for the end of 2025: be able to code on Maestro itself
Spoiler: I didn’t reach it. BUT, I’ve managed to make progress nonetheless. Let’s talk about it!
I have already talked about a few things I have done this year in a few other articles:
Refactoring blimp
Blimp is the package manager for the Maestro operating system. It is still a work in progress.
When Maestro boots, it will look on the disk for the first programme to launch. This programme initialises the system.
One of the main issues I currently have with testing Maestro is the difficulty to build that disk for testing purpose. Many steps have to be done by hand to build it and as such, many tests have to be done by hand too (such as running bash commands to check they still work after a modification).
Ideally, all tests should be performed automatically in the CI.
This is the reason why I started refactoring blimp (PR). The goal is to have packages pre-built, stored on a server (pkg.maestro-os.org), that can be downloaded to build a disk image. Before the PR, blimp had a dedicated server programme, but it turns out this is not necessary as a s3 bucket should be sufficient.
As of today, this refactor is not finished yet.
gcc, binutils, make, tar, gzip and other commands working
Before 2025, all the programmes I ran on Maestro were built on Linux, then copied on the virtual machine’s disk, so they could be run.
Even though Maestro aims for binary compatibility with Linux, programmes still had to be cross-compiled because I am using the musl C library instead of glibc.
Now that gcc works, it is possible to build programmes directly on Maestro. The next steps was to be able to build gcc with itself on Maestro to be fully selfhosted. I did not manage to get this done in time before 2026.
I still got make working (required to build gcc as you might guess). This required a fix in time management because the current system time always was the epoch (January 1st, 1970) at boot, causing make to issue warnings because of file timestamps being higher than the current time.
Now, Maestro reads time from the RTC at boot.
Even if not mentioned in the following sections, I have managed to get the following commands to work too:
file,find,grepandsedThose commands are also required to build
binutilsandgcc.
tar and gzip
Next, I wanted to grab binutils’ sources and decompress them on disk. To do that, I needed the tar and gzip commands, which I managed to make work without too many difficulties (I had to fix a deadlock, aside from a few other bugs).
But then I realised decompressing was really slow. So I looked at the system calls and realised tar creates a pipe, then executes gzip, making it pass its output to tar.
Then I realised pipes were the bottleneck, so I made them faster by increasing their buffer size from 512 bytes (way too low) to 65 536 bytes.
512 bytes is actually the amount of bytes above which the transfer is not guaranteed to be atomic. I did not understand that at the time I implemented pipes.
This guarantee is not implemented yet on Maestro.
Mutexes
To make Maestro faster at switching between tasks (important when using a pipe), I decided to implement proper mutexes.
Before that, the kernel had only spinlocks. A spinlock waits on a resource by entering a loop and do nothing (apart from wasting CPU cycles) until the resource is released.
Instead, when a process has to wait on a resource, the mutex puts the process to sleep, switching context to another process which is not waiting on a resource (potentially switching directly to the process currently working with the resource, making it release it faster).
A mutex also has a queue of processes, to serve them in a FIFO fashion (avoiding starvation).
Building binutils on Maestro
After getting binutils’ sources decompressed, I attempted to build them. The first step was to type ./configure.
I managed to get it pretty far by making a few fixes:
- System calls
mincore,fchown,fchownat,oldstat,oldfstat,oldlstat,fstatat64,newfstatat,pread64,pwrite64,sigaltstack,getgroups,setgroups,sched_getaffinityandsched_setaffinitywere missing O_APPENDdid not work- shebangs (
#!expressions at the beginning of scripts) parsing was buggy - A few other minor fixes
I also had to add a custom command on prctl called PR_MAESTRO, which implements the option PR_MAESTRO_LINUX, allowing to make the uname system call return Linux instead of Maestro, as some programmes (including autoconf) will rely on uname to know which OS they run on.
I wrote a shell command to use this option, called mocklinux.
The rename mess
Once all of this was done, I nearly made ./configure work, but then I had another bug: the rename system call was corrupting the filesystem.
It turns out, fixing this required me to rewrite a big part of the VFS and ext2 filesystem implementations. At the same time, I implemented the RENAME_EXCHANGE flag (which exchanges) the source and destination atomically.
One aspect I did not take into account in my first implementation is that you cannot move a directory into itself or inside one of its child: that would create a cycle in the filesystem
The solution to this problem is to add a global rename lock: when performing a rename operation, no other rename can happen at the same time on the system, allowing to check for cycles without data races
Note: some special cases allow to avoid taking this lock. For example, when the source and destination have the same parent directory, we do not need to check for cycles
The hashmap issue
While fixing the rename* family of system calls, I stumbled on an issue on my implementation of HashMap.
See, I made a talk in the past about my HashMap implementation (and other subjects).
The HashMap implementation uses Swiss Tables in order to be fast. At the time, that sounded like a good idea, until I realised much later that I cannot use SIMD operations in kernelspace.
Actually, SIMD operations can be used in kernelspace, but that requires saving and restoring SSE registers in order to avoid rewriting the userspace’s values. These operations take time, and it’s often faster to just not use SIMD.
My implementation has a bug somewhere which makes it do a use-after-free, causing a kernel panic. This is still under investigation to this day.
At that moment, I felt I needed to pause this and work on something else…
Side quest: NVMe
I have decided to start writing a NVMe driver for Maestro (PR).
Even though the specification is kind of scary, implementing this is fun. But I will not give details about it, since this will be a subject for another article!
Next year’s goals
The goal I had planned for the end of 2026 was to have a desktop environment working.
That involves:
- Display drivers (currently, the OS can only display text, by using VGA text mode)
- Interfaces to display drivers (framebuffer and/or DRM)
- USB mouse/keyboard support? (currently, only PS/2 keyboards are supported)
- The evdev interface for mouse/keyboard inputs
- Running X (the windowing server, not the neo-nazi social network) or Wayland. I started writing my own X server in the past (Visto), but as of today I am more and more tempted to turn it into a Wayland compositor
Since 2025’s goal has not been completed, I will probably start working on 2026’s goal instead, and go back to work on 2025’s goal when I get bored.
Call for contributions!
I am starting to take contributions to Maestro! If you think you may have valuable skills to bring to the project, join Discord so we can talk about it!
Please note that this is benevolent work. Sadly, the project does not have any budget for compensations :(