linux/kernel/sched
Roman Gushchin 09dc4ab039 sched/fair: Fix tg_set_cfs_bandwidth() deadlock on rq->lock
tg_set_cfs_bandwidth() sets cfs_b->timer_active to 0 to
force the period timer restart. It's not safe, because
can lead to deadlock, described in commit 927b54fccb:
"__start_cfs_bandwidth calls hrtimer_cancel while holding rq->lock,
waiting for the hrtimer to finish. However, if sched_cfs_period_timer
runs for another loop iteration, the hrtimer can attempt to take
rq->lock, resulting in deadlock."

Three CPUs must be involved:

  CPU0               CPU1                         CPU2
  take rq->lock      period timer fired
  ...                take cfs_b lock
  ...                ...                          tg_set_cfs_bandwidth()
  throttle_cfs_rq()  release cfs_b lock           take cfs_b lock
  ...                distribute_cfs_runtime()     timer_active = 0
  take cfs_b->lock   wait for rq->lock            ...
  __start_cfs_bandwidth()
  {wait for timer callback
   break if timer_active == 1}

So, CPU0 and CPU1 are deadlocked.

Instead of resetting cfs_b->timer_active, tg_set_cfs_bandwidth can
wait for period timer callbacks (ignoring cfs_b->timer_active) and
restart the timer explicitly.

Signed-off-by: Roman Gushchin <klamm@yandex-team.ru>
Reviewed-by: Ben Segall <bsegall@google.com>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/87wqdi9g8e.wl\%klamm@yandex-team.ru
Cc: pjt@google.com
Cc: chris.j.arges@canonical.com
Cc: gregkh@linuxfoundation.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2014-06-05 11:51:34 +02:00
..
auto_group.c sched: Replace hardcoding of -20 and 19 with MIN_NICE and MAX_NICE 2014-02-22 18:15:54 +01:00
auto_group.h Revert "sched/autogroup: Fix crash on reboot when autogroup is disabled" 2012-12-11 10:23:45 +01:00
clock.c kernel: use macros from compiler.h instead of __attribute__((...)) 2014-04-07 16:36:11 -07:00
completion.c sched: Move completion code from core.c to completion.c 2013-11-06 07:49:19 +01:00
core.c sched/fair: Fix tg_set_cfs_bandwidth() deadlock on rq->lock 2014-06-05 11:51:34 +02:00
cpuacct.c cgroup: clean up cgroup_subsys names and initialization 2014-02-08 10:36:58 -05:00
cpuacct.h sched/cpuacct: Initialize root cpuacct earlier 2013-04-10 13:54:20 +02:00
cpudeadline.c sched/deadline: Replace NR_CPUS arrays 2014-05-22 10:21:28 +02:00
cpudeadline.h sched/deadline: Replace NR_CPUS arrays 2014-05-22 10:21:28 +02:00
cpupri.c sched/cpupri: Replace NR_CPUS arrays 2014-05-22 10:21:29 +02:00
cpupri.h sched/cpupri: Replace NR_CPUS arrays 2014-05-22 10:21:29 +02:00
cputime.c sched: Sanitize irq accounting madness 2014-05-07 11:51:30 +02:00
deadline.c sched/dl: Fix race in dl_task_timer() 2014-06-05 11:51:12 +02:00
debug.c Merge branch 'for-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup 2014-04-03 13:05:42 -07:00
fair.c sched/fair: Fix tg_set_cfs_bandwidth() deadlock on rq->lock 2014-06-05 11:51:34 +02:00
features.h sched/numa: Resist moving tasks towards nodes with fewer hinting faults 2013-10-09 12:40:27 +02:00
idle.c sched/idle: Add more comments to the code 2014-03-11 11:52:49 +01:00
idle_task.c sched/fair: Push down check for high priority class task into idle_balance() 2014-03-11 12:05:37 +01:00
Makefile sched/idle: Move cpu/idle.c to sched/idle.c 2014-02-11 09:58:30 +01:00
proc.c sched: Change get_rq_runnable_load() to static and inline 2013-06-27 10:07:44 +02:00
rt.c sched: Check for stop task appearance when balancing happens 2014-04-17 13:39:51 +02:00
sched.h sched/fair: Fix tg_set_cfs_bandwidth() deadlock on rq->lock 2014-06-05 11:51:34 +02:00
stats.c kernel: audit/fix non-modular users of module_init in core code 2014-04-03 16:21:07 -07:00
stats.h sched: Micro-optimize by dropping unnecessary task_rq() calls 2013-09-25 13:51:06 +02:00
stop_task.c sched: Fix hotplug task migration 2014-02-21 21:43:18 +01:00
wait.c sched: Move wait code from core.c to wait.c 2013-11-06 07:49:18 +01:00