source

02 Processes And Threads

Processes and Process Management

What is a Process?

An application is just a program stored on disk. At this stage, it’s static (not running).

A process is an active entity.


What a Process Looks Like in Memory

Encapsulation of Process State

A process contains all the information needed for a running application:

All of this together forms the state of the process.

Address Space

The operating system gives each process its own address space - a continuous range of virtual memory addresses from V0V_0 to VmaxV_{max}.

This isolates processes from one another.

Inside this space, different sections are laid out in different regions:

Virtual Addresses

The potential range of addresses in process address space go from V_0 to V_max. They are virtual because they don’t have to correspond to actual locations in physical memory.

This enables: Isolation, Flexibility, Security


Execution State of a Process

The operating system must track what a process is doing at any moment.

If the OS stops a process, it needs to remember exactly where it left off so the process can resume seamlessly.

Key Components of Process Execution

Program Counter (PC):

CPU Registers:

Stack and Stack Pointer (SP):


Process Control Block (PCB)

The OS keeps all of this information (PC, registers, stack pointer, memory info, state, etc.) in a data structure called the Process Control Block (PCB).

The PCB is crucial for context switching.

PCB Contains:

The PCB is created when the process is initially created and is also initialized at that time. Certain fields of the PCB may be changed when process state changes (some fields can change often).

How Execution Works with PCB

PCB is stored in memory on behalf of each process. It holds all the critical execution state:


Context Switching

A context switch happens when the CPU switches from one process (say P1) to another (say P2).

This operation is EXPENSIVE:

Direct cost: Number of CPU cycles required to load and store a new PCB to and from memory

Indirect cost: Even though the OS can switch processes quickly by saving/restoring the PCB, the loss of cache data makes the resumed process slower initially. Too many context switches reduce overall system performance.

Hot cache: If the process is currently running and its needed data is already in cache, execution is very efficient

Cold cache: If the process was swapped out (due to context switch), its cache data gets cleared. When it resumes later, cache is empty and the CPU has to refill it from memory.


Process Life Cycle: States

  1. New: When a process is first created, it is in the new state. The OS does admission control (allocates a PCB and initializes resources). The process is not yet ready to run.

  2. Ready: Once initialized, the process moves to the ready state. It is prepared to run but is waiting for the CPU to become available.

  3. Running: When the scheduler picks a process from the ready queue, it goes into the running state. The process instructions are now being executed on the CPU (the active state of execution).

  4. Interrupt or I/O:

    • a. Interrupt / Time Slice Ends → The process is moved back to ready (so another process can use the CPU)
    • b. I/O request or event wait → The process moves to the waiting state
  5. Wait: The process is waiting for some event (e.g., I/O completion, network packet arrival). It is not using the CPU, but is still active in the system.

  6. Terminated: When a process finishes execution (normally or due to an error), it moves into the terminated state. The OS cleans up its resources and removes its PCB.


Process Creation

A process can create child processes. All processes form a tree-like hierarchy.

When the OS boots, it creates root processes with special (privileged) access. These root processes then create other processes, forming the process hierarchy.

Two Main Mechanisms of Process Creation

fork():

exec():


Role of the CPU Scheduler

The CPU scheduler manages how processes use the CPU resources. It determines which process will use the CPU next, and how long that process has to run.

OS Must:

CPU Efficiency

The CPU’s efficiency is defined as:

Efficiency=Time spent executing processesTotal computation time\text{Efficiency} = \frac{\text{Time spent executing processes}}{\text{Total computation time}}

Every time the OS does a context switch (saving PCB, restoring another), it uses CPU cycles that don’t directly help execute a process. This time is called scheduling overhead. If context switches happen too often, a lot of CPU time is wasted.

Timeslice

The timeslice is how long a process gets to run before the scheduler interrupts it.

Design Question: What are appropriate timeslice values? What criteria is used to decide which process is the next to run?

For I/O requests, the process is sent back to the ready queue.


Threads

Process vs. Thread

A single-threaded process is represented by two components:

All of this information is represented by the OS in a process control block.

A thread is a smaller unit of execution within a process:

Each thread has its own data structure to represent information specific to its execution context.


Multithreading

Benefits

  1. Parallelism: While each thread is executing the same code, each thread may be executing a different instruction (in the sense of different line or function) → parallel execution → speed up the program’s execution

  2. Specialization: We can give higher priority to tasks that handle more important tasks or service higher paying customers → each thread may only need a small amount of data/code → the entire state might fit into the cache (fast)

Memory requirements for a multiprocess application are greater than those of a multithreaded application.

Even on a Single CPU

Even though only one thread runs at a time, threads let the CPU stay busy by switching when one is waiting.


Synchronization Mechanisms

Since threads share the same virtual to physical address mappings, and they share the same address space, we could see data race problems: One thread can try to read the data while another modifies it, leading to inconsistencies.

Mutual Exclusion (Mutex)

Mutual exclusion (through mutex): Only one thread at a time is granted access to some data. The remaining threads must wait their turn.

Condition Variable

A thread can wait on another thread, and be able to exactly specify what condition the thread is waiting on.


Thread Creation

We need some data structure to represent a thread:

Creating a thread is conceptually like a fork (not the UNIX fork(), but similar idea):

Thread Join

Once a child thread finishes, we need a way for it to return results or signal the parent. We also need to ensure the parent doesn’t exit before its child threads (otherwise the process would die and kill the threads).

The parent thread can call join on a child thread:

This ensures proper synchronization — parent waits for child before moving on if necessary.

Example

Thread thread1;
Shared_list list;
thread1 = fork(safe_insert, 4);
safe_insert(6);
join(thread1);

The issue is that the order of parent thread and child is unpredictable unless we synchronize (with join or locks).


Multithreading Models

1. One-to-One Model

Mapping: Each user-level thread = 1 kernel-level thread

When you create a thread in your program, the kernel creates a real kernel thread too.

Pros:

Cons:

2. Many-to-One Model

Mapping: Many User threads → 1 Kernel thread

The user-level thread library decides which user thread runs, but the kernel only sees one thread.

Pros:

Cons:

3. Many-to-Many Model

Mapping: Many User threads ↔ Many Kernel threads

Kernel is aware of multithreading, but not every user thread must have a dedicated kernel thread.

Supports:

Pros:

Cons:


Scope of Multithreading

Process Scope (User-Level)

System Scope (Kernel-Level)

Difference: With process scope, fairness is at the process level. With system scope, fairness is at the thread level.


Multithreading Patterns

Boss/Workers Pattern

Setup:

Variants:

Scaling:

Pros: Simple, easy to understand

Cons: Bottleneck at boss thread; load balancing tricky

Pipeline Pattern

Setup: Break work into stages (like an assembly line)

Example: A 6-step process → 6 thread types, each for one stage

Execution:

Scaling: If one stage is slow (the bottleneck), add more threads to that stage

Pros: Specialization, good cache locality, natural concurrency

Cons: Hard to keep balanced; bursts of input can overwhelm a stage

Layered Pattern

Setup: Group related subtasks into layers

Example:

Pros: Some specialization without being as rigid as a pipeline

Cons: Synchronization between layers can be complex