Re: [RFC 4/8] Improve the tracking of active utilisation

From: Peter Zijlstra
Date: Thu Jan 14 2016 - 12:16:27 EST


On Thu, Jan 14, 2016 at 04:24:49PM +0100, Luca Abeni wrote:
> @@ -65,6 +67,62 @@ static void clear_running_bw(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
> }
> }
>
> +static void task_go_inactive(struct task_struct *p)
> +{
> + struct sched_dl_entity *dl_se = &p->dl;
> + struct hrtimer *timer = &dl_se->inactive_timer;
> + struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
> + struct rq *rq = rq_of_dl_rq(dl_rq);
> + ktime_t now, act;
> + s64 delta;
> + u64 zerolag_time;
> +
> + WARN_ON(dl_se->dl_runtime == 0);
> +
> + /* If the inactive timer is already armed, return immediately */
> + if (hrtimer_active(&dl_se->inactive_timer))
> + return;
> +
> +
> + /*
> + * We want the timer to fire at the "0 lag time", but considering
> + * that it is actually coming from rq->clock and not from
> + * hrtimer's time base reading.
> + */
> + zerolag_time = dl_se->deadline - div64_long((dl_se->runtime * dl_se->dl_period), dl_se->dl_runtime);

whitespace damage

> @@ -530,9 +587,20 @@ static void update_dl_entity(struct sched_dl_entity *dl_se,
> */
> if (dl_se->dl_new) {
> setup_new_dl_entity(dl_se, pi_se);
> + add_running_bw(dl_se, dl_rq);
> return;
> }
>
> + /* If the "inactive timer" is still active, stop it adn leave
> + * the active utilisation unchanged.
> + * If it is running, increase the active utilisation
> + */
> + if (hrtimer_active(&dl_se->inactive_timer)) {
> + hrtimer_try_to_cancel(&dl_se->inactive_timer);

what if cancel fails?

> + } else {
> + add_running_bw(dl_se, dl_rq);
> + }
> +
> if (dl_time_before(dl_se->deadline, rq_clock(rq)) ||
> dl_entity_overflow(dl_se, pi_se, rq_clock(rq))) {
> dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;

> @@ -1248,8 +1370,6 @@ static void task_fork_dl(struct task_struct *p)
> static void task_dead_dl(struct task_struct *p)
> {
> struct dl_bw *dl_b = dl_bw_of(task_cpu(p));
> - struct dl_rq *dl_rq = dl_rq_of_se(&p->dl);
> - struct rq *rq = rq_of_dl_rq(dl_rq);
>
> /*
> * Since we are TASK_DEAD we won't slip out of the domain!
> @@ -1258,10 +1378,6 @@ static void task_dead_dl(struct task_struct *p)
> /* XXX we should retain the bw until 0-lag */
> dl_b->total_bw -= p->dl.dl_bw;
> raw_spin_unlock_irq(&dl_b->lock);
> -
> - if (task_on_rq_queued(p)) {
> - clear_running_bw(&p->dl, &rq->dl);
> - }

what happens if the timer is still active here? then we get the timer
storage freed while enqueued?

> @@ -1742,12 +1858,12 @@ static void switched_from_dl(struct rq *rq, struct task_struct *p)
> * SCHED_DEADLINE until the deadline passes, the timer will reset the
> * task.
> */
> - if (!start_dl_timer(p))
> + if (task_on_rq_queued(p))
> + task_go_inactive(p);
> + if (!hrtimer_active(&p->dl.inactive_timer))
> __dl_clear_params(p);
> -
> - if (task_on_rq_queued(p)) {
> + else if (!hrtimer_callback_running(&p->dl.inactive_timer))
> clear_running_bw(&p->dl, &rq->dl);
> - }
>
> /*
> * Since this might be the only -deadline task on the rq,

idem, what if the task dies while !dl but with timer pending?