Real-Time Operating System Synchronization Mechanisms and Task Management

Posted by Anonymous and classified in Electronics

Written on in English with a size of 307.62 KB

Semaphore Fundamentals in RTOS

A semaphore is a signaling mechanism used to manage access to shared resources in multitasking systems like Real-Time Operating Systems (RTOS). It ensures that only one task or a limited number of tasks can access a critical resource at a time, preventing issues like race conditions, data corruption, deadlocks, and inconsistent behavior.

Synchronization Role

When multiple tasks try to access a common resource, semaphores help synchronize their operations by:

  • Making a task wait if the resource is busy.
  • Allowing access when the resource becomes free.
  • Ensuring the safe and consistent operation of the system.

Working Mechanism of Semaphores

A semaphore uses an internal counter:

  • When a task takes (acquires) the semaphore, the counter is decremented.
  • When a task gives (releases) the semaphore, the counter is incremented.
  • If the counter is zero, any task that tries to take it must wait (block) until the counter is greater than zero again.

Key Actions

  • Acquisition of a semaphore: Access to the resource is allowed.
  • Release of a semaphore: The resource is made available for other tasks.

Types of Semaphores

1. Binary Semaphore

Definition: A semaphore that can have only two values — 0 (locked) or 1 (unlocked).

Usage:

  • Used when only one task at a time should access a resource.
  • Typically used for mutual exclusion or simple signaling between tasks or between an interrupt and a task.

Example:

A sensor data buffer shared between tasks. Task A takes the semaphore (sets it to 0), accesses the buffer, then releases it (sets to 1).

2. Counting Semaphore

Definition: A semaphore with a counter that can have a value greater than 1.

Usage:

  • Controls multiple instances of a resource.
  • The counter value represents the number of available resources.

Example:

A system with five printers. The counting semaphore is initialized to 5. Every time a task wants to use a printer, it decrements the semaphore by 1. After printing, it increments the semaphore by 1.

3. Mutex (Mutual Exclusion Semaphore)

Definition: A special type of binary semaphore that provides mutual exclusion but includes ownership information.

Features:

  • Only the task that has acquired (locked) the mutex can release (unlock) it.
  • Helps in preventing priority inversion through special protocols.

Usage:

Protecting critical sections of code that must not be executed by more than one task at the same time.

Example:

Shared access to a configuration file: only the task that locks the mutex can unlock it after completing changes.

Important Synchronization Considerations

  • Priority Inversion Problem: Happens when a low-priority task holds a semaphore needed by a high-priority task. Mutexes often provide mechanisms like priority inheritance to address this.
  • Deadlocks: Can occur if tasks get stuck waiting for semaphores held by each other.
  • Starvation: A task might wait forever if higher-priority tasks keep taking the semaphore.

Exceptions and Interrupts

Exceptions

An exception is any unexpected event that disrupts the normal flow of execution in a processor. It forces the processor to temporarily stop executing the current instructions and start executing special code to handle the event.

Types of Exceptions

  • Synchronous exceptions: Caused by internal errors (e.g., division by zero, illegal memory access).
  • Asynchronous exceptions: Caused by external events (e.g., hardware faults).

Interrupts

An interrupt is a type of asynchronous exception generated by external hardware devices to gain immediate attention of the CPU.

It allows the CPU to temporarily pause the current execution, handle the event, and then resume the interrupted task.

Examples: Timer interrupt, serial communication interrupt, ADC interrupt.

Applications of Exceptions and Interrupts

Exceptions and interrupts are widely used in three major areas:

Internal Error and Special Condition Management

Handling events like division by zero, memory access violations, and illegal instructions. This helps in maintaining system stability and safety.

A46AI+AI5BECTtp5NFjeVUfAEXAEnLT9GXAEHAFHII8QcNLOo8HyrjoCjoAj4KTtz4Aj4Ag4AnmEwP8HQwUUPNEa1F0AAAAASUVORK5CYII=

PSvNuLQCRa9AicCLXqrShaUVGH8rUCLw8bdnpRmXVqDoFSgReNFLVbqwtALjbwX+P9xkEGkhI5w9AAAAAElFTkSuQmCC

Message Queues for Inter-Task Communication

A message queue is a buffer-like object through which tasks and Interrupt Service Routines (ISRs) communicate and synchronize by sending and receiving messages. It acts like a pipeline, temporarily holding messages from a sender until the receiver is ready, thus decoupling their execution timing.

Queue Initialization and Structure

When a message queue is created, the kernel assigns:

  • A unique ID, Queue Control Block (QCB), and queue name.
  • Memory buffers, queue length, and maximum message length.
  • Task-waiting lists: one for receivers (waiting if the queue is empty) and one for senders (waiting if the queue is full).

The kernel allocates the required memory. The queue consists of several elements (messages), with the head (first) and tail (last) indicating positions. Empty elements are also counted towards the total queue length.

Message Queue States

Message queues follow a Finite State Machine (FSM):

Empty State

When created, the queue is empty. If a task tries to receive from an empty queue, it blocks and waits.

Not Empty State

When a message is sent and no task is waiting, the queue moves to the "not empty" state. Messages accumulate until the queue is full.

Full State

When the queue reaches its maximum length. Further sending:

  • Fails with an error (in some kernels).
  • Or the sending task blocks in the sending task-waiting list (in other kernels).

Note: If a message is delivered directly to a blocked task, the queue may remain empty despite the send operation.

Core Characteristics of an RTOS

Reliability

An embedded system must operate reliably, sometimes for long periods without human intervention. Different applications require different levels of reliability (e.g., calculators versus telecom switches). System reliability depends on hardware, Board Support Package (BSP), RTOS, and the application working together, not just the RTOS alone.

Predictability (Determinism)

Real-time embedded systems must meet strict timing requirements. A predictable (deterministic) RTOS ensures system calls complete within known time frames. Developers use benchmarks to validate RTOS determinism with minimal response time variance.

Performance

Systems must be fast enough to meet timing deadlines. Performance depends on both hardware (CPU speed, MIPS) and software efficiency.

Throughput measures how much output a system generates relative to input or data transfer rates (bits per second).

Compactness

Size and cost constraints require embedded systems (e.g., cell phones) to be small and memory-efficient. The RTOS must have a small memory footprint with low static and dynamic memory consumption.

Scalability

An RTOS must scale up or down based on application needs by adding or removing modular components. Good scalability allows the same RTOS to be used across different projects (e.g., phones and base stations), saving time and cost.

RTOS Task States

Ready State

A task is ready to run but cannot because a higher priority task is currently running. When first created, a task enters the ready state and competes for CPU time. Tasks can only move from ready to running, based on priority. Kernels may maintain a separate ready list for each priority level or a combined list.

Running State

Only one task runs at a time on a single-processor system. When running, the processor loads the task’s context (registers, stack).

A running task can:

  • Be preempted by a higher-priority task (moving back to ready).
  • Move to the blocked state by:
    • Requesting an unavailable resource.
    • Waiting for an event.
    • Requesting a delay.

Blocked State

A task waits because a requested condition is not yet met. Blocking prevents CPU starvation by allowing lower-priority tasks to run.

A task unblocks when:

  • A semaphore is released.
  • A message arrives in a queue.
  • A time delay expires.

After unblocking:

  • If it is the highest priority task, it moves directly to running, preempting the current task.
  • Otherwise, it moves to the ready state.

Related entries: