1. Building an UEFI x64 kernel from scratch: A long trip to userspace

    When I just started programming, one of my first major projects was building my own kernel. Of course, I failed misserably. But I learned a lot. Back then, x64 didn't dominate the market and I never even heard about UEFI. Copy pasting code bits from tutorials and forum posts I ended up drawing some things to the screen based on keyboard input. However, I never managed to get to userspace (/userland/CPL 3).

    Things have changed a bit, and I decided to finally write a 'modern' UEFI x64 kernel which is able to get to userspace, and document my progress …

    read more
  2. Fixing the posix Batch job scheduler by updating its load average limit

    batch(1) is a little known posix command that supposedly takes a list of jobs/shell scripts and executes them when the load average of the computer drops below a certain level. It's far from an ideal scheduler, but it's builtin and does what is should do. Problem is, the queued commands actually do not execute sometimes. The load average limit is 1.5 by default, but I have 6 cores/12 threads, so my load average rises easily above that.

    The atd(8) daemon is responsible for job execution. Add -l $(your_load_limit) to the atd invocation in /etc/systemd …

    read more
  3. Numerical solution of linear PDEs: Computing the Crank-Nicolson matrix automatically

    The Crank-Nicolson method rewrites a discrete time linear PDE as a matrix multiplication $$\phi_{n+1}=C \phi_n$$. Nonlinear PDE's pose some additional problems, but are solvable as well this way (by linearizing every timestep). A major advantage here is that going $$k$$ steps into the future is just $$\phi_{n+k}=C^{k}\phi_n$$, and calculating a matrix power is polynomial time. The method is in general very stable.

    For an assignment I had to construct the Crank-Nicolson matrix for a simple linear 1 dimension PDE, which had to be derived by hand. That's a bit labourus, so I …

    read more
  4. Overwrite an existing C/C++ function without LD_PRELOAD hacks

    In a ~~failed~~ attempt to speed up CPython using a C++ extension, I found myself looking for a solution to overwrite (monkey patch) a function in the compiled C code. On linux, this is normally possible with LD_PRELOAD, which enables you to prepend a library in the dynamic linker search path. When your program requests an external function like malloc, the dynamic linker starts searching for it and hopefully finds it in your prepended library. The program will then call that function instead of the version from say, glibc. However, this was not a possibility here, as I wanted to …

    read more
  5. Recursive sata structures: Catamorphism with context

    In haskell, the Fix f data type allows you to specify a recursive datatype from its fixpoint. Folds and unfolds, as catamorphisms and anamorphisms, come for free. With these recursion schemes, functions can be specified over the data type without explicit recursion. A catamorphism folds bottom-top to a single value, while its dual the anamorphism can be used to unfold a single value.

    newtype Fix f = Fix { unFix :: f (Fix f) }
    
    cata :: Functor f => (f a -> a) -> Fix f -> a
    cata alg = alg . fmap (cata alg) . unFix
    
    ana :: Functor f => (a -> f a) -> a -> Fix f
    ana coalg = Fix . fmap …
    read more