• No results found

2.6 Convention and Practical Program Analysis

3.1.5 Blocking and Synchronization

Often tasks share common resources, beside the processor time, which must be protected from mutual access. DM and EDF are scheduling policies oblivious of resource constraints. In the following we discuss blocking and synchronization of concurrent resource accesses and we briefly sketch prominent resource constrained scheduling policies.

In fully preemptive scheduling without resource constraints, higher priority tasks are never blocked by lower priority ones. In non-preemptive scheduling, the blocking time

Chapter 3. Context 31

imposed on a task τi is simply the maximum computation time of all lower priority tasks. Bi= max

j∈lp(i)Cj (3.22)

In deferred preemptive scheduling, blocking depends on the type of strategy. For time-triggered floating regions, blocking time Bi is known by definition. For fixed region deferred preemption, though, it depends on the longest execution paths between preemption points. which will be subject to detailed discussion in Chapter 5. Once known, response time analysis can be extended by blocking time Bi such that:

Ri = Ci+ Bi+ X j∈hp(i)  Ri+ Jj Tj  Cj (3.23) Semaphores

Resources shared between tasks are typically protected by means of mutual exclusion to ensure consistency of data structures by synchronization of tasks. A code region executed under mutual exclusion is called a critical section. A common synchronization primitive is the semaphore. A task enters a critical section protected by a semaphore Si by invoking an operation wait(Si), which either grants access — thus making the task the owner of the resource — or blocks the requesting task. When a task leaves its critical section, it invokes an operation signal(Si) to free the resource and which effectively unblocks all tasks waiting for that resource such that they can attempt again to enter their respective critical sections. In Figure 3.1, this is denoted by the state wait. A semaphore can allow for multiple tasks to access the resource. A semaphore that grants access to just a single task at a time is called a mutex.

Scheduling policies with limited preemption enforce implicit critical sections with mutual exclusion with the processor time as the shared resource. In non-preemptive scheduling, the critical section encompasses the entire task. In deferred preemption scheduling, tasks are partitioned into disjoint critical sections.

Priority Inversion Problem

Synchronization globally overrides task priorities to ensure semantic correctness. If the scheduling policy is unaware of resource constraints, the priority inversion problem can occur, as illustrated in Figure 3.7. In the figure, task priorities are static and decreasing from τ1 on and only tasks τ1, τ3 share a protected resource. When τ1 is released at time step 3, τ3, which has already entered its critical section, is preempted according to the given priorities. When τ1 attempts to enter its critical section at time step 4, it is blocked by τ3, which in turn resumes execution. At time step 5, the priority inversion problem manifests: Although τ1 is the highest priority active task, τ2 is scheduled to run because τ1 is blocked and τ3 has lower priority than τ2. Thus, τ1 is not only delayed by the blocking due the critical section of τ3 but also by the computation time of the unrelated

Chapter 3. Context 32

Figure 3.7: Example of a priority inversion problem

task of intermediate priority τ2. Hence, for the time interval [4, 10], priorities of τ1, τ3 are effectively inverting.

The priority inversion problem is critical since tasks of a nominally high priority are blocked for an unbounded amount of time. In the following we briefly sketch common strategies to counter the priority inversion problem by implementing explicit resource-awareness into the scheduling decisions. We restrict the discussion to static priorities.

Priority Inheritance Protocol

The Priority Inheritance Protocol (PIP) [43] directly addresses the priority inversion problem by temporarily assigning (inheriting) the highest priority of all tasks waiting for a resource to the task currently holding it. Figure 3.8 illustrates the scheduling scenario

Figure 3.8: Example of the priority inheritance protocol

from Figure 3.7 under priority inheritance. When τ1 attempts to enter its critical section in time step 4, τ3 inherits the priority of τ1, thus preventing τ3 to be preempted by τ2 in the following.

Generally, under PIP a task τi has a nominal priority pr(i) and an active priority pr?(i). If pr?(i) is the highest priority among all active tasks, τ

i is run. If τi attempts to enter a critical section and is blocked by a task τj, active priorities are assigned such that pr?(j) = pr?(i). If τi leaves a critical section, pr?(i) is set to the maximal active priority among all tasks still blocked by τi (nested critical sections), or to pr(i) otherwise.

PIP prevents priority inversion and thus bounds the amount of blocking but still suffers from two problems:

• chained blocking: If a high priority task τi is bound to successively enter n critical sections protected by n different semaphores, in the worst-case it is blocked by n

Chapter 3. Context 33

critical sections of lower priority tasks. Thus blocking time, while being bounded, is potentially still significant.

• deadlock : If two tasks both enter critical sections and, in the following, attempt to acquire the semaphore held by the other additionally, a cyclic wait situation can occur.

Priority Ceiling Protocol

The Priority Ceiling Protocol (PCP) [43] is an extension to PIP and prevents priority inversion, chained blocking and deadlocks. The intuition is that a task is only allowed to enter a critical section if it can be guaranteed that it will not be blocked before leaving.

Let Sidenote a semaphore, then the (static) priority ceiling value C(Si) is the maximal priority among all tasks that potentially acquire Si during execution. Further, let S∗ dynamically denote the semaphore with the highest ceiling priority among all semaphores (at a specific point in time) and nominal respectively active priorities (cf. PIP).

The task τi of highest priority pr?(i) is run. Task τi is allowed to enter a critical section only if pr?(i) > C(S∗). Otherwise it is blocked and pr?(j) = pr?(i) for the task τj holding S∗. If τi leaves a critical section, pr?(i) is set to the maximal active priority among all tasks still blocked by τi (nested critical sections), or to pr(i) otherwise.

PCP bounds the amount of blocking inflicted to a task τito the longest critical section among all lower priority tasks τj that share semaphores Sk with τi and C(Sk) > pr(i).

Related documents