diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-21 13:40:02 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-21 13:40:02 -0500 |
| commit | e2defd02717ebc54ae2f4862271a3093665b426a (patch) | |
| tree | bb724dc1041b72ac9a241fb9d00aae995fea6236 /kernel | |
| parent | b5aeca54d0212515d820e5555115e2fc7847a68b (diff) | |
| parent | 2636ed5f8d15ff9395731593537b4b3fdf2af24d (diff) | |
Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull scheduler fixes from Ingo Molnar:
"Thiscontains misc fixes: preempt_schedule_common() and io_schedule()
recursion fixes, sched/dl fixes, a completion_done() revert, two
sched/rt fixes and a comment update patch"
* 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
sched/rt: Avoid obvious configuration fail
sched/autogroup: Fix failure to set cpu.rt_runtime_us
sched/dl: Do update_rq_clock() in yield_task_dl()
sched: Prevent recursion in io_schedule()
sched/completion: Serialize completion_done() with complete()
sched: Fix preempt_schedule_common() triggering tracing recursion
sched/dl: Prevent enqueue of a sleeping task in dl_task_timer()
sched: Make dl_task_time() use task_rq_lock()
sched: Clarify ordering between task_rq_lock() and move_queued_task()
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/sched/auto_group.c | 6 | ||||
| -rw-r--r-- | kernel/sched/completion.c | 19 | ||||
| -rw-r--r-- | kernel/sched/core.c | 113 | ||||
| -rw-r--r-- | kernel/sched/deadline.c | 33 | ||||
| -rw-r--r-- | kernel/sched/sched.h | 76 |
5 files changed, 148 insertions, 99 deletions
diff --git a/kernel/sched/auto_group.c b/kernel/sched/auto_group.c index 8a2e230fb86a..eae160dd669d 100644 --- a/kernel/sched/auto_group.c +++ b/kernel/sched/auto_group.c | |||
| @@ -87,8 +87,7 @@ static inline struct autogroup *autogroup_create(void) | |||
| 87 | * so we don't have to move tasks around upon policy change, | 87 | * so we don't have to move tasks around upon policy change, |
| 88 | * or flail around trying to allocate bandwidth on the fly. | 88 | * or flail around trying to allocate bandwidth on the fly. |
| 89 | * A bandwidth exception in __sched_setscheduler() allows | 89 | * A bandwidth exception in __sched_setscheduler() allows |
| 90 | * the policy change to proceed. Thereafter, task_group() | 90 | * the policy change to proceed. |
| 91 | * returns &root_task_group, so zero bandwidth is required. | ||
| 92 | */ | 91 | */ |
| 93 | free_rt_sched_group(tg); | 92 | free_rt_sched_group(tg); |
| 94 | tg->rt_se = root_task_group.rt_se; | 93 | tg->rt_se = root_task_group.rt_se; |
| @@ -115,9 +114,6 @@ bool task_wants_autogroup(struct task_struct *p, struct task_group *tg) | |||
| 115 | if (tg != &root_task_group) | 114 | if (tg != &root_task_group) |
| 116 | return false; | 115 | return false; |
| 117 | 116 | ||
| 118 | if (p->sched_class != &fair_sched_class) | ||
| 119 | return false; | ||
| 120 | |||
| 121 | /* | 117 | /* |
| 122 | * We can only assume the task group can't go away on us if | 118 | * We can only assume the task group can't go away on us if |
| 123 | * autogroup_move_group() can see us on ->thread_group list. | 119 | * autogroup_move_group() can see us on ->thread_group list. |
diff --git a/kernel/sched/completion.c b/kernel/sched/completion.c index 7052d3fd4e7b..8d0f35debf35 100644 --- a/kernel/sched/completion.c +++ b/kernel/sched/completion.c | |||
| @@ -274,7 +274,7 @@ bool try_wait_for_completion(struct completion *x) | |||
| 274 | * first without taking the lock so we can | 274 | * first without taking the lock so we can |
| 275 | * return early in the blocking case. | 275 | * return early in the blocking case. |
| 276 | */ | 276 | */ |
| 277 | if (!ACCESS_ONCE(x->done)) | 277 | if (!READ_ONCE(x->done)) |
| 278 | return 0; | 278 | return 0; |
| 279 | 279 | ||
| 280 | spin_lock_irqsave(&x->wait.lock, flags); | 280 | spin_lock_irqsave(&x->wait.lock, flags); |
| @@ -297,6 +297,21 @@ EXPORT_SYMBOL(try_wait_for_completion); | |||
| 297 | */ | 297 | */ |
| 298 | bool completion_done(struct completion *x) | 298 | bool completion_done(struct completion *x) |
| 299 | { | 299 | { |
| 300 | return !!ACCESS_ONCE(x->done); | 300 | if (!READ_ONCE(x->done)) |
| 301 | return false; | ||
| 302 | |||
| 303 | /* | ||
| 304 | * If ->done, we need to wait for complete() to release ->wait.lock | ||
| 305 | * otherwise we can end up freeing the completion before complete() | ||
| 306 | * is done referencing it. | ||
| 307 | * | ||
| 308 | * The RMB pairs with complete()'s RELEASE of ->wait.lock and orders | ||
| 309 | * the loads of ->done and ->wait.lock such that we cannot observe | ||
| 310 | * the lock before complete() acquires it while observing the ->done | ||
| 311 | * after it's acquired the lock. | ||
| 312 | */ | ||
| 313 | smp_rmb(); | ||
| 314 | spin_unlock_wait(&x->wait.lock); | ||
| 315 | return true; | ||
| 301 | } | 316 | } |
| 302 | EXPORT_SYMBOL(completion_done); | 317 | EXPORT_SYMBOL(completion_done); |
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 13049aac05a6..f0f831e8a345 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
| @@ -307,66 +307,6 @@ __read_mostly int scheduler_running; | |||
| 307 | int sysctl_sched_rt_runtime = 950000; | 307 | int sysctl_sched_rt_runtime = 950000; |
| 308 | 308 | ||
| 309 | /* | 309 | /* |
| 310 | * __task_rq_lock - lock the rq @p resides on. | ||
| 311 | */ | ||
| 312 | static inline struct rq *__task_rq_lock(struct task_struct *p) | ||
| 313 | __acquires(rq->lock) | ||
| 314 | { | ||
| 315 | struct rq *rq; | ||
| 316 | |||
| 317 | lockdep_assert_held(&p->pi_lock); | ||
| 318 | |||
| 319 | for (;;) { | ||
| 320 | rq = task_rq(p); | ||
| 321 | raw_spin_lock(&rq->lock); | ||
| 322 | if (likely(rq == task_rq(p) && !task_on_rq_migrating(p))) | ||
| 323 | return rq; | ||
| 324 | raw_spin_unlock(&rq->lock); | ||
| 325 | |||
| 326 | while (unlikely(task_on_rq_migrating(p))) | ||
| 327 | cpu_relax(); | ||
| 328 | } | ||
| 329 | } | ||
| 330 | |||
| 331 | /* | ||
| 332 | * task_rq_lock - lock p->pi_lock and lock the rq @p resides on. | ||
| 333 | */ | ||
| 334 | static struct rq *task_rq_lock(struct task_struct *p, unsigned long *flags) | ||
| 335 | __acquires(p->pi_lock) | ||
| 336 | __acquires(rq->lock) | ||
| 337 | { | ||
| 338 | struct rq *rq; | ||
| 339 | |||
| 340 | for (;;) { | ||
| 341 | raw_spin_lock_irqsave(&p->pi_lock, *flags); | ||
| 342 | rq = task_rq(p); | ||
| 343 | raw_spin_lock(&rq->lock); | ||
| 344 | if (likely(rq == task_rq(p) && !task_on_rq_migrating(p))) | ||
| 345 | return rq; | ||
| 346 | raw_spin_unlock(&rq->lock); | ||
| 347 | raw_spin_unlock_irqrestore(&p->pi_lock, *flags); | ||
| 348 | |||
| 349 | while (unlikely(task_on_rq_migrating(p))) | ||
| 350 | cpu_relax(); | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | static void __task_rq_unlock(struct rq *rq) | ||
| 355 | __releases(rq->lock) | ||
| 356 | { | ||
| 357 | raw_spin_unlock(&rq->lock); | ||
| 358 | } | ||
| 359 | |||
| 360 | static inline void | ||
| 361 | task_rq_unlock(struct rq *rq, struct task_struct *p, unsigned long *flags) | ||
| 362 | __releases(rq->lock) | ||
| 363 | __releases(p->pi_lock) | ||
| 364 | { | ||
| 365 | raw_spin_unlock(&rq->lock); | ||
| 366 | raw_spin_unlock_irqrestore(&p->pi_lock, *flags); | ||
| 367 | } | ||
| 368 | |||
| 369 | /* | ||
| 370 | * this_rq_lock - lock this runqueue and disable interrupts. | 310 | * this_rq_lock - lock this runqueue and disable interrupts. |
| 371 | */ | 311 | */ |
| 372 | static struct rq *this_rq_lock(void) | 312 | static struct rq *this_rq_lock(void) |
| @@ -2899,7 +2839,7 @@ void __sched schedule_preempt_disabled(void) | |||
| 2899 | preempt_disable(); | 2839 | preempt_disable(); |
| 2900 | } | 2840 | } |
| 2901 | 2841 | ||
| 2902 | static void preempt_schedule_common(void) | 2842 | static void __sched notrace preempt_schedule_common(void) |
| 2903 | { | 2843 | { |
| 2904 | do { | 2844 | do { |
| 2905 | __preempt_count_add(PREEMPT_ACTIVE); | 2845 | __preempt_count_add(PREEMPT_ACTIVE); |
| @@ -4418,36 +4358,29 @@ EXPORT_SYMBOL_GPL(yield_to); | |||
| 4418 | * This task is about to go to sleep on IO. Increment rq->nr_iowait so | 4358 | * This task is about to go to sleep on IO. Increment rq->nr_iowait so |
| 4419 | * that process accounting knows that this is a task in IO wait state. | 4359 | * that process accounting knows that this is a task in IO wait state. |
| 4420 | */ | 4360 | */ |
| 4421 | void __sched io_schedule(void) | ||
| 4422 | { | ||
| 4423 | struct rq *rq = raw_rq(); | ||
| 4424 | |||
| 4425 | delayacct_blkio_start(); | ||
| 4426 | atomic_inc(&rq->nr_iowait); | ||
| 4427 | blk_flush_plug(current); | ||
| 4428 | current->in_iowait = 1; | ||
| 4429 | schedule(); | ||
| 4430 | current->in_iowait = 0; | ||
| 4431 | atomic_dec(&rq->nr_iowait); | ||
| 4432 | delayacct_blkio_end(); | ||
| 4433 | } | ||
| 4434 | EXPORT_SYMBOL(io_schedule); | ||
| 4435 | |||
| 4436 | long __sched io_schedule_timeout(long timeout) | 4361 | long __sched io_schedule_timeout(long timeout) |
| 4437 | { | 4362 | { |
| 4438 | struct rq *rq = raw_rq(); | 4363 | int old_iowait = current->in_iowait; |
| 4364 | struct rq *rq; | ||
| 4439 | long ret; | 4365 | long ret; |
| 4440 | 4366 | ||
| 4367 | current->in_iowait = 1; | ||
| 4368 | if (old_iowait) | ||
| 4369 | blk_schedule_flush_plug(current); | ||
| 4370 | else | ||
| 4371 | blk_flush_plug(current); | ||
| 4372 | |||
| 4441 | delayacct_blkio_start(); | 4373 | delayacct_blkio_start(); |
| 4374 | rq = raw_rq(); | ||
| 4442 | atomic_inc(&rq->nr_iowait); | 4375 | atomic_inc(&rq->nr_iowait); |
| 4443 | blk_flush_plug(current); | ||
| 4444 | current->in_iowait = 1; | ||
| 4445 | ret = schedule_timeout(timeout); | 4376 | ret = schedule_timeout(timeout); |
| 4446 | current->in_iowait = 0; | 4377 | current->in_iowait = old_iowait; |
| 4447 | atomic_dec(&rq->nr_iowait); | 4378 | atomic_dec(&rq->nr_iowait); |
| 4448 | delayacct_blkio_end(); | 4379 | delayacct_blkio_end(); |
| 4380 | |||
| 4449 | return ret; | 4381 | return ret; |
| 4450 | } | 4382 | } |
| 4383 | EXPORT_SYMBOL(io_schedule_timeout); | ||
| 4451 | 4384 | ||
| 4452 | /** | 4385 | /** |
| 4453 | * sys_sched_get_priority_max - return maximum RT priority. | 4386 | * sys_sched_get_priority_max - return maximum RT priority. |
| @@ -7642,6 +7575,12 @@ static inline int tg_has_rt_tasks(struct task_group *tg) | |||
| 7642 | { | 7575 | { |
