diff options
| -rw-r--r-- | include/linux/sched.h | 1 | ||||
| -rw-r--r-- | kernel/fork.c | 2 | ||||
| -rw-r--r-- | kernel/sched.c | 53 | ||||
| -rw-r--r-- | kernel/workqueue_sched.h | 16 |
4 files changed, 69 insertions, 3 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index f118809c953f..edc3dd168d87 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -1696,6 +1696,7 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t * | |||
| 1696 | #define PF_EXITING 0x00000004 /* getting shut down */ | 1696 | #define PF_EXITING 0x00000004 /* getting shut down */ |
| 1697 | #define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */ | 1697 | #define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */ |
| 1698 | #define PF_VCPU 0x00000010 /* I'm a virtual CPU */ | 1698 | #define PF_VCPU 0x00000010 /* I'm a virtual CPU */ |
| 1699 | #define PF_WQ_WORKER 0x00000020 /* I'm a workqueue worker */ | ||
| 1699 | #define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */ | 1700 | #define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */ |
| 1700 | #define PF_MCE_PROCESS 0x00000080 /* process policy on mce errors */ | 1701 | #define PF_MCE_PROCESS 0x00000080 /* process policy on mce errors */ |
| 1701 | #define PF_SUPERPRIV 0x00000100 /* used super-user privileges */ | 1702 | #define PF_SUPERPRIV 0x00000100 /* used super-user privileges */ |
diff --git a/kernel/fork.c b/kernel/fork.c index b6cce14ba047..a82a65cef741 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -907,7 +907,7 @@ static void copy_flags(unsigned long clone_flags, struct task_struct *p) | |||
| 907 | { | 907 | { |
| 908 | unsigned long new_flags = p->flags; | 908 | unsigned long new_flags = p->flags; |
| 909 | 909 | ||
| 910 | new_flags &= ~PF_SUPERPRIV; | 910 | new_flags &= ~(PF_SUPERPRIV | PF_WQ_WORKER); |
| 911 | new_flags |= PF_FORKNOEXEC; | 911 | new_flags |= PF_FORKNOEXEC; |
| 912 | new_flags |= PF_STARTING; | 912 | new_flags |= PF_STARTING; |
| 913 | p->flags = new_flags; | 913 | p->flags = new_flags; |
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 | ||
diff --git a/kernel/workqueue_sched.h b/kernel/workqueue_sched.h new file mode 100644 index 000000000000..af040babb742 --- /dev/null +++ b/kernel/workqueue_sched.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | /* | ||
| 2 | * kernel/workqueue_sched.h | ||
| 3 | * | ||
| 4 | * Scheduler hooks for concurrency managed workqueue. Only to be | ||
| 5 | * included from sched.c and workqueue.c. | ||
| 6 | */ | ||
| 7 | static inline void wq_worker_waking_up(struct task_struct *task, | ||
| 8 | unsigned int cpu) | ||
| 9 | { | ||
| 10 | } | ||
| 11 | |||
| 12 | static inline struct task_struct *wq_worker_sleeping(struct task_struct *task, | ||
| 13 | unsigned int cpu) | ||
| 14 | { | ||
| 15 | return NULL; | ||
| 16 | } | ||
