Introduction to RTOS Part 10 - Deadlock and Starvation | Digi-Key Electronics

Introduction to RTOS Part 10 - Deadlock and Starvation | Digi-Key Electronics

Dining Philosophers Problem: Understanding Starvation and Deadlock

Introduction to the Dining Philosophers Problem

  • Five philosophers sit at a round table, each with one chopstick placed between them. They can only eat when they have two chopsticks.
  • This scenario illustrates the classic dining philosophers problem, which is a metaphor for multiple threads trying to access shared resources in computing.

Importance of the Problem

  • The dining philosophers problem highlights critical issues in multi-threading: starvation and deadlock.
  • In this analogy, philosophers represent tasks or threads, chopsticks symbolize semaphores or mutexes, and the bowl of noodles represents shared resources like global variables or serial ports.

Starvation Explained

  • If higher priority tasks (e.g., Sorawana and Confucius) continuously take chopsticks without yielding, lower priority tasks may starve due to lack of access to resources.
  • To prevent starvation on single-core systems, high-priority tasks should yield periodically to allow other tasks to run.

Techniques to Prevent Starvation

  • On multi-core systems, high-priority tasks can be assigned different cores or triggered by interrupts/events for better resource sharing.
  • Aging is another technique where waiting tasks gradually increase their priority over time if they remain unexecuted. This ensures that all tasks eventually get CPU time.

Deadlock Overview

  • A simple algorithm where each philosopher picks up one chopstick can lead to deadlock if all hold onto their left chopstick without being able to pick up the right one.
  • Deadlock occurs when no philosopher can proceed because they are all waiting for a resource held by another philosopher.

Best Practices Against Deadlock

  • Implementing best practices in concurrent programming helps prevent deadlocks. For example, ensuring that task priorities are managed effectively during mutex acquisition.
  • A practical example involves two tasks taking two mutexes; introducing delays can force deadlocks for demonstration purposes but also highlights potential bugs in real applications.

Conclusion on Managing Resources

Understanding Deadlock and Livelock in Concurrency

The Problem of Deadlock

  • A deadlock occurs when two tasks are waiting on each other to release resources, preventing both from continuing. This highlights the risks associated with using multiple mutexes and semaphores.
  • To prevent deadlocks, it's crucial to avoid having a task block indefinitely while waiting for a mutex or semaphore. Implementing timeouts can help manage this issue effectively.

Implementing Timeouts

  • By creating a timeout (e.g., 1 second) for tasks attempting to acquire a mutex, if a task times out, it releases any held mutexes and retries after a delay. This allows one task to proceed if another is blocked.
  • However, timeouts do not eliminate all concurrency issues; they can lead to livelock where tasks continuously retry without making progress due to synchronized timeouts.

Solutions for Deadlock and Livelock

Dijkstra's Solution: Hierarchical Resource Allocation

  • Dijkstra proposed assigning priorities or numbers to resources (chopsticks). Philosophers pick up the lower-numbered chopstick first, ensuring that at least one philosopher can eat without blocking others.
  • In this scenario, only one chopstick remains unpicked at any time, allowing other philosophers access sequentially and preventing deadlocks.

Implementation of Mutex Order

  • When coding this solution, it's good practice to release mutexes in reverse order of acquisition. This maintains consistency and reduces complexity in resource management.
  • Both tasks should acquire the same order of mutexes (e.g., always acquiring mutex 1 before mutex 2), mirroring the hierarchical approach used by philosophers.

Introducing an Arbitrator

  • Another method involves using an arbitrator (like a waiter), which grants permission for tasks to access shared resources. This ensures that only one task operates at any given moment.
  • While effective in preventing deadlocks, this approach limits parallel execution since it serializes access to resources.

The Dining Philosophers Challenge

  • The challenge involves implementing both hierarchical allocation and arbitrator solutions within an Arduino sketch simulating five philosophers trying to eat without encountering deadlock.
  • Participants must ensure that all philosophers get their chance without falling into deadlock scenarios while managing delays intentionally included in the code for testing purposes.
