| From 604626b6f21cffbf0af7740755b25476d4a5e638 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 12 Jan 2021 11:24:04 +0100 |
| Subject: kthread: Extract KTHREAD_IS_PER_CPU |
| |
| From: Peter Zijlstra <peterz@infradead.org> |
| |
| [ Upstream commit ac687e6e8c26181a33270efd1a2e2241377924b0 ] |
| |
| There is a need to distinguish geniune per-cpu kthreads from kthreads |
| that happen to have a single CPU affinity. |
| |
| Geniune per-cpu kthreads are kthreads that are CPU affine for |
| correctness, these will obviously have PF_KTHREAD set, but must also |
| have PF_NO_SETAFFINITY set, lest userspace modify their affinity and |
| ruins things. |
| |
| However, these two things are not sufficient, PF_NO_SETAFFINITY is |
| also set on other tasks that have their affinities controlled through |
| other means, like for instance workqueues. |
| |
| Therefore another bit is needed; it turns out kthread_create_per_cpu() |
| already has such a bit: KTHREAD_IS_PER_CPU, which is used to make |
| kthread_park()/kthread_unpark() work correctly. |
| |
| Expose this flag and remove the implicit setting of it from |
| kthread_create_on_cpu(); the io_uring usage of it seems dubious at |
| best. |
| |
| Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> |
| Reviewed-by: Valentin Schneider <valentin.schneider@arm.com> |
| Tested-by: Valentin Schneider <valentin.schneider@arm.com> |
| Link: https://lkml.kernel.org/r/20210121103506.557620262@infradead.org |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| include/linux/kthread.h | 3 +++ |
| kernel/kthread.c | 27 ++++++++++++++++++++++++++- |
| kernel/smpboot.c | 1 + |
| 3 files changed, 30 insertions(+), 1 deletion(-) |
| |
| diff --git a/include/linux/kthread.h b/include/linux/kthread.h |
| index 4e26609c77d41..eb305353f20fa 100644 |
| --- a/include/linux/kthread.h |
| +++ b/include/linux/kthread.h |
| @@ -31,6 +31,9 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), |
| unsigned int cpu, |
| const char *namefmt); |
| |
| +void kthread_set_per_cpu(struct task_struct *k, int cpu); |
| +bool kthread_is_per_cpu(struct task_struct *k); |
| + |
| /** |
| * kthread_run - create and wake a thread. |
| * @threadfn: the function to run until signal_pending(current). |
| diff --git a/kernel/kthread.c b/kernel/kthread.c |
| index bd58765d75e76..fd6f9322312aa 100644 |
| --- a/kernel/kthread.c |
| +++ b/kernel/kthread.c |
| @@ -433,11 +433,36 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), |
| return p; |
| kthread_bind(p, cpu); |
| /* CPU hotplug need to bind once again when unparking the thread. */ |
| - set_bit(KTHREAD_IS_PER_CPU, &to_kthread(p)->flags); |
| to_kthread(p)->cpu = cpu; |
| return p; |
| } |
| |
| +void kthread_set_per_cpu(struct task_struct *k, int cpu) |
| +{ |
| + struct kthread *kthread = to_kthread(k); |
| + if (!kthread) |
| + return; |
| + |
| + WARN_ON_ONCE(!(k->flags & PF_NO_SETAFFINITY)); |
| + |
| + if (cpu < 0) { |
| + clear_bit(KTHREAD_IS_PER_CPU, &kthread->flags); |
| + return; |
| + } |
| + |
| + kthread->cpu = cpu; |
| + set_bit(KTHREAD_IS_PER_CPU, &kthread->flags); |
| +} |
| + |
| +bool kthread_is_per_cpu(struct task_struct *k) |
| +{ |
| + struct kthread *kthread = to_kthread(k); |
| + if (!kthread) |
| + return false; |
| + |
| + return test_bit(KTHREAD_IS_PER_CPU, &kthread->flags); |
| +} |
| + |
| /** |
| * kthread_unpark - unpark a thread created by kthread_create(). |
| * @k: thread created by kthread_create(). |
| diff --git a/kernel/smpboot.c b/kernel/smpboot.c |
| index 5043e7433f4b1..eeb7f8e9cce37 100644 |
| --- a/kernel/smpboot.c |
| +++ b/kernel/smpboot.c |
| @@ -187,6 +187,7 @@ __smpboot_create_thread(struct smp_hotplug_thread *ht, unsigned int cpu) |
| kfree(td); |
| return PTR_ERR(tsk); |
| } |
| + kthread_set_per_cpu(tsk, cpu); |
| /* |
| * Park the thread so that it could start right on the CPU |
| * when it is available. |
| -- |
| 2.27.0 |
| |