// OPERATING SYSTEMSEight chapters. One machine.

261305 · Chiang Mai University · following Silberschatz, Galvin & Gagne, Operating System Concepts 10th edition. How an OS shares one CPU, one memory and one disk among programs that all think they own the machine.

Ch 1–2 · The machine Ch 3–4 · Processes & threads Ch 5 · Scheduling Ch 6–8 · Concurrency live scheduler works offline
Part 1

What an OS is and does

Chapters 1–2. Interrupts, dual-mode operation, system calls, and the four ways to structure a kernel. The vocabulary everything else is written in.

Part 2

Processes, threads, scheduling

Chapters 3–5. What a process actually is, how threads differ, and the algorithms that decide who gets the CPU next — with the arithmetic the exam asks for.

Part 3

Concurrency and deadlock

Chapters 6–8. Race conditions, the critical-section problem, mutexes, semaphores, monitors, the classic problems — and the four conditions that produce deadlock.

Tools

Two working solvers

A CPU scheduling simulator that draws the Gantt chart and computes waiting and turnaround time for six algorithms, and a Banker's algorithm checker that finds the safe sequence.

The one idea that connects all eight chapters

Every chapter is the same question asked about a different resource: how do you share one thing among many claimants without them noticing, corrupting each other, or getting stuck?

ChapterThe shared thingThe mechanism
1–2the whole machinedual-mode operation, interrupts, system calls
3the illusion of a private machinethe process, the PCB, context switching
4one process's address spacethreads
5the CPUscheduling algorithms
6–7shared datamutexes, semaphores, monitors
8everything at oncedeadlock prevention, avoidance, detection
How to use thisRead a chapter, then go straight to Scheduler and make it compute something. The scheduling arithmetic and the Banker's algorithm are the two places this course reliably takes marks off people, and they are both mechanical once you have seen them work.

// LEARNChapters

All eight chapters, written for understanding rather than transcription. Open one box at a time — each is one idea you could be asked to explain out loud.

1 Introduction — what an OS actually is

There is no single agreed definition. The working one: the OS is the program that runs at all times on the computer — the kernel — plus system programs and application programs.

What it does

It sits between the user and the hardware and acts as resource allocator and control program. It has to be fair, efficient, and prevent programs from interfering with each other.

Interrupts — how the OS ever gets control back

Once a user program is running, the CPU is its CPU. The only reason the OS ever runs again is an interrupt.

  • Hardware interrupt — a device signals the CPU over the system bus.
  • Trap / exception — a software-generated interrupt: an error, or a deliberate system call.
  • The CPU stops, saves state, jumps through the interrupt vector to the handler, then resumes.
Why this mattersAn OS is interrupt driven. No interrupts, no OS — it would hand the CPU to the first program and never get it back.

Dual-mode operation

One mode bit in hardware separates user mode (1) from kernel mode (0). Dangerous instructions are privileged and only run in kernel mode.

user program → system call → trap → mode bit = 0 → kernel runs → return → mode bit = 1

This is the single most examined diagram in Chapter 1. Without hardware support for two modes, no protection is possible at all.

Storage hierarchy

registers → cache → main memory → SSD → hard disk → tape. Going down: bigger, slower, cheaper, and more persistent. Volatile above the disk line, non-volatile below.

Multiprogramming and multitasking

Multiprogramming keeps several jobs in memory so the CPU always has something to run — when one waits for I/O, another gets the CPU. Multitasking (time sharing) switches so frequently that users can interact with each job. That switching requires CPU scheduling (Ch 5) and, if memory is short, swapping or virtual memory.

2 OS Services & Structures

Services, in two groups

  • Helpful to the user: user interface, program execution, I/O operations, file-system manipulation, communications, error detection.
  • Efficient operation of the system itself: resource allocation, logging/accounting, protection and security.

System calls — the only door into the kernel

Programs almost never issue system calls directly; they call an API (Win32, POSIX, the Java API) and the run-time library issues the call. Each call has a number; the OS keeps a system-call table indexed by that number.

Three ways to pass parameters: in registers; in a block/table in memory with the address in a register; or pushed on the stack. Registers are fastest but there may be more parameters than registers.

CategoryExamples
Process controlfork, exit, wait, abort
File managementopen, read, write, close
Device managementioctl, read, write
Information maintenancegetpid, alarm, sleep
Communicationspipe, shm_open, mmap
Protectionchmod, umask, chown

Four kernel structures — know the trade-off

