All projects

Systems / 2026

Multi-threaded Operating System

A C++ and assembly operating system implementing cooperative and preemptive context switching, synchronization primitives, and ownership-aware smart pointers.

Overview

I built an operating system in C++ and assembly that runs multiple threads on shared hardware. The work covers three layers that have to agree with each other: context switching in both cooperative and preemptive forms, synchronization primitives that let threads coordinate safely, and smart pointers providing strong, weak, and unique ownership semantics.

Problem and motivation

Concurrency is usually met from above, through a runtime that already guarantees threads exist and that a lock means something. I wanted to build the layer that makes those guarantees.

A thread is, concretely, a saved register set and a stack. A lock is a data structure plus an agreement about when a thread may proceed. Implementing both meant confronting the moment where those abstractions are not yet true.

Approach

Context switching came first, because everything else depends on it. Saving and restoring execution state is inherently machine-specific, so that path is written in assembly, with C++ above it deciding which thread should run next.

Cooperative switching came before preemptive switching. Under cooperation, a thread yields at a point it chooses, so the set of moments where a switch can occur is small and known. Preemption removes that guarantee: a switch can land between any two instructions, which is what makes synchronization necessary rather than merely convenient.

Ownership came last. Smart pointers with strong, weak, and unique semantics make the lifetime of shared kernel objects explicit instead of leaving it to convention.

Architecture

The system separates concerns along the boundary of what the hardware forces:

  1. Assembly context switch: saves the outgoing thread’s register state and restores the incoming thread’s, the one place the machine’s calling convention is fully exposed.
  2. Scheduling and thread state: C++ structures tracking which threads exist and which is eligible to run.
  3. Synchronization primitives: the mechanisms threads use to establish mutual exclusion and ordering once preemption makes interleaving arbitrary.
  4. Ownership types: unique ownership for objects with one owner, strong references for shared lifetime, and weak references for observers that must not keep an object alive.

Challenges and tradeoffs

The recurring difficulty is that the code implementing concurrency cannot assume concurrency is already safe. A scheduler manipulating thread state is itself interruptible, so its own critical sections have to be protected by something more primitive than the locks it provides to everyone else.

Moving from cooperative to preemptive switching is where latent assumptions surface. Code that was correct only because it happened never to be interrupted stops being correct, and the failures are timing-dependent rather than reproducible on demand.

Weak references exist to break the cycles that strong references create. Adding them costs an extra indirection and the possibility that a reference no longer resolves, a cost paid deliberately to make lifetime bugs visible at the point of use instead of at shutdown.

Result

The system runs multiple threads with both cooperative and preemptive context switching, provides synchronization primitives for coordinating between them, and manages object lifetime through smart pointers with strong, weak, and unique ownership. The source is not published.

What I learned

Building the layer underneath threads changed how I read concurrent code. A race is not an event that occurs; it is a claim about ordering that was never actually established. Having written the scheduler that decides those orderings, I now look first for where a piece of code assumes it will not be interrupted, which is the same instinct that pipeline hazards and hardware timeouts demand elsewhere in my work.

Contact information

Based in Austin, Texas

Let’s talk.

Email works best, but feel free to reach out anywhere.

Phone
(469) 465-1537
Primary email
[email protected]
University email
[email protected]
Profiles