diff options
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 96eafd5f345f..edd5a54b95da 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -77,6 +77,7 @@ | |||
77 | #include <asm/irq_regs.h> | 77 | #include <asm/irq_regs.h> |
78 | 78 | ||
79 | #include "sched_cpupri.h" | 79 | #include "sched_cpupri.h" |
80 | #include "workqueue_sched.h" | ||
80 | 81 | ||
81 | #define CREATE_TRACE_POINTS | 82 | #define CREATE_TRACE_POINTS |
82 | #include <trace/events/sched.h> | 83 | #include <trace/events/sched.h> |
@@ -2306,6 +2307,9 @@ static inline void ttwu_post_activation(struct task_struct *p, struct rq *rq, | |||
2306 | rq->idle_stamp = 0; | 2307 | rq->idle_stamp = 0; |
2307 | } | 2308 | } |
2308 | #endif | 2309 | #endif |
2310 | /* if a worker is waking up, notify workqueue */ | ||
2311 | if ((p->flags & PF_WQ_WORKER) && success) | ||
2312 | wq_worker_waking_up(p, cpu_of(rq)); | ||
2309 | } | 2313 | } |
2310 | 2314 | ||
2311 | /** | 2315 | /** |
@@ -2414,6 +2418,37 @@ out: | |||
2414 | } | 2418 | } |
2415 | 2419 | ||
2416 | /** | 2420 | /** |
2421 | * try_to_wake_up_local - try to wake up a local task with rq lock held | ||
2422 | * @p: the thread to be awakened | ||
2423 | * | ||
2424 | * Put @p on the run-queue if it's not alredy there. The caller must | ||
2425 | * ensure that this_rq() is locked, @p is bound to this_rq() and not | ||
2426 | * the current task. this_rq() stays locked over invocation. | ||
2427 | */ | ||
2428 | static void try_to_wake_up_local(struct task_struct *p) | ||
2429 | { | ||
2430 | struct rq *rq = task_rq(p); | ||
2431 | bool success = false; | ||
2432 | |||
2433 | BUG_ON(rq != this_rq()); | ||
2434 | BUG_ON(p == current); | ||
2435 | lockdep_assert_held(&rq->lock); | ||
2436 | |||
2437 | if (!(p->state & TASK_NORMAL)) | ||
2438 | return; | ||
2439 | |||
2440 | if (!p->se.on_rq) { | ||
2441 | if (likely(!task_running(rq, p))) { | ||
2442 | schedstat_inc(rq, ttwu_count); | ||
2443 | schedstat_inc(rq, ttwu_local); | ||
2444 | } | ||
2445 | ttwu_activate(p, rq, false, false, true, ENQUEUE_WAKEUP); | ||
2446 | success = true; | ||
2447 | } | ||
2448 | ttwu_post_activation(p, rq, 0, success); | ||
2449 | } | ||
2450 | |||
2451 | /** | ||
2417 | * wake_up_process - Wake up a specific process | 2452 | * wake_up_process - Wake up a specific process |
2418 | * @p: The process to be woken up. | 2453 | * @p: The process to be woken up. |
2419 | * | 2454 | * |
@@ -3618,10 +3653,24 @@ need_resched_nonpreemptible: | |||
3618 | clear_tsk_need_resched(prev); | 3653 | clear_tsk_need_resched(prev); |
3619 | 3654 | ||
3620 | if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { | 3655 | if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { |
3621 | if (unlikely(signal_pending_state(prev->state, prev))) | 3656 | if (unlikely(signal_pending_state(prev->state, prev))) { |
3622 | prev->state = TASK_RUNNING; | 3657 | prev->state = TASK_RUNNING; |
3623 | else | 3658 | } else { |
3659 | /* | ||
3660 | * If a worker is going to sleep, notify and | ||
3661 | * ask workqueue whether it wants to wake up a | ||
3662 | * task to maintain concurrency. If so, wake | ||
3663 | * up the task. | ||
3664 | */ | ||
3665 | if (prev->flags & PF_WQ_WORKER) { | ||
3666 | struct task_struct *to_wakeup; | ||
3667 | |||
3668 | to_wakeup = wq_worker_sleeping(prev, cpu); | ||
3669 | if (to_wakeup) | ||
3670 | try_to_wake_up_local(to_wakeup); | ||
3671 | } | ||
3624 | deactivate_task(rq, prev, DEQUEUE_SLEEP); | 3672 | deactivate_task(rq, prev, DEQUEUE_SLEEP); |
3673 | } | ||
3625 | switch_count = &prev->nvcsw; | 3674 | switch_count = &prev->nvcsw; |
3626 | } | 3675 | } |
3627 | 3676 | ||