Skip to content

Commit bba90e0

Browse files
committed
Merge tag 'core-core-2022-03-21' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull core process handling RT latency updates from Thomas Gleixner: - Reduce the amount of work to release a task stack in context switch. There is no real reason to do cgroup accounting and memory freeing in this performance sensitive context. Aside of this the invoked functions cannot be called from this preemption disabled context on PREEMPT_RT enabled kernels. Solve this by moving the accounting into do_exit() and delaying the freeing of the stack unless the vmap stack can be cached. - Provide a mechanism to delay raising signals from atomic context on PREEMPT_RT enabled kernels as sighand::lock cannot be acquired. Store the information in the task struct and raise it in the exit path. * tag 'core-core-2022-03-21' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: signal, x86: Delay calling signals in atomic on RT enabled kernels fork: Use IS_ENABLED() in account_kernel_stack() fork: Only cache the VMAP stack in finish_task_switch() fork: Move task stack accounting to do_exit() fork: Move memcg_charge_kernel_stack() into CONFIG_VMAP_STACK fork: Don't assign the stack pointer in dup_task_struct() fork, IA64: Provide alloc_thread_stack_node() for IA64 fork: Duplicate task_struct before stack allocation fork: Redo ifdefs around task stack handling
2 parents 3fd3327 + bf9ad37 commit bba90e0

9 files changed

Lines changed: 241 additions & 101 deletions

File tree

arch/ia64/include/asm/thread_info.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,15 @@ struct thread_info {
5555
#ifndef ASM_OFFSETS_C
5656
/* how to get the thread information struct from C */
5757
#define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
58-
#define alloc_thread_stack_node(tsk, node) \
58+
#define arch_alloc_thread_stack_node(tsk, node) \
5959
((unsigned long *) ((char *) (tsk) + IA64_TASK_SIZE))
6060
#define task_thread_info(tsk) ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
6161
#else
6262
#define current_thread_info() ((struct thread_info *) 0)
63-
#define alloc_thread_stack_node(tsk, node) ((unsigned long *) 0)
63+
#define arch_alloc_thread_stack_node(tsk, node) ((unsigned long *) 0)
6464
#define task_thread_info(tsk) ((struct thread_info *) 0)
6565
#endif
66-
#define free_thread_stack(tsk) /* nothing */
66+
#define arch_free_thread_stack(tsk) /* nothing */
6767
#define task_stack_page(tsk) ((void *)(tsk))
6868

6969
#define __HAVE_THREAD_FUNCTIONS

arch/x86/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ config X86
120120
select ARCH_WANTS_NO_INSTR
121121
select ARCH_WANT_HUGE_PMD_SHARE
122122
select ARCH_WANT_LD_ORPHAN_WARN
123+
select ARCH_WANTS_RT_DELAYED_SIGNALS
123124
select ARCH_WANTS_THP_SWAP if X86_64
124125
select ARCH_HAS_PARANOID_L1D_FLUSH
125126
select BUILDTIME_TABLE_SORT

include/linux/sched.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,9 @@ struct task_struct {
10901090
/* Restored if set_restore_sigmask() was used: */
10911091
sigset_t saved_sigmask;
10921092
struct sigpending pending;
1093+
#ifdef CONFIG_RT_DELAYED_SIGNALS
1094+
struct kernel_siginfo forced_info;
1095+
#endif
10931096
unsigned long sas_ss_sp;
10941097
size_t sas_ss_size;
10951098
unsigned int sas_ss_flags;

include/linux/sched/task_stack.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ static inline void *try_get_task_stack(struct task_struct *tsk)
7979
static inline void put_task_stack(struct task_struct *tsk) {}
8080
#endif
8181

82+
void exit_task_stack_account(struct task_struct *tsk);
83+
8284
#define task_stack_end_corrupted(task) \
8385
(*(end_of_stack(task)) != STACK_END_MAGIC)
8486

kernel/Kconfig.preempt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,14 @@ config SCHED_CORE
132132
which is the likely usage by Linux distributions, there should
133133
be no measurable impact on performance.
134134

135-
135+
config ARCH_WANTS_RT_DELAYED_SIGNALS
136+
bool
137+
help
138+
This option is selected by architectures where raising signals
139+
can happen in atomic contexts on PREEMPT_RT enabled kernels. This
140+
option delays raising the signal until the return to user space
141+
loop where it is also delivered. X86 requires this to deliver
142+
signals from trap handlers which run on IST stacks.
143+
144+
config RT_DELAYED_SIGNALS
145+
def_bool PREEMPT_RT && ARCH_WANTS_RT_DELAYED_SIGNALS

kernel/entry/common.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,18 @@ static void handle_signal_work(struct pt_regs *regs, unsigned long ti_work)
148148
arch_do_signal_or_restart(regs, ti_work & _TIF_SIGPENDING);
149149
}
150150

151+
#ifdef CONFIG_RT_DELAYED_SIGNALS
152+
static inline void raise_delayed_signal(void)
153+
{
154+
if (unlikely(current->forced_info.si_signo)) {
155+
force_sig_info(&current->forced_info);
156+
current->forced_info.si_signo = 0;
157+
}
158+
}
159+
#else
160+
static inline void raise_delayed_signal(void) { }
161+
#endif
162+
151163
static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
152164
unsigned long ti_work)
153165
{
@@ -162,6 +174,8 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
162174
if (ti_work & _TIF_NEED_RESCHED)
163175
schedule();
164176

177+
raise_delayed_signal();
178+
165179
if (ti_work & _TIF_UPROBE)
166180
uprobe_notify_resume(regs);
167181

kernel/exit.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,7 @@ void __noreturn do_exit(long code)
845845
put_page(tsk->task_frag.page);
846846

847847
validate_creds_for_do_exit(tsk);
848+
exit_task_stack_account(tsk);
848849

849850
check_stack_usage();
850851
preempt_disable();

0 commit comments

Comments
 (0)