· endless loop.
Both task structures are relatively simple. Run-to-completion tasks are most useful for initialization and startup. They typically run once, when the system first powers on. Endless-loop tasks do the majority of the work in the application by handling inputs and outputs. Typically, they run many times while the system is powered on.
5.5.1 Run-to-Completion Tasks
An example of a run-to-completion task is the application-level initialization task, shown in Listing 5.1. The initialization task initializes the application and creates additional services, tasks, and needed kernel objects.
Listing 5.1: Pseudo code for a run-to-completion task.
RunToCompletionTask ()
{
Initialize application
Create ‘endless loop tasks'
Create kernel objects
Delete or suspend this task
}
The application initialization task typically has a higher priority than the application tasks it creates so that its initialization work is not preempted. In the simplest case, the other tasks are one or more lower priority endless-loop tasks. The application initialization task is written so that it suspends or deletes itself after it completes its work so the newly created tasks can run.
5.5.2 Endless-Loop Tasks
As with the structure of the application initialization task, the structure of an endless loop task can also contain initialization code. The endless loop's initialization code, however, only needs to be executed when the task first runs, after which the task executes in an endless loop, as shown in Listing 5.2.
The critical part of the design of an endless-loop task is the one or more blocking calls within the body of the loop. These blocking calls can result in the blocking of this endless-loop task, allowing lower priority tasks to run.
Listing 5.2: Pseudo code for an endless-loop task.
EndlessLoopTask ()
{
Initialization code
Loop Forever
{
Body of loop
Make one or more blocking calls
}
}
5.6 Synchronization, Communication, and Concurrency
Tasks synchronize and communicate amongst themselves by using
The concept of concurrency and how an application is optimally decomposed into concurrent tasks is also discussed in more detail later in this book. For now, remember that the task object is the fundamental construct of most kernels. Tasks, along with task-management services, allow developers to design applications for concurrency to meet multiple time constraints and to address various design problems inherent to real-time embedded applications.
5.7 Points to Remember
Some points to remember include the following:
· Most real-time kernels provide task objects and task-management services that allow developers to meet the requirements of real-time applications.
· Applications can contain system tasks or user-created tasks, each of which has a name, a unique ID, a priority, a task control block (TCB), a stack, and a task routine.
· A real-time application is composed of multiple concurrent tasks that are independent threads of execution, competing on their own for processor execution time.
· Tasks can be in one of three primary states during their lifetime: ready, running, and blocked.
· Priority-based, preemptive scheduling kernels that allow multiple tasks to be assigned to the same priority use task-ready lists to help scheduled tasks run.
· Tasks can run to completion or can run in an endless loop. For tasks that run in endless loops, structure the code so that the task blocks, which allows lower priority tasks to run.
· Typical task operations that kernels provide for application development include task creation and deletion, manual task scheduling, and dynamic acquisition of task information.
Chapter 6: Semaphores
6.1 Introduction
Multiple concurrent threads of execution within an application must be able to synchronize their execution and coordinate mutually exclusive access to shared resources. To address these requirements, RTOS kernels provide a semaphore object and associated semaphore management services.
This chapter discusses the following:
· defining a semaphore,
· typical semaphore operations, and
· common semaphore use.
6.2 Defining Semaphores