Message ID | 20210205140650.464297049@linuxfoundation.org |
---|---|
State | Superseded |
Headers | show |
Series | None | expand |
Hi! > 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. AFAIK this should not be in 4.19/5.10 as it does not fix anything w/o 5ba2ffba13a1e. Nobody calls kthread_is_per_cpu() in those kernels. Best regards, Pavel -- http://www.livejournal.com/~pavelmachek
diff --git a/include/linux/kthread.h b/include/linux/kthread.h index c1961761311db..72308c38e06c4 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -32,6 +32,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 2eed853ab9cc5..81abfac351272 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -460,11 +460,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 c230c2dd48e19..84c16654d8598 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.