Introduction to RTOS Part 7 - Semaphore | Digi-Key Electronics

Introduction to RTOS Part 7 - Semaphore | Digi-Key Electronics

Understanding Semaphores and Mutexes

Introduction to Semaphores

  • The lecture begins by comparing a mutex to a key at a coffee shop, used for locking and unlocking shared resources, specifically restrooms.
  • A semaphore is introduced as a mechanism that can count beyond one, allowing multiple threads access to shared resources, akin to having several restrooms with a bucket of keys.

Limitations of Semaphore Analogy

  • While semaphores allow multiple threads into critical sections, this is rarely needed; they are better suited for signaling between threads.
  • A semaphore can hold a positive count value. For example, if set to three, it allows up to three tasks simultaneous access to the critical section.

Semaphore Functionality

  • When Task A checks the semaphore (value > 0), it decrements the value and enters the critical section. This atomic operation prevents interruptions from other tasks.
  • As more tasks (B and C) check and decrement the semaphore, it reaches zero when three tasks are in the critical section. Any additional task will block until another task exits.

Managing Access with Semaphores

  • Upon completing their work in the critical section, tasks must call "semaphore give" to increment the semaphore value back up.
  • This process illustrates how semaphores manage access but raises questions about protecting individual resources from concurrent thread access.

Practical Use Cases for Semaphores

  • Semaphores are often utilized in producer-consumer designs where producers add data and consumers remove it from shared resources like buffers or linked lists.
  • Producers signal availability by calling "semaphore give," which increments the semaphore's value while limiting buffer size through maximum values.

Consumer Tasks Interaction

  • Consumers must call "semaphore take" before accessing shared resources; if the semaphore is above zero, they can read and remove values from the buffer.
  • If all consumer tasks follow this protocol correctly, they can operate concurrently until reaching zero on the semaphore which blocks further consumption.

Complexity of Using Semaphores

  • The discussion highlights that semaphores may introduce unnecessary complexity compared to simpler queue implementations for managing resource access.

Differences Between Mutexes and Semaphores

  • Mutexes imply ownership—only one task can hold them at any time—while semaphores do not imply ownership; they signal readiness between different tasks.

Understanding Semaphores and Mutexes in Real-Time Operating Systems

Priority Inheritance and Semaphore Basics

  • Priority Inheritance: Semaphores can automatically raise the priority of tasks holding mutex locks to prevent higher-priority tasks from being blocked, addressing the issue of priority inversion.
  • Binary Semaphores vs. Mutexes: A binary semaphore, which counts to one, is not the same as a mutex. While they may seem similar at first glance, their functionalities differ significantly.
  • Usage in Interrupt Service Routines: Binary semaphores are preferred over mutexes in interrupt service routines to avoid blocking these critical sections for resource availability.
  • POSIX Semaphore Terminology: Different operating systems have unique terminologies for semaphore operations; for instance, POSIX uses "post" and "wait." It's essential to consult documentation for clarity.

Implementing Binary Semaphores

  • Using Binary Semaphores in Setup Functions: Instead of using a mutex hackily, a binary semaphore initialized to zero can effectively manage task parameters during setup functions.
  • Blocking Behavior with Semaphores: The xSemaphoreTake function blocks the setup function until parameters are read, demonstrating how semaphores can streamline task management.

Counting Semaphores and Task Management

  • Counting Semaphore Demo Setup: A counting semaphore with a maximum limit equal to the number of tasks (five in this case) is created. Each task copies data into a local message struct before incrementing the semaphore.
  • Task Execution Flow: Each task prints its copied struct contents after incrementing the semaphore and then deletes itself. This showcases efficient memory management within FreeRTOS.
  • Finalizing Task Execution: The setup function retrieves all five counts from the semaphore through a loop, ensuring that all tasks have completed their operations before returning control back to an infinite loop.

Challenges with Shared Resources

  • Serial Port Output Overlap Issue: Without protection mechanisms like mutexes around shared resources (e.g., serial port), outputs may overlap due to concurrent access by multiple tasks.
  • Circular Buffer Challenge Introduction: A new program involves five producer tasks writing values into a circular buffer while two consumer tasks read from it. The challenge lies in protecting this buffer using semaphores and mutexes effectively.

Implementation Details for Circular Buffers

  • Producer/Consumer Model Explanation: Producers write their task numbers three times into the buffer while consumers print out any available data. Proper synchronization is crucial here to avoid race conditions.
Video description

A semaphore is a signaling mechanism used to synchronise two or more threads. Similar to a mutex, it can be used to protect shared resources. In this video, we show you how to use semaphores with FreeRTOS on an ESP32 to pass data between tasks. The starting code for the challenge can be found here: https://github.com/ShawnHymel/introduction-to-rtos/blob/main/07-semaphore/esp32-freertos-07-challenge-counting-semaphore/esp32-freertos-07-challenge-counting-semaphore.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-7-freertos-semaphore-example/51aa8660524c4daba38cba7c2f5baba7 Code for this video series (including demonstrations, challenges, and solutions) can be found here: https://github.com/ShawnHymel/introduction-to-rtos A semaphore is similar to a mutex in that it is a locking mechanism used to tell tasks to wait if some resource is not available for use. However, semaphores are more than a simple lock: they can count to more than 1 and can therefore allow multiple threads to enter a critical section of code. In practice, however, we often do not want to let multiple threads manipulate shared data, and we would still need to protect that data (or shared resource) with something like a mutex. So, we use semaphores as a signaling mechanism to tell other threads when it is safe to access a resource or read new data. A buffer or linked list can be written to by a number of “producer” threads. Each time one of these producer threads adds data to this resource, it increments a semaphore, which is just a counting variable that can be accessed atomically. When a “consumer” thread wishes to read data from the resource, it decrements the semaphore count. If the semaphore is 0, that means no new data is available, so consumer threads must wait (e.g. enter the blocked state). Semaphores work similarly to mutex, but are generally used in different circumstances. We provide examples of these use cases in the video as well as issue a challenge to use semaphores on your own. 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-7-freertos-semaphore-example/51aa8660524c4daba38cba7c2f5baba7 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