提交 b2250b44 编写于 作者: Y Yihao Wu 提交者: Caspar Zhang

alinux: sched: Fix per-cgroup idle accounting deadlock

fix #29692432

seqcount assumes that writers are already exclusive, so it saves extra
locking. However this critial section protected by idle_seqcount can
be entered twice if an interrupt tries to wake up a task on this cpu.

Once race caused by interrupt is avoided, writers are exclusive. So
seqlock is unnecessary, and local_irq_save + seqcount is enough.

Fixes: 61e58859 ("alinux: sched: Introduce per-cgroup idle accounting")
Signed-off-by: NYihao Wu <wuyihao@linux.alibaba.com>
Acked-by: NShanpei Chen <shanpeic@linux.alibaba.com>
上级 e0b245f8
...@@ -599,14 +599,18 @@ void cgroup_idle_start(struct sched_entity *se) ...@@ -599,14 +599,18 @@ void cgroup_idle_start(struct sched_entity *se)
clock = __rq_clock_broken(se->cfs_rq->rq); clock = __rq_clock_broken(se->cfs_rq->rq);
local_irq_save(flags);
write_seqcount_begin(&se->idle_seqcount); write_seqcount_begin(&se->idle_seqcount);
__schedstat_set(se->cg_idle_start, clock); __schedstat_set(se->cg_idle_start, clock);
write_seqcount_end(&se->idle_seqcount); write_seqcount_end(&se->idle_seqcount);
spin_lock_irqsave(&se->iowait_lock, flags); spin_lock(&se->iowait_lock);
if (schedstat_val(se->cg_nr_iowait)) if (schedstat_val(se->cg_nr_iowait))
__schedstat_set(se->cg_iowait_start, clock); __schedstat_set(se->cg_iowait_start, clock);
spin_unlock_irqrestore(&se->iowait_lock, flags); spin_unlock(&se->iowait_lock);
local_irq_restore(flags);
} }
void cgroup_idle_end(struct sched_entity *se) void cgroup_idle_end(struct sched_entity *se)
...@@ -620,19 +624,23 @@ void cgroup_idle_end(struct sched_entity *se) ...@@ -620,19 +624,23 @@ void cgroup_idle_end(struct sched_entity *se)
clock = __rq_clock_broken(se->cfs_rq->rq); clock = __rq_clock_broken(se->cfs_rq->rq);
local_irq_save(flags);
write_seqcount_begin(&se->idle_seqcount); write_seqcount_begin(&se->idle_seqcount);
idle_start = schedstat_val(se->cg_idle_start); idle_start = schedstat_val(se->cg_idle_start);
__schedstat_add(se->cg_idle_sum, clock - idle_start); __schedstat_add(se->cg_idle_sum, clock - idle_start);
__schedstat_set(se->cg_idle_start, 0); __schedstat_set(se->cg_idle_start, 0);
write_seqcount_end(&se->idle_seqcount); write_seqcount_end(&se->idle_seqcount);
spin_lock_irqsave(&se->iowait_lock, flags); spin_lock(&se->iowait_lock);
if (schedstat_val(se->cg_nr_iowait)) { if (schedstat_val(se->cg_nr_iowait)) {
iowait_start = schedstat_val(se->cg_iowait_start); iowait_start = schedstat_val(se->cg_iowait_start);
__schedstat_add(se->cg_iowait_sum, clock - iowait_start); __schedstat_add(se->cg_iowait_sum, clock - iowait_start);
__schedstat_set(se->cg_iowait_start, 0); __schedstat_set(se->cg_iowait_start, 0);
} }
spin_unlock_irqrestore(&se->iowait_lock, flags); spin_unlock(&se->iowait_lock);
local_irq_restore(flags);
} }
void cpuacct_cpuset_changed(struct cgroup *cgrp, struct cpumask *deleted, void cpuacct_cpuset_changed(struct cgroup *cgrp, struct cpumask *deleted,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册