StructureIdeaCost
MonolithicEverything in one address space. UNIX, Linux.Fast, but huge and hard to maintain; one bug can take down the kernel
LayeredLayer n uses only layer n−1.Clean to build and debug; hard to define the layers, and slow from crossing them
MicrokernelMove as much as possible into user space; kernel does little but message passing. Mach.Reliable and extensible, but message passing costs performance
ModulesObject-oriented core with loadable kernel modules (LKM). Linux, Solaris.Best of both — flexible without message-passing overhead

Real systems are hybrid: Linux is monolithic plus modules; macOS and iOS layer a hybrid Mach/BSD kernel; Windows is mostly monolithic with a microkernel heritage.

Exam favourite"Why did microkernels not take over?" — because every service that used to be a function call became a message, and the overhead outweighed the elegance.
3 Processes

A process is a program in execution. The program is passive — a file on disk. The process is active, with a program counter and resources.

The four parts of a process in memory

SectionHoldsSize
Textthe program codefixed
Dataglobal variablesfixed
Heapmemory allocated at run timegrows
Stacktemporary data: parameters, return addresses, localsgrows and shrinks

Five states

new → ready ⇄ running → terminated
            ↑      ↓
          waiting

Only one process is running per CPU core at any instant. Many can be ready, many can be waiting.

The PCB — the process's identity card

The Process Control Block stores everything needed to restart a process: state, program counter, CPU registers, scheduling information, memory-management information, accounting information, I/O status.

Context switchSaving the current PCB and loading another is a context switch. It is pure overhead — the system does no useful work during it — and its cost is why the time quantum in round robin must be large compared with it.

Creating and ending processes

In UNIX, fork() makes a copy of the parent and returns 0 to the child and the child's pid to the parent. Usually the child then calls exec() to replace its image with a new program, while the parent may wait().

  • Zombie — the process has terminated but the parent has not yet called wait().
  • Orphan — the parent terminated first; init/systemd adopts it.

Interprocess communication — two models

Shared memoryMessage passing
Howa region both map and read/write directlysend() / receive() through the kernel
Speedfaster — kernel involved only at setupslower — every message is a system call
Synchronisationthe programmer's problemhandled by the mechanism
Suitsone machine, large datadistributed systems, safety

The producer–consumer problem is the standard shared-memory example, and it walks straight into Chapter 6 — an unsynchronised bounded buffer has a race condition.

4 Threads & Concurrency

A thread is the unit of CPU use. Threads of one process share text, data, heap and open files, but each has its own thread ID, program counter, register set and stack.

The two-line answerThreads share the address space; processes do not. That single fact produces every benefit and every hazard below.

Four benefits

  • Responsiveness — the UI keeps running while another thread blocks.
  • Resource sharing — free, because they share by default.
  • Economy — creating a thread is far cheaper than creating a process.
  • Scalability — a multithreaded process can genuinely run in parallel on multiple cores.

Concurrency ≠ parallelism

Concurrency = making progress on more than one task. Parallelism = actually performing more than one at the same instant. A single core can be concurrent but never parallel.

Amdahl's Law — the ceiling on what more cores can buy you, where S is the strictly serial fraction:

speedup ≤ 1 / ( S + (1 − S)/N )

If 25% of the work is serial, then even with infinite cores the speedup can never exceed . Serial fraction, not core count, is the limit.

Multithreading models

ModelMeaningWeakness
Many-to-Onemany user threads → one kernel threadone blocking call blocks all of them; no parallelism
One-to-Oneeach user thread → its own kernel threadtrue parallelism, but creating threads is expensive. Linux, Windows
Many-to-Manymany user threads multiplexed onto ≤ that many kernel threadsflexible but hard to implement

Implicit threading

Concurrency is hard, so hand it to a library: thread pools, fork-join, OpenMP, Grand Central Dispatch. A thread pool also caps the number of threads, which stops a server from being flattened by requests.

Threading issues

  • fork() and exec() — does fork duplicate all threads or only the caller? If exec follows immediately, duplicating them all is wasted.
  • Signal handling — which thread receives the signal? The one it applies to, every thread, or a dedicated thread.
  • Thread cancellationasynchronous (kill it now; may leave data inconsistent) vs deferred (it checks a cancellation point and exits cleanly). Deferred is safer.
  • Thread-local storage — per-thread data, unlike local variables which vanish per call.
5 CPU Scheduling

The whole chapter rests on one observation: process execution is a CPU–I/O burst cycle. A process computes for a while, then waits for I/O, and repeats. The burst distribution is what scheduling exploits — there are many short bursts and few long ones.

When does the scheduler run?

Four moments. A process:

  1. switches from running → waiting (e.g. an I/O request)
  2. switches from running → ready (an interrupt)
  3. switches from waiting → ready (I/O finished)
  4. terminates
