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
2 changed files with 29 additions and 29 deletions
|
@ -233,6 +233,8 @@ static inline int valid_signal(unsigned long sig)
|
|||
}
|
||||
|
||||
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, struct siginfo *, struct task_struct *);
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
int ret = check_kill_permission(sig, info, p);
|
||||
|
||||
ret = check_kill_permission(sig, info, p);
|
||||
|
||||
if (!ret && sig) {
|
||||
ret = -ESRCH;
|
||||
if (lock_task_sighand(p, &flags)) {
|
||||
ret = __group_send_sig_info(sig, info, p);
|
||||
unlock_task_sighand(p, &flags);
|
||||
}
|
||||
}
|
||||
if (!ret && sig)
|
||||
ret = do_send_sig_info(sig, info, p, true);
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The caller must ensure the task can't exit.
|
||||
*/
|
||||
int
|
||||
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
|
||||
* (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))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&p->sighand->siglock, flags);
|
||||
ret = specific_send_sig_info(sig, info, p);
|
||||
spin_unlock_irqrestore(&p->sighand->siglock, flags);
|
||||
return ret;
|
||||
return do_send_sig_info(sig, info, p, false);
|
||||
}
|
||||
|
||||
#define __si_special(priv) \
|
||||
|
@ -2278,7 +2275,6 @@ static int
|
|||
do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
|
||||
{
|
||||
struct task_struct *p;
|
||||
unsigned long flags;
|
||||
int error = -ESRCH;
|
||||
|
||||
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
|
||||
* 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)) {
|
||||
error = specific_send_sig_info(sig, info, p);
|
||||
unlock_task_sighand(p, &flags);
|
||||
if (!error && sig) {
|
||||
error = do_send_sig_info(sig, info, p, false);
|
||||
/*
|
||||
* 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();
|
||||
|
|
Loading…
Reference in a new issue