SwadhyAI Notes

All Operating Systems notes

Start here

A process is still the big container for protection and accounting, but threads are the units the scheduler usually runs. First lesson: list what is shared vs private when you add a thread inside the same process.

Threads vs processes (first principles)

Threads in one process typically share the virtual address space (heap, static data, code) and often the file descriptor table and signal dispositions. Each thread still has its own stack, register set, and kernel scheduling metadata.

That sharing makes communication cheap (pointer passing) but means one serious memory bug can kill every thread in the process. Separate processes trade isolation for IPC cost.

By the end of this page you should be able to

  1. Name at least four resources threads in one process usually share.
  2. Explain why context switches are often cheaper between threads than between processes.
  3. Relate `CLONE_VM` (conceptually) to “same address space.”

When threads help vs hurt

Design intuition before diving into POSIX details.

Threads help

Parallel CPU-bound work on shared data structures; low-latency coordination with mutexes instead of sockets.

Threads hurt

Oversubscription, hidden globals, fragile signal semantics, and fault blast radius across the whole process.

Interview anchor

Be ready to draw one process, two threads and label shared mm vs per-thread stacks.

Operating systems · Threads

Threads vs processes

Shared address space vs isolation

TL;DR

Threads are schedulable units sharing most process resources (VAS, open files, signal dispositions in POSIX) but have private stacks, registers, and TLS, processes isolate by default; threads cooperate in-memory with explicit synchronization.

Summary

Use threads when shared in-memory state wins over IPC cost; use processes when fault isolation or different trust domains matter. Interviews want crisp contrasts plus one failure mode (data race vs SIGKILL isolation).

Diagram

Use this as the picture you would redraw from memory after closing the tab.
Diagram text: the exact Mermaid definition below preserves the nodes, labels, and connections. Enable JavaScript to view the rendered diagram.
Read the diagram definition
flowchart TB
  P[Process: mm + files]
  T1[Thread 1 stack/regs]
  T2[Thread 2 stack/regs]
  P --> T1
  P --> T2

Deeper narrative

Threads share the hard state that is expensive to duplicate: page tables, some signal state, and (by default) file descriptors. That sharing is why parallel parsers are fast, and why one data race can corrupt the whole process.

Mechanism (step by step)

Treat each step as a sentence in the story you tell on a whiteboard.
1

Clone flags decide sharing

`CLONE_VM` shares address space; without it you have a new process.

2

Scheduler sees threads

Each thread is a schedulable entity with its own kernel stack slice.

3

Synchronization replaces IPC

Mutexes protect shared heap instead of sending bytes across sockets.

4

Fault isolation

SIGSEGV in one thread tears down the entire process unless handled per-thread carefully.

Key insights

Each card is a compression of the lesson, use them as spaced-repetition prompts.

Shared heap, private stacks

Heap races are the default bug class; stacks are separate so each thread has call frames and local variables.

File descriptor table sharing

Threads share offset into files unless you `dup`: surprises when two threads `read` the same fd concurrently.

Signal delivery model

Per-thread signal masks matter; process-directed signals choose an arbitrary thread without a mask, subtle debugging.

Fork+threads

Libraries may use `pthread_atfork` handlers to reinitialize locks, shows interaction between process and thread APIs.

Did you know?

Trivia with teeth: the kind of fact that changes how you reason about a design.
Linux represents threads as tasks (`task_struct`) sharing `mm_struct` via `clone(CLONE_VM)`.
`fork` in a multithreaded program is historically dangerous, only the forking thread survives in the child per POSIX rules.
Kernel threads (`kworker`) are not user processes, they run only in kernel mode to do background work.

Common pitfalls

Where smart people still trip, read slowly.

Default stack size × N

Thousands of threads can exhaust virtual memory, pools or fibers mitigate.

Hidden globals

errno is thread-local; other TLS must be explicit, globals bite under concurrency.

Comparison

Process vs thread (typical POSIX)

ProcessThread
Address spacePrivate by defaultShared with peers in process
Creation costHigher (new tables)Lower (reuse mm)
IPC needHigher for tight loopsLower, use locks instead

Glossary

1:1 model

Each user thread maps to one kernel thread (common Linux NPTL).

M:N

Many user threads multiplexed on fewer kernel threads, Go runtime style.

TLS

Thread-local storage for per-thread globals.

Interview follow-ups

  1. Quantify context switch cost thread vs process on Linux.
  2. When would you still choose processes over threads for a worker pool?
  3. How does Go’s M:N model differ from 1:1 pthreads?

Callouts

Answer skeleton

“Threads share VAS and fds; processes default-private; threads cheaper communication, processes stronger crash isolation.”

Walkthrough & deep dive

Left: practical “how would I use this?” threads. Right: slower, code-leaning explanations, open one panel at a time so the page does not feel like a wall of sameness.

Walkthrough

Design

When would you run a browser renderer in a separate process vs thread? (site isolation vs performance).

Deep dive

Green threads history

M:N user threads multiplexed on fewer kernel threads, blocking syscalls could stall many green threads; modern runtimes work around with thread pools and nonblocking I/O.

Thread count

Terminal
grep -c ^processor /proc/cpuinfo
ps -o nlwp= -p $

Self-check

Misses here are cheap; misses in an interview are not. Treat wrong answers as a patch list for tomorrow.

1Threads in one process share…

2Processes isolate faults better than threads because…

3Concurrent unsynchronized writes to shared globals are…