The definition that gets examinedIf scheduling happens only at 1 and 4 it is nonpreemptive — the process keeps the CPU until it gives it up. Otherwise it is preemptive. Cases 1 and 4 offer no choice; 2 and 3 do. Virtually every modern OS is preemptive.

The dispatcher then does the handover: switch context, switch to user mode, jump to the right location. The time this takes is dispatch latency.

The five criteria — and which way is better

CriterionMeaningWant
CPU utilisationkeep the CPU busymaximise
Throughputprocesses completed per time unitmaximise
Turnaround timesubmission → completionminimise
Waiting timetotal time sitting in the ready queueminimise
Response timesubmission → first responseminimise
turnaround = completion − arrival
waiting     = turnaround − burst
response   = first time on CPU − arrival

Learn those three lines and most scheduling questions become arithmetic. Note waiting time is not "time before it first runs" — it accumulates every time the process is put back in the ready queue.

The algorithms

  • FCFS — first come, first served. Simple, nonpreemptive, and vulnerable to the convoy effect: one long process at the front makes everyone wait. Average waiting time depends heavily on arrival order.
  • SJF — shortest job first. Provably optimal for minimum average waiting time. The catch: you cannot know the next burst length, so you predict it by exponential averaging of past bursts.
  • SRTF — preemptive SJF. A newly arrived shorter job preempts the running one.
  • Round Robin — each process gets a quantum q, then goes to the back of the queue. No process waits more than (n−1)q. Large q degenerates to FCFS; tiny q drowns in context-switch overhead. Typically 10–100 ms.
  • Priority — highest priority first; SJF is priority scheduling where the priority is the predicted burst. Risk: starvation of low-priority processes. Fix: ageing — raise priority the longer a process waits.
  • Multilevel queue — a separate queue per priority, often by process type. Multilevel feedback queue lets processes move between queues, which is how a real OS separates interactive from CPU-bound work automatically.
Go and use itEvery one of these is implemented in the Scheduler tab. Type in a process table and it draws the Gantt chart and computes the averages — including the four textbook examples, already loaded.

Beyond one CPU

Multiprocessor: usually symmetric (SMP), each core self-scheduling from a common queue or its own. Watch for load balancing (push and pull migration) and processor affinity — a process prefers the core whose cache is already warm.

Real-time: soft real-time gives critical processes preference; hard real-time guarantees a deadline. Rate-monotonic scheduling assigns priority by period (shorter period = higher priority); earliest-deadline-first assigns it dynamically.

6 Synchronization Tools

Concurrent access to shared data can leave it inconsistent. That is a race condition — the outcome depends on the order in which threads happen to run.

counter++ → reg = counter ; reg = reg + 1 ; counter = reg

Three machine instructions, not one. Interleave two threads' copies of those three and an increment silently disappears. This is why counter++ is not atomic.

The critical-section problem

Each process has a critical section where it touches shared data. A correct solution must satisfy all three:

  1. Mutual exclusion — only one process in its critical section at a time.
  2. Progress — if no one is in the critical section, someone wanting in must get in; the decision cannot be postponed indefinitely.
  3. Bounded waiting — a limit on how many others may enter before a waiting process gets its turn.

Peterson's solution is the classic software-only proof of the idea, using a shared turn and a flag[] array. It satisfies all three — but it is not guaranteed on modern hardware, because processors reorder reads and writes. It is taught for the reasoning, not for use.

Hardware support

  • Memory barriers — force all earlier memory changes to become visible before continuing.
  • Atomic instructionstest_and_set() and compare_and_swap() do read-modify-write in one uninterruptible step.
  • Atomic variables — the usable face of the above, e.g. an integer that increments atomically.

The three tools you must be able to compare

ToolWhat it isWatch out for
Mutex lockacquire() / release() around the critical section. Boolean available.The simple version spins — busy waiting. A spinlock is fine only if the wait is shorter than a context switch.
SemaphoreInteger S with wait() and signal(). Counting (any range) or binary (0/1, like a mutex).Can be used for ordering as well as exclusion. Easy to misuse — swap the operations and you deadlock.
MonitorA language construct: only one process active inside at a time, with condition variables supporting wait() and signal().Safer because the compiler enforces it; signal() on a condition with nobody waiting does nothing — unlike a semaphore, which remembers.
The distinction that gets marksA semaphore's signal() increments and is remembered. A condition variable's signal() is lost if no one is waiting. Getting these the wrong way round is the classic exam error.

