Chapter 13 — Mutexes, Semaphores, and a Console Lock

Chapter 13 — Mutexes, Semaphores, and a Console Lock
This entry is part 13 of 33 in the series Writing A Linux Style Operating System From Scratch

In Chapter 12, we added wait queues and blocking keyboard input: Now we need synchronization primitives that ordinary kernel code can use. This chapter adds: A mutex provides mutual exclusion: only one thread may hold the protected resource at a time. OSDev describes a mutex as a mutual-exclusion mechanism, similar to a binary semaphore, used

Chapter 12 – Wait Queues and Blocking Keyboard Input

Chapter 12 – Wait Queues and Blocking Keyboard Input
This entry is part 12 of 33 in the series Writing A Linux Style Operating System From Scratch

In Chapter 11, we added the first blocking primitive: That gave the scheduler a way to remove a thread from the ready queue until a future timer tick. Now we need a more general primitive: This is the foundation for real kernel I/O. A keyboard reader should not spin like this: It should block: This

Chapter 11 — Blocking Primitives, Sleep Queues, and Scheduler Hygiene

Chapter 11 — Blocking Primitives, Sleep Queues, and Scheduler Hygiene
This entry is part 11 of 33 in the series Writing A Linux Style Operating System From Scratch

In Chapter 10, we added timer-driven preemption: Now we need the next scheduler capability: blocking. A runnable thread competes for CPU time. A blocked or sleeping thread does not. OSDev describes a blocking process as one that waits for an event, such as a semaphore or message, and is removed from the active scheduling queue

Chapter 10 — Timer-Driven Preemptive Multitasking

This entry is part 10 of 33 in the series Writing A Linux Style Operating System From Scratch

In Chapter 9, we built cooperative multitasking: That works, but it has a major weakness: A thread like that can monopolize the CPU forever. This chapter adds the next step: timer-driven preemption. With preemptive scheduling: OSDev describes preemptive multitasking as scheduling where an interrupt, usually timer-driven, allows the kernel to take control away from the

Chapter 9 — Cooperative Multitasking and Kernel Threads

This entry is part 9 of 33 in the series Writing A Linux Style Operating System From Scratch

We now have enough foundation to start multitasking: This chapter adds the first scheduler. Not a preemptive scheduler yet. A cooperative scheduler. That means each kernel thread keeps running until it voluntarily calls: “` cthread_yield(); textkernel thread objectper-thread kernel stackready queuex86 context switch assemblythread_create()thread_yield()thread_exit()round-robin cooperative schedulingtwo-thread test textcreate two kernel threadsswitch between them cooperativelyprove both

Chapter 8 – Moving the Heap onto Virtual Memory

Chapter 8 – Moving the Heap onto Virtual Memory
This entry is part 8 of 33 in the series Writing A Linux Style Operating System From Scratch

In Chapter 6, the kernel heap still depended on low identity-mapped physical pages. That worked as a bootstrap step, but it tied the heap to the first 16 MiB of RAM. In Chapter 7, we added a real VMM and proved that the kernel can map and unmap pages anywhere the page tables allow. That

Chapter 7 — A Real Virtual Memory Mapping Layer

Chapter 7 — A Real Virtual Memory Mapping Layer
This entry is part 7 of 33 in the series Writing A Linux Style Operating System From Scratch

In Chapter 5 we enabled paging, but only with a fixed identity map: In Chapter 6 we built a heap, but it still had an important weakness: because only the first 16 MiB were identity-mapped. Now we fix the architectural problem. This chapter adds a small virtual memory manager, or VMM: This lets the kernel

Chapter 6 — Building the First Kernel Heap

Chapter 6 — Building the First Kernel Heap
This entry is part 6 of 33 in the series Writing A Linux Style Operating System From Scratch

In Chapter 5, we enabled paging with a simple identity map: That gave us a working paged kernel, but not yet a comfortable way to allocate variable-sized objects. The physical memory manager gives us whole pages: But kernel code usually needs smaller objects: So this chapter builds the first kernel heap. We will keep it

Chapter 5 — Turning On Paging

Chapter 5 — Turning On Paging
This entry is part 5 of 33 in the series Writing A Linux Style Operating System From Scratch

In Chapter 4, we built the first memory-management layer: Now we add the next layer: paging. Paging lets the CPU translate a virtual address into a physical address through page tables. In 32-bit x86 paging without PAE, a virtual address is split into a page-directory index, page-table index, and page offset; page directories and page

Chapter 4 — Reading the Memory Map and Building a Physical Page Allocator

Chapter 4 — Reading the Memory Map and Building a Physical Page Allocator
This entry is part 4 of 33 in the series Writing A Linux Style Operating System From Scratch

Before we add paging, a heap, processes, filesystems, or user programs, the kernel must answer a basic question: Which physical 4 KiB pages of RAM are safe for me to use? Right now, our kernel can boot, print text, catch CPU exceptions, and receive timer/keyboard interrupts. But it still cannot safely allocate memory. This chapter