Topic 3b – Coordinating Activities and Shared Resources

Dozens of processes, one CPU, limited resources — the OS keeps the peace.

Learning Objectives

By the end of this topic, you should be able to:

Learning Activities

To help you meet the learning objectives, we have prepared a combination of readings, activities, and videos.

Course Readings

These reading were designed to introduce the course topics to an audience of educators. They should be considered "required" and read in order.

Supplemental Readings

Some participants find it helpful to read about a topic from a source written for a slightly more technical audience. These supplemental readings cover similar material as the course readings but may not fully align with the course learning objectives. Use them as an optional complement to your study, not a substitute for the course readings.

Lesson Videos

These videos support the readings above and may present the material with some deeper connections and worked examples.

Activity

When this course has a face-to-face component I conduct a hands-on, unplugged activity that gives participants an opportunity to explore the problem of deadlock and begin to discuss techniques to avoid deadlock. While you do not have an opportunity to complete this activity with your peers, I think it is worth your time to read the activity and consider what it would look like both with adults and with your students.

Checking for Understanding, Questions

Programs and Processes

  1. Explain the difference between a program and a process in your own words. Use a non-computing analogy to illustrate the distinction.
  2. Can the same program give rise to more than one process at the same time? Explain what that would look like in practice.
  3. What does the process table contain, and which OS component is responsible for maintaining it?
  4. What is the difference between a process that is "ready" and one that is "waiting"? Why does this distinction matter for how the dispatcher allocates CPU time?

The Dispatch Cycle

  1. Walk through what happens, step by step, when an interrupt signal is received by the CPU during a process's time slice.
  2. Why is the ability to save and restore process state essential for multiprogramming to work?
  3. A student asks: "If the computer is switching between processes thousands of times per second, doesn't all that switching slow things down?" How would you respond? Under what conditions is the student right, and under what conditions are they wrong?

Shared Resources and Deadlock

  1. Describe the scenario in which a simple flag fails to protect a nonshareable resource. What is the name for this kind of timing-dependent failure?
  2. What makes a semaphore different from a simple flag? What hardware feature makes the semaphore reliable?
  3. Define critical region and mutual exclusion. How does a semaphore enforce mutual exclusion?
  4. Two processes are deadlocked. Process A holds Resource 1 and is waiting for Resource 2. Process B holds Resource 2 and is waiting for Resource 1. Identify which of the three deadlock conditions are present in this scenario.
  5. For each of the three deadlock conditions, describe one strategy an OS could use to eliminate that condition. Which strategy does spooling use, and how?

Checking for Understanding, Answers

You can compare your answers to the following answer key.

Show Answer Key

Programs and Processes

  1. A program is a static set of instructions stored on disk — it is a recipe, a blueprint, a script. A process is a program in execution: it has a current state, allocated memory, a position in the code, and registers holding working values. A non-computing analogy: a cake recipe is the program; the act of baking the cake (with a specific oven, at a specific moment, with a cook following along) is the process.
  2. Yes. Opening a program twice (two browser windows, two instances of a text editor) creates two separate processes, each with its own state, memory space, and position in execution — even though both are running from the same program file on disk.
  3. The process table contains one entry per active process, recording its process ID, current state (running, ready, waiting), the saved contents of its CPU registers, memory allocation, and other bookkeeping information needed to resume it. The scheduler (and more specifically, the dispatcher) is responsible for maintaining and using this table.
  4. A ready process has everything it needs to run and is simply waiting for the CPU to become available. A waiting process cannot run even if the CPU were free — it is blocked pending some external event (a disk read completing, user input arriving, a semaphore being released). The dispatcher only considers ready processes when selecting the next one to run; a waiting process would waste the CPU time slice, so it is skipped entirely until its event occurs.