Liveness — three ways to be stuck

  • Deadlock — each waits for an event only the other can cause.
  • Priority inversion — a high-priority process waits on a lock held by a low-priority one. Fixed by priority inheritance.
  • Starvation — a process waits forever on a semaphore queue.
7 Synchronization Examples

Three classical problems. They exist to test any newly proposed synchronisation scheme — if your primitive cannot express these cleanly, it is not good enough.

1 · Bounded buffer (producer–consumer)

Producers add to a buffer of n slots, consumers remove. Three semaphores:

mutex = 1   (mutual exclusion on the buffer)
full  = 0   (slots currently filled)
empty = n   (slots currently free)

The producer waits on empty and signals full; the consumer does the reverse. Order matters: take mutex after the counting semaphore, never before, or you deadlock holding the lock.

2 · Readers–writers

Many readers may read at once; a writer needs exclusive access. The variants differ in who gets preference:

  • First variant — readers preferred. No reader waits unless a writer already holds it → writers can starve.
  • Second variant — writers preferred. A waiting writer blocks new readers → readers can starve.

Some systems provide this directly as a reader–writer lock.

3 · Dining philosophers

Five philosophers, five chopsticks, each needs the two beside them. The naive solution — pick up left, then right — deadlocks if all five pick up their left chopstick simultaneously. That is the whole point of the problem, and it is a live demonstration of Chapter 8's four conditions.

Fixes: allow at most four at the table; pick up both chopsticks only if both are free (in a critical section); or make odd philosophers take left-then-right and even ones right-then-left, breaking the circular wait.

Deadlock-free is not starvation-freeA solution can avoid deadlock and still let one philosopher never eat. Both must be argued separately.
8 Deadlocks

A set of processes is deadlocked when every process in the set is waiting for an event that only another process in the set can cause.

The four necessary conditions — all must hold

ConditionMeaningBreak it by…
Mutual exclusionat least one resource is non-sharablerarely possible — some resources simply cannot be shared
Hold and waita process holding one resource waits for anotherrequest everything at once, or release all before requesting more
No preemptiona resource is released only voluntarilytake resources away from a waiting process
Circular waitP0 waits for P1, P1 for P2, … Pn for P0impose a total ordering on resource types and require requests in increasing order

All four must hold simultaneously — so preventing deadlock means making sure at least one can never happen. In practice, ordering resources to break circular wait is the usable one.

Resource-allocation graph

Processes are circles, resource types are rectangles with a dot per instance. A request edge P→R, an assignment edge R→P.

  • No cycle → definitely no deadlock.
  • Cycle, one instance per resource type → definitely deadlock.
  • Cycle, several instancespossibly deadlock. A cycle alone is not proof.

Four ways to handle it

  1. Prevention — structurally forbid one of the four conditions.
  2. Avoidance — require processes to declare their maximum claim in advance, then only ever enter safe states. This is the Banker's algorithm.
  3. Detection and recovery — let it happen, notice, then recover.
  4. Ignore it — pretend deadlocks never occur. What UNIX, Linux and Windows all actually do, on the grounds that they are rare and the cost of prevention is high.

Safe state — the idea behind avoidance

A state is safe if there is a sequence of all processes such that each can obtain its remaining need from what is currently available plus what the earlier processes will release. Then:

safe → no deadlock
unsafe → deadlock is possible, not certain
avoidance = never leave the safe set

Banker's algorithm handles multiple instances per resource type using Available, Max, Allocation and Need, where Need = Max − Allocation. A request is granted only if the resulting state is still safe.

Try itThe Scheduler tab has a working Banker's checker preloaded with the textbook snapshot — it computes the Need matrix and finds the safe sequence, and lets you test a request.

Recovery

Abort processes — all deadlocked ones, or one at a time until the cycle breaks. Or preempt resources, which raises three questions: which victim to choose (cost), how far to roll back, and how to avoid always picking the same victim — starvation.

// SOLVERSScheduler & Banker's

Two working implementations, not lookup tables. Type in any process table and the scheduler runs the real algorithm, draws the Gantt chart and computes every column the exam asks for.

CPU scheduling simulator

Edit the table, pick an algorithm, press Run. Times are unitless — use whatever the question uses.

ProcessArrivalBurstPriority

Worked textbook examples

Every figure below is produced by the simulator above — load the example and check it yourself.

FCFS — order changes everything

Bursts P1=24, P2=3, P3=3, all arriving at 0.

order P1,P2,P3 → waits 0, 24, 27 → average 17
order P2,P3,P1 → waits 6, 0, 3   → average 3

Same processes, same algorithm, 5.7× difference. That is the convoy effect: one long job at the front holds up everyone behind it.

