mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-09 06:43:09 +00:00
signals: introduce do_send_sig_info() helper
Introduce do_send_sig_info() and convert group_send_sig_info(), send_sig_info(), do_send_specific() to use this helper. Hopefully it will have more users soon, it allows to specify specific/group behaviour via "bool group" argument. Shaves 80 bytes from .text. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: stephane eranian <eranian@googlemail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Roland McGrath <roland@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
964ee7df90
commit
4a30debfb7
@ -233,6 +233,8 @@ static inline int valid_signal(unsigned long sig)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern int next_signal(struct sigpending *pending, sigset_t *mask);
|
extern int next_signal(struct sigpending *pending, sigset_t *mask);
|
||||||
|
extern int do_send_sig_info(int sig, struct siginfo *info,
|
||||||
|
struct task_struct *p, bool group);
|
||||||
extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
|
extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
|
||||||
extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
|
extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
|
||||||
extern long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig,
|
extern long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig,
|
||||||
|
@ -971,6 +971,20 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
|
|||||||
return send_signal(sig, info, t, 0);
|
return send_signal(sig, info, t, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p,
|
||||||
|
bool group)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int ret = -ESRCH;
|
||||||
|
|
||||||
|
if (lock_task_sighand(p, &flags)) {
|
||||||
|
ret = send_signal(sig, info, p, group);
|
||||||
|
unlock_task_sighand(p, &flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force a signal that the process can't ignore: if necessary
|
* Force a signal that the process can't ignore: if necessary
|
||||||
* we unblock the signal and change any SIG_IGN to SIG_DFL.
|
* we unblock the signal and change any SIG_IGN to SIG_DFL.
|
||||||
@ -1068,18 +1082,10 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long
|
|||||||
*/
|
*/
|
||||||
int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
|
int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
int ret = check_kill_permission(sig, info, p);
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = check_kill_permission(sig, info, p);
|
if (!ret && sig)
|
||||||
|
ret = do_send_sig_info(sig, info, p, true);
|
||||||
if (!ret && sig) {
|
|
||||||
ret = -ESRCH;
|
|
||||||
if (lock_task_sighand(p, &flags)) {
|
|
||||||
ret = __group_send_sig_info(sig, info, p);
|
|
||||||
unlock_task_sighand(p, &flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1224,15 +1230,9 @@ static int kill_something_info(int sig, struct siginfo *info, pid_t pid)
|
|||||||
* These are for backward compatibility with the rest of the kernel source.
|
* These are for backward compatibility with the rest of the kernel source.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* The caller must ensure the task can't exit.
|
|
||||||
*/
|
|
||||||
int
|
int
|
||||||
send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
|
send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure legacy kernel users don't send in bad values
|
* Make sure legacy kernel users don't send in bad values
|
||||||
* (normal paths check this in check_kill_permission).
|
* (normal paths check this in check_kill_permission).
|
||||||
@ -1240,10 +1240,7 @@ send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
|
|||||||
if (!valid_signal(sig))
|
if (!valid_signal(sig))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
spin_lock_irqsave(&p->sighand->siglock, flags);
|
return do_send_sig_info(sig, info, p, false);
|
||||||
ret = specific_send_sig_info(sig, info, p);
|
|
||||||
spin_unlock_irqrestore(&p->sighand->siglock, flags);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define __si_special(priv) \
|
#define __si_special(priv) \
|
||||||
@ -2278,7 +2275,6 @@ static int
|
|||||||
do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
|
do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
|
||||||
{
|
{
|
||||||
struct task_struct *p;
|
struct task_struct *p;
|
||||||
unsigned long flags;
|
|
||||||
int error = -ESRCH;
|
int error = -ESRCH;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
@ -2288,14 +2284,16 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
|
|||||||
/*
|
/*
|
||||||
* The null signal is a permissions and process existence
|
* The null signal is a permissions and process existence
|
||||||
* probe. No signal is actually delivered.
|
* probe. No signal is actually delivered.
|
||||||
*
|
|
||||||
* If lock_task_sighand() fails we pretend the task dies
|
|
||||||
* after receiving the signal. The window is tiny, and the
|
|
||||||
* signal is private anyway.
|
|
||||||
*/
|
*/
|
||||||
if (!error && sig && lock_task_sighand(p, &flags)) {
|
if (!error && sig) {
|
||||||
error = specific_send_sig_info(sig, info, p);
|
error = do_send_sig_info(sig, info, p, false);
|
||||||
unlock_task_sighand(p, &flags);
|
/*
|
||||||
|
* If lock_task_sighand() failed we pretend the task
|
||||||
|
* dies after receiving the signal. The window is tiny,
|
||||||
|
* and the signal is private anyway.
|
||||||
|
*/
|
||||||
|
if (unlikely(error == -ESRCH))
|
||||||
|
error = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
Loading…
Reference in New Issue
Block a user