This project implements a basic kernel-level thread library for use in educational or custom operating systems. It supports thread creation, context switching, scheduling (preemptive/cooperative), and essential synchronization primitives.
Designed for clarity, minimalism, and educational value in low-level threading concepts.
- Low-level thread creation and termination
- Manual and automatic (preemptive) context switching
- Cooperative and preemptive scheduling support
- Basic synchronization primitives: mutexes, condition variables
- Minimal external dependencies for integration in educational OS kernels
ucontext_t *uc_link // Context to resume when this one returns
sigset_t uc_sigmask // Signals blocked in this context
stack_t uc_stack // Stack for this context
mcontext_t uc_mcontext // Machine-specific saved state (registers, PC, etc.)- Initialization: Create and initialize a new thread
- Switching:
getcontext: Capture current context and prepare for swapsetcontext: Set a thread's context (used for first-time entry)swapcontext: Save current context and switch to another
- Sleeping / Blocking: Threads can block on locks or condition variables
- Termination: Clean up and remove thread from system
running_queue:std::dequeholding ready-to-run thread contextsall_threads:std::unordered_set<tid, Join(state, cv)>
Used for thread join management
waiting_queue: For threads blocked on mutexes or condition variables
- First thread:
setcontextto jump directly into it - All others:
makecontext→ pushed intoready_queue
- Current thread pushed back to
ready_queue - Scheduler pops next thread
swapcontextto resume next
See: swapcontext man page
- Context switch on timer interrupt is treated like a normal function call
- Interrupt handler creates a new stack frame above current user stack
- When interrupt returns, user thread resumes execution naturally
- Disable interrupts before scheduling, re-enable after
- Unlocking a mutex or calling
cv.wait()may require disabling interrupts
Supports:
- Mutexes (locks)
- Condition Variables
- Semaphores (planned or minimal)
- All threads that aren't blocked should run
- No memory leaks: all thread contexts are freed properly
- FIFO order in ready queues
- Threads should return normally
- Interrupts are enabled when running user threads
- Exit cleanly with no dangling locks or blocked threads
- Releasing a mutex not held →
std::runtime_error std::bad_allocif stack memory can’t be allocatedjoinon invalid or already-joined thread- Robust condition variable memory handling
test1: Basic yield between threadstest_join: Multiple threads + join behaviortestpiz: Lock and condition variable correctnesstestrel: Robust error handlingtestint: Interrupt handling test
- Proper semaphores
- Thread priorities
- Better memory pool for context allocation
- Fine-grained timer tuning for preemption