Skip to content

Exercises related to dependent tasks

NPP and Unnecessary Blocking

Exercice 1

NPP is simple to implement and it avoids deadlock. But it introduces unnecessary blocking, meaning that a task with higher priority that does not require access to the critical section can be blocked. Illustrate a scenario with 3 tasks where NPP introduces unnecessary blocking.

Maximum Blocking Time Using PIP

Exercice 2

Consider a system with 3 tasks \(\tau_1\), \(\tau_2\), and \(\tau_3\), with decreasing priority. The tasks share 3 resources \(A\), \(B\), and \(C\). Assume that the system is implementing PIP and compute the maximum blocking time \(B_i\) for each task, knowing that the longest access duration of task \(\tau_i\) on resource \(A\), \(B\), and \(C\) is defined as:

Task \(A\) \(B\) \(C\)
\(\tau_{1}\) 3 0 3
\(\tau_{2}\) 3 4 0
\(\tau_{3}\) 4 3 6

Hint: recall the following points:

  • Using PIP, a task \(\tau_i\) can be blocked at most once for each lower priority task, i.e. at most for one critical section that can be owned by each lower priority task.
  • A task \(\tau_i\) can be blocked

    • through direct blocking: a lower priority task that shares a critical section with \(\tau_i\) owns the critical section.
    • through push-through blocking: a medium-priority task is blocked by a low priority task that has inherited a higher priority. It can happen only if a critical section is accessed both by a task with lower priority and by a task with higher priority.

Situation for Maximum Blocking Time Using PIP

Exercice 3

For the task set described in the previous exercise, illustrate the situation in which task \(\tau_2\) experiences its maximum blocking time, when using RM and PIP.

Hint: you must first compute the maximum blocking time of task \(\tau_2\) and reproduce the corresponding situation

Blocking Time Upper Bound using PIP

Exercice 3

The computation of the blocking time upper bound under PIP can be computed with the following algorithm:

Input: Durations \(\delta_{i,k}\) for each task \(\tau_{i}\) and each mutex \(M_{k}\)
Output: \(B_{i}\) for each task \(\tau_{i}\)

Notation: \(Ceiling(M_{k})\) is the priority ceiling of mutex \(M_{k}\).
Notation: \(P_{i}\) is the priority of task \(i\).
Notation: \(\delta_{j,k}\) is the duration of the longest critical section of task \(\tau_{i}\) guarded by mutex \(M_{k}\).

// Assumes tasks are ordered by decreasing priorities
(1)   begin
(2)    for i := 1 to n − 1 do // for each task
(3)     \(B^{l}_{i}\) := 0;
(4)     for j := i + 1 to n do // for each lower priority task
(5)      \(D_{max}\) := 0;
(6)      for k := 1 to m do // for each semaphore
(7)       if (\(Ceiling(M_{k})\)\(P_{i}\)) and (\(\delta_{j,k}\) > \(D_{max}\)) do
(8)        \(D_{max}\) := \(\delta_{j,k}\);
(9)       end
(10)     end
(11)     if (\(D_{max}\) > 0) do
(11)      \(B^{l}_{i}\) := \(B^{l}_{i}\) + \(D_{max}\);
(12)     end
(12)    end
(13)   \(B^{s}_{i}\) := 0;
(14)    for k := 1 to m do // for each semaphore
(15)     \(D_{max}\) := 0;
(16)     for j := i + 1 to n do // for each lower priority task
(17)      if (\(Ceiling(M_{k})\)\(P_{i}\)) and (\(\delta_{j,k}\) > \(D_{max}\)) do
(18)       \(D_{max}\) := \(\delta_{j,k}\);
(19)      end
(20)     end
(11)     if (\(D_{max}\) > 0) do
(21)      \(B^{s}_{i}\) := \(B^{s}_{i}\) + \(D_{max}\);
(12)     end
(22)    end
(23)    \(B_{i}\) := min(\(B^{l}_{i}\), \(B^{s}_{i}\));
(24)   end
(25)  \(B_{n}\) := 0;
(26)  end

Given four tasks \(\tau_{i}\) that share three mutexes \(M_{k}\) with durations \(\delta_{i,k}\),

Task \(\delta_{i,1}\) \(\delta_{i,2}\) \(\delta_{i,3}\)
\(\tau_{1}\) 1 2 0
\(\tau_{2}\) 0 9 3
\(\tau_{3}\) 8 7 0
\(\tau_{4}\) 6 5 4

and the corresponding priority ceiling for each mutex,

Semaphore Priority ceiling
\(M_{1}\) \(p_{1}\)
\(M_{2}\) \(p_{1}\)
\(M_{3}\) \(p_{2}\)

compute the upper bound of the blocking time \(B_{i}\) for each task \(\tau_{i}\).
Note that a value of \(0\) in the table above means that the corresponding task is not using the mutex.

Schedulability Analysis for dependent tasks

Exercice 4

Consider the following task set with their computing time, period and blocking time:

Task \(C_{i}\) \(T_{i}\) \(B_{i}\)
\(\tau_{1}\) 4 10 5
\(\tau_{2}\) 3 15 3
\(\tau_{3}\) 3 20 0

Note that the blocking time of the task with the lowest priority is 0 in all cases. Using the generalized schedulability test, validate the schedulability of this task set.

PIP Implementation in Keil RTX5: data structures

Exercice 5

For implementing the Priority Inheritance Protocol, the following changes are required in the kernel:

  • Each thread must store its nominal and active priority
  • Inheritance: Each mutex keeps track of the thread holding the mutex
  • Transitivity: Each thread keeps track of the mutex in which it is blocked

The osRtxThread_t and osRtxMutex_t data structures are defined in the “rtx_os.h” file. Examine the data structures and document how the required changes for PIP are implemented.

PIP Implementation in Keil RTX5: Mutex lock and unlock

Exercice 6

Changes in the Mutex lock for implementing PIP:

  • If Mutex is free, it becomes locked and the mutex keeps track of the thread locking the mutex.
  • If Mutex is locked, the priority of the thread locking it is changed to the priority of the task calling lock.

The osMutexAcquire/svcRtxMutexAcquire function is defined in the “rtx_mutex.c” file. Examine the code and document how the required changes for PIP are implemented.

Exercice 7

Changes in the Mutex unlock for implementing PIP:

  • If no thread is blocked on the Mutex, then simply unlock the Mutex.
  • If one or more threads are blocked on the Mutex, then the highest-priority thread is awakened and is stored as owner of the Mutex. The priority of the thread unlocking the Mutex is updated.

The osMutexRelease/svcRtxMutexRelease function is defined in the “rtx_mutex.c” file. Examine the code and document how the required changes for PIP are implemented.