Commit 29701d69 authored by Jens Axboe's avatar Jens Axboe
Browse files

Merge tag 'core-entry-notify-signal' of...

Merge tag 'core-entry-notify-signal' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into tif-task_work.arch

Core changes to support TASK_NOTIFY_SIGNAL

* tag 'core-entry-notify-signal' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  task_work: Use TIF_NOTIFY_SIGNAL if available
  entry: Add support for TIF_NOTIFY_SIGNAL
  signal: Add task_sigpending() helper
parents f8394f23 114518eb
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -804,11 +804,11 @@ static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs)
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 * mistake.
 */
void arch_do_signal(struct pt_regs *regs)
void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
{
	struct ksignal ksig;

	if (get_signal(&ksig)) {
	if (has_signal && get_signal(&ksig)) {
		/* Whee! Actually deliver the signal.  */
		handle_signal(&ksig, regs);
		return;
+8 −3
Original line number Diff line number Diff line
@@ -37,6 +37,10 @@
# define _TIF_UPROBE			(0)
#endif

#ifndef _TIF_NOTIFY_SIGNAL
# define _TIF_NOTIFY_SIGNAL		(0)
#endif

/*
 * TIF flags handled in syscall_enter_from_user_mode()
 */
@@ -69,7 +73,7 @@

#define EXIT_TO_USER_MODE_WORK						\
	(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE |		\
	 _TIF_NEED_RESCHED | _TIF_PATCH_PENDING |			\
	 _TIF_NEED_RESCHED | _TIF_PATCH_PENDING | _TIF_NOTIFY_SIGNAL |	\
	 ARCH_EXIT_TO_USER_MODE_WORK)

/**
@@ -259,12 +263,13 @@ static __always_inline void arch_exit_to_user_mode(void) { }
#endif

/**
 * arch_do_signal -  Architecture specific signal delivery function
 * arch_do_signal_or_restart -  Architecture specific signal delivery function
 * @regs:	Pointer to currents pt_regs
 * @has_signal:	actual signal to handle
 *
 * Invoked from exit_to_user_mode_loop().
 */
void arch_do_signal(struct pt_regs *regs);
void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal);

/**
 * arch_syscall_exit_tracehook - Wrapper around tracehook_report_syscall_exit()
+2 −2
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@
#endif

#define XFER_TO_GUEST_MODE_WORK						\
	(_TIF_NEED_RESCHED | _TIF_SIGPENDING |			\
	(_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL |	\
	 _TIF_NOTIFY_RESUME | ARCH_XFER_TO_GUEST_MODE_WORK)

struct kvm_vcpu;
+17 −3
Original line number Diff line number Diff line
@@ -353,11 +353,25 @@ static inline int restart_syscall(void)
	return -ERESTARTNOINTR;
}

static inline int signal_pending(struct task_struct *p)
static inline int task_sigpending(struct task_struct *p)
{
	return unlikely(test_tsk_thread_flag(p,TIF_SIGPENDING));
}

static inline int signal_pending(struct task_struct *p)
{
#if defined(TIF_NOTIFY_SIGNAL)
	/*
	 * TIF_NOTIFY_SIGNAL isn't really a signal, but it requires the same
	 * behavior in terms of ensuring that we break out of wait loops
	 * so that notify signal callbacks can be processed.
	 */
	if (unlikely(test_tsk_thread_flag(p, TIF_NOTIFY_SIGNAL)))
		return 1;
#endif
	return task_sigpending(p);
}

static inline int __fatal_signal_pending(struct task_struct *p)
{
	return unlikely(sigismember(&p->pending.signal, SIGKILL));
@@ -365,7 +379,7 @@ static inline int __fatal_signal_pending(struct task_struct *p)

static inline int fatal_signal_pending(struct task_struct *p)
{
	return signal_pending(p) && __fatal_signal_pending(p);
	return task_sigpending(p) && __fatal_signal_pending(p);
}

static inline int signal_pending_state(long state, struct task_struct *p)
@@ -502,7 +516,7 @@ extern int set_user_sigmask(const sigset_t __user *umask, size_t sigsetsize);
static inline void restore_saved_sigmask_unless(bool interrupted)
{
	if (interrupted)
		WARN_ON(!test_thread_flag(TIF_SIGPENDING));
		WARN_ON(!signal_pending(current));
	else
		restore_saved_sigmask();
}
+27 −0
Original line number Diff line number Diff line
@@ -198,4 +198,31 @@ static inline void tracehook_notify_resume(struct pt_regs *regs)
	blkcg_maybe_throttle_current();
}

/*
 * called by exit_to_user_mode_loop() if ti_work & _TIF_NOTIFY_SIGNAL. This
 * is currently used by TWA_SIGNAL based task_work, which requires breaking
 * wait loops to ensure that task_work is noticed and run.
 */
static inline void tracehook_notify_signal(void)
{
#if defined(TIF_NOTIFY_SIGNAL)
	clear_thread_flag(TIF_NOTIFY_SIGNAL);
	smp_mb__after_atomic();
	if (current->task_works)
		task_work_run();
#endif
}

/*
 * Called when we have work to process from exit_to_user_mode_loop()
 */
static inline void set_notify_signal(struct task_struct *task)
{
#if defined(TIF_NOTIFY_SIGNAL)
	if (!test_and_set_tsk_thread_flag(task, TIF_NOTIFY_SIGNAL) &&
	    !wake_up_state(task, TASK_INTERRUPTIBLE))
		kick_process(task);
#endif
}

#endif	/* <linux/tracehook.h> */
Loading