posix-cpu-timers: clear TICK_DEP_BIT_POSIX_TIMER on clone
Subsystems (4)
Benjamin Segall
reviewerPATCH v2 1/1 posix-cpu-timers: clear TICK_DEP_BIT_POSIX_TIMER on clone
When we clone a new thread, we do not inherit its posix_cputimers, and clear them with posix_cputimers_init. However, this does not clear the tick dependency it creates in tsk->tick_dep_mask, and the handler does not reach the code to clear the dependency if there were no timers to begin with.
Thus if a thread has a cputimer running before cloneing/forking, that hierarchy will prevent nohz_full unless they create a cputimer of their own.
Process-wide timers do not have this problem because fork does not copy signal_struct as a baseline, it creates one from scratch.
--- include/linux/tick.h | 8 ++++++++ kernel/fork.c | 2 ++ 2 files changed, 10 insertions(+)
include/linux/tick.h +8 -0
@@ -249,16 +249,23 @@ static inline void tick_dep_set_task(struct task_struct *tsk, enum tick_dep_bits bit) {if (tick_nohz_full_enabled ())tick_nohz_dep_set_task (tsk, bit); } +static inline void tick_dep_clear_task (struct task_struct *tsk,enum tick_dep_bits bit) {if (tick_nohz_full_enabled ())tick_nohz_dep_clear_task (tsk, bit); } + +static inline void tick_dep_init_task (struct task_struct *tsk) +{ +atomic_set (&tsk->tick_dep_mask,0 ); +} +static inline void tick_dep_set_signal (struct task_struct *tsk,enum tick_dep_bits bit) {if (tick_nohz_full_enabled ())tick_nohz_dep_set_signal (tsk, bit);
@@ -288,10 +295,11 @@ static inline void tick_dep_set_cpu(int cpu, enum tick_dep_bits bit) { }static inline void tick_dep_clear_cpu (int cpu,enum tick_dep_bits bit) { }static inline void tick_dep_set_task (struct task_struct *tsk,enum tick_dep_bits bit) { }static inline void tick_dep_clear_task (struct task_struct *tsk,enum tick_dep_bits bit) { } +static inline void tick_dep_init_task (struct task_struct *tsk) { }static inline void tick_dep_set_signal (struct task_struct *tsk,enum tick_dep_bits bit) { }static inline void tick_dep_clear_signal (struct signal_struct *signal,enum tick_dep_bits bit) { }
kernel/fork.c +2 -0
@@ -103,10 +103,11 @@#include <linux/user_events.h> #include <linux/iommu.h> #include <linux/rseq.h> #include <uapi/linux/pidfd.h> #include <linux/pidfs.h> +#include <linux/tick.h> #include <asm/pgalloc.h> #include <linux/uaccess.h> #include <asm/mmu_context.h> #include <asm/cacheflush.h>
@@ -2290,10 +2291,11 @@ __latent_entropy struct task_struct *copy_process(task_io_accounting_init (&p->ioac);acct_clear_integrals (p);posix_cputimers_init (&p->posix_cputimers); +tick_dep_init_task (p); p->io_context =NULL ;audit_set_context (p,NULL );cgroup_fork (p);if (args->kthread) {
Signature · 1 line
2.47.0.rc1.288.g06298d1525-goog
Quoted 1 line · Benjamin Segall
When we clone a new thread, we do not inherit its
posix_cputimers, and
We? We neither clone something nor can we inherit anything from the kernel. Please do not impersonate code and use passive voice.
Quoted 1 line
clear them with
posix_cputimers_init. However, this does not clear the
Please denote functions with brackets, i.e. fun() so its obvious.
Quoted 10 lines
tick dependency it creates in
tsk->tick_dep_mask, and the handler does not reach the code to clear the dependency if there were no timers to begin with.Thus if a thread has a cputimer running before cloneing/forking, that hierarchy will prevent
nohz_fullunless they create a cputimer of their own.Process-wide timers do not have this problem because fork does not copy
signal_structas a baseline, it creates one from scratch.
And the solution to this is described where in the change log?
Thanks,
tglx