Video description

Starvation and deadlock are two common bugs that can occur in concurrent programming. Starvation happens when one one or more threads do not get a chance to run or do not get access to a shared resource because other (often higher priority) threads are hogging the CPU or resource. The code for the Dining Philosophers challenge can be found here: https://github.com/ShawnHymel/introduction-to-rtos/blob/main/10-deadlock/esp32-freertos-10-challenge-dining-philosophers/esp32-freertos-10-challenge-dining-philosophers.ino The solution to the challenge in the video can be found here: https://www.digikey.com/en/maker/projects/introduction-to-rtos-solution-to-part-10-deadlock-and-starvation/872c6a057901432e84594d79fcb2cc5d Code for this video series (including demonstrations, challenges, and solutions) can be found here: https://github.com/ShawnHymel/introduction-to-rtos We can avoid starvation by ensuring that higher-priority tasks yield the processor periodically to allow lower-priority tasks a chance to run. Additionally, the higher-priority tasks should make sure to release any shared resources they might have to allow lower-priority tasks access to them. We can also implement a technique called “aging” in a high priority task or in the scheduler itself. Aging gradually increases the priority of any task that has been in the blocked state for some period of time. Eventually, the task will reach the same priority level as the high priority tasks that are hogging the CPU/resource, and the previously low-priority task will get a chance to run. After performing its required actions, the low-priority task will have its priority downgraded to its original level to start the aging process again. In the video, we provide the classic “Dining Philosophers” as an analogy to demonstrate starvation and deadlock. Deadlock occurs when all tasks are waiting on each other for a lock (e.g. mutex or semaphore) and no task is able to continue execution. Deadlock can result in system-wide failure and should be avoided at all costs. We also give two possible solutions to the Dining Philosophers problem, including assigning a hierarchy to the locks as well as using a mutex to control access to the locks. Product Links: https://www.digikey.com/en/products/detail/adafruit-industries-llc/3405/7244967 Related Videos: Introduction to RTOS Part 1 - What is a Real-Time Operating System (RTOS)? - https://youtu.be/F321087yYy4​ Introduction to RTOS Part 2 - Getting Started with FreeRTOS - https://youtu.be/JIr7Xm_riRs​ Introduction to RTOS Part 3 - Task Scheduling - https://youtu.be/95yUbClyf3E​ Introduction to RTOS Part 4 - Memory Management - https://youtu.be/Qske3yZRW5I​ Introduction to RTOS Part 5 - Queue - https://youtu.be/pHJ3lxOoWeI​ Introduction to RTOS Part 6 - Mutex - https://youtu.be/I55auRpbiTs​ Introduction to RTOS Part 7 - https://youtu.be/5JcMtbA9QEE​ Introduction to RTOS Part 8 - https://youtu.be/b1f1Iex0Tso Introduction to RTOS Part 9 - https://youtu.be/qsflCf6ahXU Introduction to RTOS Part 10 - https://youtu.be/hRsWi4HIENc Introduction to RTOS Part 11 - https://youtu.be/C2xKhxROmhA Introduction to RTOS Part 12 - https://youtu.be/LPSHUcH5aQc Related Project Links: https://www.digikey.com/en/maker/projects/introduction-to-rtos-solution-to-part-10-deadlock-and-starvation/872c6a057901432e84594d79fcb2cc5d Related Articles: https://www.digikey.com/en/maker/videos/shawn-hymel/getting-started-with-stm32-and-nucleo-part-3-how-to-run-multiple-threads-with-cmsis-rtos-interface Learn more: Maker.io - https://www.digikey.com/en/maker Digi-Key’s Blog – TheCircuit https://www.digikey.com/en/blog Connect with Digi-Key on Facebook https://www.facebook.com/digikey.electronics/ And follow us on Twitter https://twitter.com/digikey