SJF — the optimal one

Bursts 6, 8, 7, 3 all available at 0 → run shortest first: P4, P1, P3, P2.

waits 3, 16, 9, 0 → average 7

SJF is provably optimal for average waiting time. The catch is that it needs the next burst length, which cannot be known — only predicted by exponential averaging.

SRTF — preemptive SJF

Arrivals 0, 1, 2, 3 with bursts 8, 4, 9, 5.

Gantt: P1(0–1) P2(1–5) P4(5–10) P1(10–17) P3(17–26)
waits = (10−1) + (1−1) + (17−2) + (5−3) = 26 → average 6.5

Round Robin, q = 4

Bursts 24, 3, 3.

Gantt: P1(0–4) P2(4–7) P3(7–10) then P1 straight through to 30
average waiting 5.67, average turnaround 15.67

Higher average turnaround than SJF, but much better response time — everyone runs within the first 10 units. That trade is the reason RR exists.

Priority

Bursts 10, 1, 2, 1, 5 with priorities 3, 1, 4, 5, 2 (1 = highest).

order P2, P5, P1, P3, P4 → average waiting 8.2

Note P4 waits 18 units. Push that pattern far enough and low-priority processes starve — the fix is ageing.

Banker's algorithm

Preloaded with the textbook snapshot: 5 processes, 3 resource types A(10) B(5) C(7). Edit any cell and re-run.

Test a request

How the algorithm reads Need = Max − Allocation. A state is safe if you can order every process so each one's remaining Need fits in what is Available plus what the earlier ones give back when they finish. Grant a request only if the state after pretending to grant it is still safe.

Safe means deadlock is impossible. Unsafe does not mean deadlocked — only that deadlock has become possible, which is why avoidance refuses to go there.

// TRAININGDrills

Cards to make the definitions automatic, then a mock exam that explains every answer.

Flashcards

Click to flip. Keyboard: Space flip · ←/→ move · G got it · A again.

Ch 1–4
click to flip
click to flip back

Mock exam

Single-answer questions grade the moment you click.

// LAST LOOKCheat Sheet

Every formula, list and number on one screen.

Ch 5 The three formulas

turnaround = completion − arrival
waiting     = turnaround − burst
response   = first CPU time − arrival

Round robin: no process waits more than (n−1)q. Amdahl: speedup ≤ 1/(S + (1−S)/N).

Ch 5 Algorithms at a glance

AlgorithmPreemptive?StrengthWeakness
FCFSnosimple, fair by arrivalconvoy effect
SJFnooptimal average waitburst length unknowable
SRTFyesoptimal with arrivalsmore context switches
RRyesbest response timehigher turnaround; q sensitive
Priorityeitherexpresses importancestarvation → fix with ageing
MLFQyesseparates I/O-bound from CPU-bound automaticallymost parameters to tune

Ch 6 The three requirements

Mutual exclusion · Progress · Bounded waiting. A solution must satisfy all three.

Semaphore signal() is remembered. Condition-variable signal() is lost if nobody waits. That is the classic mix-up.

Ch 8 The four conditions

Mutual exclusion · Hold and wait · No preemption · Circular wait. All four must hold at once — prevention removes any one, and breaking circular wait by ordering resources is the practical route.

Need = Max − Allocation. Safe ⇒ no deadlock. Unsafe ⇒ deadlock possible, not certain. Cycle in an RAG with one instance per type ⇒ deadlock; with multiple instances ⇒ maybe.

Ch 1–4 Fast facts

Process sectionstext · data · heap · stack
Process statesnew · ready · running · waiting · terminated
Threads sharecode, data, files — not registers or stack
fork() returns0 to the child, the child's pid to the parent
Kernel structuresmonolithic · layered · microkernel · modules
Mode bit0 = kernel, 1 = user

// WHO BUILT THISZann

One of five course consoles for this semester. Same shell, same shortcuts, same offline-first rule.

Author

NameThu Htoo Zan — Zann
Student ID670615524
ProgrammeInformation Systems & Network Engineering (ISNE)
FacultyFaculty of Engineering, Chiang Mai University

This course

Code261305
TitleOperating Systems
TextSilberschatz, Galvin & Gagne — Operating System Concepts, 10th edition
CoveredChapters 1–8
On the contentThese notes are my own restatement of course concepts, written for revision. Lecture slides and textbook figures remain the property of their authors and are not redistributed here.

Built with

Vanilla HTML, CSS and JavaScript. No framework, no build step, no dependencies, no network calls. The scheduling simulator and Banker's checker are real implementations — every worked example on this site is produced by running them.

ZZANN