diff options
Diffstat (limited to 'debian/patches-rt/posix-timers-thread-posix-cpu-timers-on-rt.patch')
-rw-r--r-- | debian/patches-rt/posix-timers-thread-posix-cpu-timers-on-rt.patch | 174 |
1 files changed, 108 insertions, 66 deletions
diff --git a/debian/patches-rt/posix-timers-thread-posix-cpu-timers-on-rt.patch b/debian/patches-rt/posix-timers-thread-posix-cpu-timers-on-rt.patch index 84581ac96..e7abb5e6a 100644 --- a/debian/patches-rt/posix-timers-thread-posix-cpu-timers-on-rt.patch +++ b/debian/patches-rt/posix-timers-thread-posix-cpu-timers-on-rt.patch @@ -1,7 +1,7 @@ From: John Stultz <johnstul@us.ibm.com> Date: Fri, 3 Jul 2009 08:29:58 -0500 Subject: posix-timers: Thread posix-cpu-timers on -rt -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.2/older/patches-5.2.17-rt9.tar.xz +Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.4/older/patches-5.4.3-rt1.tar.xz posix-cpu-timer code takes non -rt safe locks in hard irq context. Move it to a thread. @@ -12,59 +12,39 @@ Signed-off-by: John Stultz <johnstul@us.ibm.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- - include/linux/sched.h | 3 - init/init_task.c | 7 + - kernel/fork.c | 3 - kernel/time/posix-cpu-timers.c | 154 ++++++++++++++++++++++++++++++++++++++++- - 4 files changed, 164 insertions(+), 3 deletions(-) + include/linux/posix-timers.h | 10 ++ + kernel/time/posix-cpu-timers.c | 175 ++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 174 insertions(+), 11 deletions(-) ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -826,6 +826,9 @@ struct task_struct { - #ifdef CONFIG_POSIX_TIMERS - struct task_cputime cputime_expires; - struct list_head cpu_timers[3]; -+#ifdef CONFIG_PREEMPT_RT_BASE +--- a/include/linux/posix-timers.h ++++ b/include/linux/posix-timers.h +@@ -123,6 +123,9 @@ struct posix_cputimers { + struct posix_cputimer_base bases[CPUCLOCK_MAX]; + unsigned int timers_active; + unsigned int expiry_active; ++#ifdef CONFIG_PREEMPT_RT + struct task_struct *posix_timer_list; +#endif - #endif - - /* Process credentials: */ ---- a/init/init_task.c -+++ b/init/init_task.c -@@ -51,6 +51,12 @@ static struct sighand_struct init_sighan - .signalfd_wqh = __WAIT_QUEUE_HEAD_INITIALIZER(init_sighand.signalfd_wqh), }; -+#if defined(CONFIG_POSIX_TIMERS) && defined(CONFIG_PREEMPT_RT_BASE) -+# define INIT_TIMER_LIST .posix_timer_list = NULL, + static inline void posix_cputimers_init(struct posix_cputimers *pct) +@@ -152,9 +155,16 @@ static inline void posix_cputimers_rt_wa + INIT_CPU_TIMERBASE(b[2]), \ + } + ++#ifdef CONFIG_PREEMPT_RT ++# define INIT_TIMER_LIST .posix_timer_list = NULL, +#else +# define INIT_TIMER_LIST +#endif + - /* - * Set up the first task table, touch at your own risk!. Base=0, - * limit=0x1fffff (=2MB) -@@ -120,6 +126,7 @@ struct task_struct init_task - INIT_CPU_TIMERS(init_task) - .pi_lock = __RAW_SPIN_LOCK_UNLOCKED(init_task.pi_lock), - .timer_slack_ns = 50000, /* 50 usec default slack */ -+ INIT_TIMER_LIST - .thread_pid = &init_struct_pid, - .thread_group = LIST_HEAD_INIT(init_task.thread_group), - .thread_node = LIST_HEAD_INIT(init_signals.thread_head), ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -1647,6 +1647,9 @@ static void rt_mutex_init_task(struct ta - */ - static void posix_cpu_timers_init(struct task_struct *tsk) - { -+#ifdef CONFIG_PREEMPT_RT_BASE -+ tsk->posix_timer_list = NULL; -+#endif - tsk->cputime_expires.prof_exp = 0; - tsk->cputime_expires.virt_exp = 0; - tsk->cputime_expires.sched_exp = 0; + #define INIT_CPU_TIMERS(s) \ + .posix_cputimers = { \ + .bases = INIT_CPU_TIMERBASES(s.posix_cputimers.bases), \ ++ INIT_TIMER_LIST \ + }, + #else + struct posix_cputimers { }; --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -3,8 +3,10 @@ @@ -86,28 +66,88 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de> #include "posix-timers.h" -@@ -1147,15 +1150,13 @@ void cpu_timers_grab_expiry_lock(struct +@@ -27,6 +30,9 @@ void posix_cputimers_group_init(struct p + pct->bases[CPUCLOCK_PROF].nextevt = cpu_limit * NSEC_PER_SEC; + pct->timers_active = true; + } ++#ifdef CONFIG_PREEMPT_RT ++ pct->posix_timer_list = NULL; ++#endif + } + + /* +@@ -804,7 +810,8 @@ static inline void check_dl_overrun(stru + } + } + +-static bool check_rlimit(u64 time, u64 limit, int signo, bool rt, bool hard) ++static bool check_rlimit(struct task_struct *tsk, u64 time, u64 limit, ++ int signo, bool rt, bool hard) + { + if (time < limit) + return false; +@@ -812,9 +819,9 @@ static bool check_rlimit(u64 time, u64 l + if (print_fatal_signals) { + pr_info("%s Watchdog Timeout (%s): %s[%d]\n", + rt ? "RT" : "CPU", hard ? "hard" : "soft", +- current->comm, task_pid_nr(current)); ++ tsk->comm, task_pid_nr(tsk)); + } +- __group_send_sig_info(signo, SEND_SIG_PRIV, current); ++ __group_send_sig_info(signo, SEND_SIG_PRIV, tsk); + return true; + } + +@@ -850,11 +857,11 @@ static void check_thread_timers(struct t + + /* At the hard limit, send SIGKILL. No further action. */ + if (hard != RLIM_INFINITY && +- check_rlimit(rttime, hard, SIGKILL, true, true)) ++ check_rlimit(tsk, rttime, hard, SIGKILL, true, true)) + return; + + /* At the soft limit, send a SIGXCPU every second */ +- if (check_rlimit(rttime, soft, SIGXCPU, true, false)) { ++ if (check_rlimit(tsk, rttime, soft, SIGXCPU, true, false)) { + soft += USEC_PER_SEC; + tsk->signal->rlim[RLIMIT_RTTIME].rlim_cur = soft; + } +@@ -949,11 +956,11 @@ static void check_process_timers(struct + + /* At the hard limit, send SIGKILL. No further action. */ + if (hard != RLIM_INFINITY && +- check_rlimit(ptime, hardns, SIGKILL, false, true)) ++ check_rlimit(tsk, ptime, hardns, SIGKILL, false, true)) + return; + + /* At the soft limit, send a SIGXCPU every second */ +- if (check_rlimit(ptime, softns, SIGXCPU, false, false)) { ++ if (check_rlimit(tsk, ptime, softns, SIGXCPU, false, false)) { + sig->rlim[RLIMIT_CPU].rlim_cur = soft + 1; + softns += NSEC_PER_SEC; + } +@@ -1110,15 +1117,12 @@ static inline bool fastpath_timer_check( * already updated our counts. We need to check if any timers fire now. * Interrupts are disabled. */ --void run_posix_cpu_timers(struct task_struct *tsk) +-void run_posix_cpu_timers(void) +static void __run_posix_cpu_timers(struct task_struct *tsk) { - LIST_HEAD(firing); +- struct task_struct *tsk = current; struct k_itimer *timer, *next; unsigned long flags; - spinlock_t *expiry_lock; + LIST_HEAD(firing); - lockdep_assert_irqs_disabled(); - /* * The fast path checks that there are no expired thread or thread * group timers. If that's so, just return. -@@ -1215,6 +1216,153 @@ void run_posix_cpu_timers(struct task_st - spin_unlock(expiry_lock); +@@ -1171,6 +1175,155 @@ void run_posix_cpu_timers(void) + } } -+#ifdef CONFIG_PREEMPT_RT_BASE ++#ifdef CONFIG_PREEMPT_RT +#include <linux/kthread.h> +#include <linux/cpu.h> +DEFINE_PER_CPU(struct task_struct *, posix_timer_task); @@ -134,13 +174,13 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de> + /* Process task list */ + while (1) { + /* save next */ -+ next = tsk->posix_timer_list; ++ next = tsk->posix_cputimers.posix_timer_list; + + /* run the task timers, clear its ptr and + * unreference it + */ + __run_posix_cpu_timers(tsk); -+ tsk->posix_timer_list = NULL; ++ tsk->posix_cputimers.posix_timer_list = NULL; + put_task_struct(tsk); + + /* check if this is the last on the list */ @@ -156,18 +196,19 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de> + if (unlikely(tsk->exit_state)) + return 0; + -+ if (!task_cputime_zero(&tsk->cputime_expires)) -+ return 1; ++ if (!expiry_cache_is_inactive(&tsk->posix_cputimers)) ++ return 1; + -+ if (!task_cputime_zero(&tsk->signal->cputime_expires)) -+ return 1; ++ if (!expiry_cache_is_inactive(&tsk->signal->posix_cputimers)) ++ return 1; + + return 0; +} + -+void run_posix_cpu_timers(struct task_struct *tsk) ++void run_posix_cpu_timers(void) +{ + unsigned int cpu = smp_processor_id(); ++ struct task_struct *tsk = current; + struct task_struct *tasklist; + + BUG_ON(!irqs_disabled()); @@ -179,16 +220,16 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de> + tasklist = per_cpu(posix_timer_tasklist, cpu); + + /* check to see if we're already queued */ -+ if (!tsk->posix_timer_list && __fastpath_timer_check(tsk)) { ++ if (!tsk->posix_cputimers.posix_timer_list && __fastpath_timer_check(tsk)) { + get_task_struct(tsk); + if (tasklist) { -+ tsk->posix_timer_list = tasklist; ++ tsk->posix_cputimers.posix_timer_list = tasklist; + } else { + /* + * The list is terminated by a self-pointing + * task_struct + */ -+ tsk->posix_timer_list = tsk; ++ tsk->posix_cputimers.posix_timer_list = tsk; + } + per_cpu(posix_timer_tasklist, cpu) = tsk; + @@ -246,13 +287,14 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de> + return 0; +} +early_initcall(posix_cpu_thread_init); -+#else /* CONFIG_PREEMPT_RT_BASE */ -+void run_posix_cpu_timers(struct task_struct *tsk) ++ ++#else /* CONFIG_PREEMPT_RT */ ++void run_posix_cpu_timers(void) +{ + lockdep_assert_irqs_disabled(); -+ __run_posix_cpu_timers(tsk); ++ __run_posix_cpu_timers(current); +} -+#endif /* CONFIG_PREEMPT_RT_BASE */ ++#endif /* CONFIG_PREEMPT_RT */ + /* * Set one of the process-wide special case CPU timers or RLIMIT_CPU. |