The Dispatch Cycle

  1. When an interrupt arrives mid-slice: (1) the CPU finishes the current instruction, then (2) automatically saves the current process's state (registers, program counter) to its entry in the process table — this is the context switch. (3) The CPU switches to privileged mode and transfers control to the OS interrupt handler. (4) The OS handles the interrupt (e.g., noting that a time slice expired, or that I/O completed). (5) The scheduler selects the next ready process, the dispatcher loads its saved state into the CPU registers, and execution resumes.
  2. Without save/restore of process state, switching away from a process would destroy its in-progress work — the registers, program counter, and working values that define exactly where it was. Multiprogramming requires that each process can be paused and resumed exactly where it left off, potentially many thousands of times before it finishes. The context switch mechanism makes this possible.
  3. The student is partly right and partly wrong. Context switches do have a small overhead cost — saving and restoring state takes a few hundred nanoseconds. Under extremely heavy load with very short time slices, this overhead can become significant (thrashing). However, in the normal case, the switching overhead is tiny compared to the time slices themselves, and the benefit is large: processes that are blocked waiting for I/O yield the CPU rather than wasting it, so the overall throughput of the system increases. The computer feels faster under reasonable load, not slower.

Shared Resources and Deadlock

  1. A simple flag fails because reading the flag and setting it are two separate instructions. A context switch can occur between those two steps, allowing a second process to also read the flag as "available" and proceed — resulting in two processes inside what should be an exclusive region simultaneously. This timing-dependent failure is called a race condition.
  2. A semaphore combines the test-and-set into a single, atomic (uninterruptible) hardware instruction. No context switch can occur between reading and setting the semaphore's value, eliminating the race condition. The hardware feature is the atomic test-and-set (or compare-and-swap) instruction that the CPU provides specifically to support this kind of mutual exclusion.
  3. A critical region is a section of code that accesses a nonshareable resource and must not be executed by more than one process at a time. Mutual exclusion is the guarantee that only one process is in a critical region at any given moment. A semaphore enforces this by acting as a lock: before entering the critical region a process decrements the semaphore (blocking if it is already 0); upon leaving it increments the semaphore, allowing a waiting process to proceed.
  4. All three classic deadlock conditions are present: mutual exclusion (each resource can only be held by one process at a time), hold and wait (each process holds one resource while waiting for another), and circular wait (A waits for B's resource while B waits for A's, forming a cycle). The fourth condition sometimes listed — no preemption — is also implied (neither process voluntarily releases what it holds).
  5. One strategy per condition: eliminate mutual exclusion by making the resource shareable where possible (not always feasible); eliminate hold and wait by requiring processes to request all resources they will ever need before starting (or release all held resources before requesting a new one); eliminate circular wait by imposing a global ordering on resources so processes must always request them in the same sequence. Spooling eliminates mutual exclusion for devices like printers: instead of letting processes write directly to the printer (nonshareable), they write to a shared spool file on disk, and a single dedicated spooler process accesses the printer. The printer is no longer contested directly.

Extend Your Learning

The following resources go a little deeper on topics we touched on but did not fully explore in the readings. These are entirely optional — none of this material appears on the Competency Demo — but each one is a natural "next question" from something covered this week.

  • Multi-core processors and true parallelism
    Traditional multiprogramming creates the illusion of simultaneous execution on a single CPU. Modern multi-core processors can run processes genuinely simultaneously on separate cores. This changes the OS's job significantly and introduces new complications for semaphores and critical regions. This accessible article from Lenovo covers how multi-core CPUs work and what the OS must do differently.
    How Multi-Core Processors Work — Lenovo
  • Threads vs. processes
    A thread is a lighter-weight unit of execution that lives inside a process — multiple threads can run within a single process, sharing its memory space. Modern applications use threads extensively (a web browser may have separate threads for the UI, network requests, and JavaScript execution). This Wikipedia article explains the thread/process distinction clearly.
    Thread (computing) — Wikipedia
  • The Dining Philosophers problem
    This classic computer science thought experiment models deadlock and resource competition through five philosophers sitting at a table, each needing two chopsticks to eat. It is one of the most elegant illustrations of why deadlock avoidance is genuinely hard. This Wikipedia article includes the original problem statement and several proposed solutions.
    Dining Philosophers Problem — Wikipedia
  • Priority inversion: the Mars Pathfinder story
    In 1997, the Mars Pathfinder spacecraft experienced repeated system resets caused by priority inversion — a high-priority process was being blocked by a low-priority process holding a semaphore it needed. The fix was applied remotely from Earth. This write-up tells the full story and is a remarkable real-world example of the concepts from this topic.
    What Really Happened on Mars — UNC CS