|
@@ -704,13 +704,84 @@ static bool dl_entity_overflow(struct sched_dl_entity *dl_se,
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * When a -deadline entity is queued back on the runqueue, its runtime and
|
|
|
- * deadline might need updating.
|
|
|
+ * Revised wakeup rule [1]: For self-suspending tasks, rather then
|
|
|
+ * re-initializing task's runtime and deadline, the revised wakeup
|
|
|
+ * rule adjusts the task's runtime to avoid the task to overrun its
|
|
|
+ * density.
|
|
|
*
|
|
|
- * The policy here is that we update the deadline of the entity only if:
|
|
|
- * - the current deadline is in the past,
|
|
|
- * - using the remaining runtime with the current deadline would make
|
|
|
- * the entity exceed its bandwidth.
|
|
|
+ * Reasoning: a task may overrun the density if:
|
|
|
+ * runtime / (deadline - t) > dl_runtime / dl_deadline
|
|
|
+ *
|
|
|
+ * Therefore, runtime can be adjusted to:
|
|
|
+ * runtime = (dl_runtime / dl_deadline) * (deadline - t)
|
|
|
+ *
|
|
|
+ * In such way that runtime will be equal to the maximum density
|
|
|
+ * the task can use without breaking any rule.
|
|
|
+ *
|
|
|
+ * [1] Luca Abeni, Giuseppe Lipari, and Juri Lelli. 2015. Constant
|
|
|
+ * bandwidth server revisited. SIGBED Rev. 11, 4 (January 2015), 19-24.
|
|
|
+ */
|
|
|
+static void
|
|
|
+update_dl_revised_wakeup(struct sched_dl_entity *dl_se, struct rq *rq)
|
|
|
+{
|
|
|
+ u64 laxity = dl_se->deadline - rq_clock(rq);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If the task has deadline < period, and the deadline is in the past,
|
|
|
+ * it should already be throttled before this check.
|
|
|
+ *
|
|
|
+ * See update_dl_entity() comments for further details.
|
|
|
+ */
|
|
|
+ WARN_ON(dl_time_before(dl_se->deadline, rq_clock(rq)));
|
|
|
+
|
|
|
+ dl_se->runtime = (dl_se->dl_density * laxity) >> BW_SHIFT;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Regarding the deadline, a task with implicit deadline has a relative
|
|
|
+ * deadline == relative period. A task with constrained deadline has a
|
|
|
+ * relative deadline <= relative period.
|
|
|
+ *
|
|
|
+ * We support constrained deadline tasks. However, there are some restrictions
|
|
|
+ * applied only for tasks which do not have an implicit deadline. See
|
|
|
+ * update_dl_entity() to know more about such restrictions.
|
|
|
+ *
|
|
|
+ * The dl_is_implicit() returns true if the task has an implicit deadline.
|
|
|
+ */
|
|
|
+static inline bool dl_is_implicit(struct sched_dl_entity *dl_se)
|
|
|
+{
|
|
|
+ return dl_se->dl_deadline == dl_se->dl_period;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * When a deadline entity is placed in the runqueue, its runtime and deadline
|
|
|
+ * might need to be updated. This is done by a CBS wake up rule. There are two
|
|
|
+ * different rules: 1) the original CBS; and 2) the Revisited CBS.
|
|
|
+ *
|
|
|
+ * When the task is starting a new period, the Original CBS is used. In this
|
|
|
+ * case, the runtime is replenished and a new absolute deadline is set.
|
|
|
+ *
|
|
|
+ * When a task is queued before the begin of the next period, using the
|
|
|
+ * remaining runtime and deadline could make the entity to overflow, see
|
|
|
+ * dl_entity_overflow() to find more about runtime overflow. When such case
|
|
|
+ * is detected, the runtime and deadline need to be updated.
|
|
|
+ *
|
|
|
+ * If the task has an implicit deadline, i.e., deadline == period, the Original
|
|
|
+ * CBS is applied. the runtime is replenished and a new absolute deadline is
|
|
|
+ * set, as in the previous cases.
|
|
|
+ *
|
|
|
+ * However, the Original CBS does not work properly for tasks with
|
|
|
+ * deadline < period, which are said to have a constrained deadline. By
|
|
|
+ * applying the Original CBS, a constrained deadline task would be able to run
|
|
|
+ * runtime/deadline in a period. With deadline < period, the task would
|
|
|
+ * overrun the runtime/period allowed bandwidth, breaking the admission test.
|
|
|
+ *
|
|
|
+ * In order to prevent this misbehave, the Revisited CBS is used for
|
|
|
+ * constrained deadline tasks when a runtime overflow is detected. In the
|
|
|
+ * Revisited CBS, rather than replenishing & setting a new absolute deadline,
|
|
|
+ * the remaining runtime of the task is reduced to avoid runtime overflow.
|
|
|
+ * Please refer to the comments update_dl_revised_wakeup() function to find
|
|
|
+ * more about the Revised CBS rule.
|
|
|
*/
|
|
|
static void update_dl_entity(struct sched_dl_entity *dl_se,
|
|
|
struct sched_dl_entity *pi_se)
|
|
@@ -720,6 +791,14 @@ static void update_dl_entity(struct sched_dl_entity *dl_se,
|
|
|
|
|
|
if (dl_time_before(dl_se->deadline, rq_clock(rq)) ||
|
|
|
dl_entity_overflow(dl_se, pi_se, rq_clock(rq))) {
|
|
|
+
|
|
|
+ if (unlikely(!dl_is_implicit(dl_se) &&
|
|
|
+ !dl_time_before(dl_se->deadline, rq_clock(rq)) &&
|
|
|
+ !dl_se->dl_boosted)){
|
|
|
+ update_dl_revised_wakeup(dl_se, rq);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
|
|
|
dl_se->runtime = pi_se->dl_runtime;
|
|
|
}
|
|
@@ -1274,11 +1353,6 @@ static void dequeue_dl_entity(struct sched_dl_entity *dl_se)
|
|
|
__dequeue_dl_entity(dl_se);
|
|
|
}
|
|
|
|
|
|
-static inline bool dl_is_constrained(struct sched_dl_entity *dl_se)
|
|
|
-{
|
|
|
- return dl_se->dl_deadline < dl_se->dl_period;
|
|
|
-}
|
|
|
-
|
|
|
static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags)
|
|
|
{
|
|
|
struct task_struct *pi_task = rt_mutex_get_top_task(p);
|
|
@@ -1310,7 +1384,7 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags)
|
|
|
* If that is the case, the task will be throttled and
|
|
|
* the replenishment timer will be set to the next period.
|
|
|
*/
|
|
|
- if (!p->dl.dl_throttled && dl_is_constrained(&p->dl))
|
|
|
+ if (!p->dl.dl_throttled && !dl_is_implicit(&p->dl))
|
|
|
dl_check_constrained_dl(&p->dl);
|
|
|
|
|
|
if (p->on_rq == TASK_ON_RQ_MIGRATING || flags & ENQUEUE_RESTORE) {
|