LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH 3/3] Consolidate send_sigqueue and send_group_sigqueue
@ 2008-02-22 12:56 Pavel Emelyanov
2008-02-22 14:41 ` Oleg Nesterov
0 siblings, 1 reply; 10+ messages in thread
From: Pavel Emelyanov @ 2008-02-22 12:56 UTC (permalink / raw)
To: Andrew Morton; +Cc: Linux Kernel Mailing List, Oleg Nesterov
Both function do the same thing after proper locking, but
with different sigpening structs, so move the common code
into a helper.
After this we have 4 places that look very similar:
send_sigqueue: calls do_send_sigqueue and signal_wakeup
send_group_sigqueue: calls do_send_sigqueue and __group_complete_signal
__group_send_sig_info: calls send_signal and __group_complete_signal
specific_send_sig_info: calls send_signal and signal_wakeup
Besides, send_signal performs actions similar to do_send_sigqueue's
and __group_complete_signal - to signal_wakeup.
It looks like they can be consolidated gracefully.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
---
kernel/signal.c | 86 ++++++++++++++++++------------------------------------
1 files changed, 29 insertions(+), 57 deletions(-)
diff --git a/kernel/signal.c b/kernel/signal.c
index 8b1b404..c6bb821 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1291,10 +1291,33 @@ void sigqueue_free(struct sigqueue *q)
__sigqueue_free(q);
}
+static int do_send_sigqueue(int sig, struct sigqueue *q, struct task_struct *t,
+ struct sigpending *pending)
+{
+ if (unlikely(!list_empty(&q->list))) {
+ /*
+ * If an SI_TIMER entry is already queue just increment
+ * the overrun count.
+ */
+
+ BUG_ON(q->info.si_code != SI_TIMER);
+ q->info.si_overrun++;
+ return 0;
+ }
+
+ if (sig_ignored(t, sig))
+ return 1;
+
+ signalfd_notify(t, sig);
+ list_add_tail(&q->list, &pending->list);
+ sigaddset(&pending->signal, sig);
+ return 0;
+}
+
int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
{
unsigned long flags;
- int ret = 0;
+ int ret = -1;
BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
@@ -1308,37 +1331,14 @@ int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
*/
rcu_read_lock();
- if (!likely(lock_task_sighand(p, &flags))) {
- ret = -1;
+ if (!likely(lock_task_sighand(p, &flags)))
goto out_err;
- }
- if (unlikely(!list_empty(&q->list))) {
- /*
- * If an SI_TIMER entry is already queue just increment
- * the overrun count.
- */
- BUG_ON(q->info.si_code != SI_TIMER);
- q->info.si_overrun++;
- goto out;
- }
- /* Short-circuit ignored signals. */
- if (sig_ignored(p, sig)) {
- ret = 1;
- goto out;
- }
- /*
- * Deliver the signal to listening signalfds. This must be called
- * with the sighand lock held.
- */
- signalfd_notify(p, sig);
+ ret = do_send_sigqueue(sig, q, p, &p->pending);
- list_add_tail(&q->list, &p->pending.list);
- sigaddset(&p->pending.signal, sig);
if (!sigismember(&p->blocked, sig))
signal_wake_up(p, sig == SIGKILL);
-out:
unlock_task_sighand(p, &flags);
out_err:
rcu_read_unlock();
@@ -1350,7 +1350,7 @@ int
send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
{
unsigned long flags;
- int ret = 0;
+ int ret;
BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
@@ -1359,38 +1359,10 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
spin_lock_irqsave(&p->sighand->siglock, flags);
handle_stop_signal(sig, p);
- /* Short-circuit ignored signals. */
- if (sig_ignored(p, sig)) {
- ret = 1;
- goto out;
- }
-
- if (unlikely(!list_empty(&q->list))) {
- /*
- * If an SI_TIMER entry is already queue just increment
- * the overrun count. Other uses should not try to
- * send the signal multiple times.
- */
- BUG_ON(q->info.si_code != SI_TIMER);
- q->info.si_overrun++;
- goto out;
- }
- /*
- * Deliver the signal to listening signalfds. This must be called
- * with the sighand lock held.
- */
- signalfd_notify(p, sig);
-
- /*
- * Put this signal on the shared-pending queue.
- * We always use the shared queue for process-wide signals,
- * to avoid several races.
- */
- list_add_tail(&q->list, &p->signal->shared_pending.list);
- sigaddset(&p->signal->shared_pending.signal, sig);
+ ret = do_send_sigqueue(sig, q, p, &p->signal->shared_pending);
__group_complete_signal(sig, p);
-out:
+
spin_unlock_irqrestore(&p->sighand->siglock, flags);
read_unlock(&tasklist_lock);
return ret;
--
1.5.3.4
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 3/3] Consolidate send_sigqueue and send_group_sigqueue
2008-02-22 12:56 [PATCH 3/3] Consolidate send_sigqueue and send_group_sigqueue Pavel Emelyanov
@ 2008-02-22 14:41 ` Oleg Nesterov
2008-02-28 4:54 ` Thomas Gleixner
0 siblings, 1 reply; 10+ messages in thread
From: Oleg Nesterov @ 2008-02-22 14:41 UTC (permalink / raw)
To: Pavel Emelyanov, Thomas Gleixner; +Cc: Andrew Morton, Linux Kernel Mailing List
On 02/22, Pavel Emelyanov wrote:
>
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -1291,10 +1291,33 @@ void sigqueue_free(struct sigqueue *q)
> __sigqueue_free(q);
> }
>
> +static int do_send_sigqueue(int sig, struct sigqueue *q, struct task_struct *t,
> + struct sigpending *pending)
> +{
> + if (unlikely(!list_empty(&q->list))) {
> + /*
> + * If an SI_TIMER entry is already queue just increment
> + * the overrun count.
> + */
> +
> + BUG_ON(q->info.si_code != SI_TIMER);
> + q->info.si_overrun++;
> + return 0;
> + }
> +
> + if (sig_ignored(t, sig))
> + return 1;
> +
> + signalfd_notify(t, sig);
> + list_add_tail(&q->list, &pending->list);
> + sigaddset(&pending->signal, sig);
> + return 0;
> +}
> +
> int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
> {
> unsigned long flags;
> - int ret = 0;
> + int ret = -1;
>
> BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
>
> @@ -1308,37 +1331,14 @@ int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
> */
> rcu_read_lock();
>
> - if (!likely(lock_task_sighand(p, &flags))) {
> - ret = -1;
> + if (!likely(lock_task_sighand(p, &flags)))
> goto out_err;
> - }
>
> - if (unlikely(!list_empty(&q->list))) {
> - /*
> - * If an SI_TIMER entry is already queue just increment
> - * the overrun count.
> - */
> - BUG_ON(q->info.si_code != SI_TIMER);
> - q->info.si_overrun++;
> - goto out;
> - }
> - /* Short-circuit ignored signals. */
> - if (sig_ignored(p, sig)) {
> - ret = 1;
> - goto out;
> - }
> - /*
> - * Deliver the signal to listening signalfds. This must be called
> - * with the sighand lock held.
> - */
> - signalfd_notify(p, sig);
> + ret = do_send_sigqueue(sig, q, p, &p->pending);
>
> - list_add_tail(&q->list, &p->pending.list);
> - sigaddset(&p->pending.signal, sig);
> if (!sigismember(&p->blocked, sig))
> signal_wake_up(p, sig == SIGKILL);
>
> -out:
> unlock_task_sighand(p, &flags);
> out_err:
> rcu_read_unlock();
> @@ -1350,7 +1350,7 @@ int
> send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
> {
> unsigned long flags;
> - int ret = 0;
> + int ret;
>
> BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
>
> @@ -1359,38 +1359,10 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
> spin_lock_irqsave(&p->sighand->siglock, flags);
> handle_stop_signal(sig, p);
>
> - /* Short-circuit ignored signals. */
> - if (sig_ignored(p, sig)) {
> - ret = 1;
> - goto out;
> - }
> -
> - if (unlikely(!list_empty(&q->list))) {
> - /*
> - * If an SI_TIMER entry is already queue just increment
> - * the overrun count. Other uses should not try to
> - * send the signal multiple times.
> - */
> - BUG_ON(q->info.si_code != SI_TIMER);
> - q->info.si_overrun++;
> - goto out;
> - }
> - /*
> - * Deliver the signal to listening signalfds. This must be called
> - * with the sighand lock held.
> - */
> - signalfd_notify(p, sig);
> -
> - /*
> - * Put this signal on the shared-pending queue.
> - * We always use the shared queue for process-wide signals,
> - * to avoid several races.
> - */
> - list_add_tail(&q->list, &p->signal->shared_pending.list);
> - sigaddset(&p->signal->shared_pending.signal, sig);
> + ret = do_send_sigqueue(sig, q, p, &p->signal->shared_pending);
>
> __group_complete_signal(sig, p);
> -out:
> +
> spin_unlock_irqrestore(&p->sighand->siglock, flags);
> read_unlock(&tasklist_lock);
> return ret;
> --
Personally, I think this change is very good. But send_sigqueue() and
send_group_sigqueue() have a very subtle difference which I was never
able to understand.
Let's suppose that sigqueue is already queued, and the signal is ignored
(the latter means we should re-schedule cpu timer or handle overrruns).
In that case send_sigqueue() returns 0, but send_group_sigqueue() returns 1.
I think this is not the problem (in fact, I think this patch makes the
behaviour more correct), but I hope Thomas can take a look and confirm.
Oleg.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 3/3] Consolidate send_sigqueue and send_group_sigqueue
2008-02-22 14:41 ` Oleg Nesterov
@ 2008-02-28 4:54 ` Thomas Gleixner
2008-02-28 6:17 ` Oleg Nesterov
0 siblings, 1 reply; 10+ messages in thread
From: Thomas Gleixner @ 2008-02-28 4:54 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Pavel Emelyanov, Andrew Morton, Linux Kernel Mailing List,
Roland McGrath
On Fri, 22 Feb 2008, Oleg Nesterov wrote:
> > -
> > - if (unlikely(!list_empty(&q->list))) {
> > - /*
> > - * If an SI_TIMER entry is already queue just increment
> > - * the overrun count.
> > - */
> > - BUG_ON(q->info.si_code != SI_TIMER);
> > - q->info.si_overrun++;
> > - goto out;
> > - }
> > - /* Short-circuit ignored signals. */
> > - if (sig_ignored(p, sig)) {
> > - ret = 1;
> > - goto out;
> > - }
> > send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
> > - /* Short-circuit ignored signals. */
> > - if (sig_ignored(p, sig)) {
> > - ret = 1;
> > - goto out;
> > - }
> > -
> > - if (unlikely(!list_empty(&q->list))) {
> > - /*
> > - * If an SI_TIMER entry is already queue just increment
> > - * the overrun count. Other uses should not try to
> > - * send the signal multiple times.
> > - */
> > - BUG_ON(q->info.si_code != SI_TIMER);
> > - q->info.si_overrun++;
> > - goto out;
> > - }
>
> Personally, I think this change is very good. But send_sigqueue() and
> send_group_sigqueue() have a very subtle difference which I was never
> able to understand.
>
> Let's suppose that sigqueue is already queued, and the signal is ignored
> (the latter means we should re-schedule cpu timer or handle overrruns).
> In that case send_sigqueue() returns 0, but send_group_sigqueue() returns 1.
>
> I think this is not the problem (in fact, I think this patch makes the
> behaviour more correct), but I hope Thomas can take a look and confirm.
It should not change anything. We should never have a signal enqueued
when it's ignored anyway.
Roland, any insight why this is different aside of a copy and paste
error ?
Thanks,
tglx
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 3/3] Consolidate send_sigqueue and send_group_sigqueue
2008-02-28 4:54 ` Thomas Gleixner
@ 2008-02-28 6:17 ` Oleg Nesterov
[not found] ` <20080228113633.7431C2700FD@magilla.localdomain>
0 siblings, 1 reply; 10+ messages in thread
From: Oleg Nesterov @ 2008-02-28 6:17 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Pavel Emelyanov, Andrew Morton, Linux Kernel Mailing List,
Roland McGrath
On 02/28, Thomas Gleixner wrote:
>
> On Fri, 22 Feb 2008, Oleg Nesterov wrote:
> > > -
> > > - if (unlikely(!list_empty(&q->list))) {
> > > - /*
> > > - * If an SI_TIMER entry is already queue just increment
> > > - * the overrun count.
> > > - */
> > > - BUG_ON(q->info.si_code != SI_TIMER);
> > > - q->info.si_overrun++;
> > > - goto out;
> > > - }
> > > - /* Short-circuit ignored signals. */
> > > - if (sig_ignored(p, sig)) {
> > > - ret = 1;
> > > - goto out;
> > > - }
>
> > > send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
>
> > > - /* Short-circuit ignored signals. */
> > > - if (sig_ignored(p, sig)) {
> > > - ret = 1;
> > > - goto out;
> > > - }
> > > -
> > > - if (unlikely(!list_empty(&q->list))) {
> > > - /*
> > > - * If an SI_TIMER entry is already queue just increment
> > > - * the overrun count. Other uses should not try to
> > > - * send the signal multiple times.
> > > - */
> > > - BUG_ON(q->info.si_code != SI_TIMER);
> > > - q->info.si_overrun++;
> > > - goto out;
> > > - }
> >
> > Personally, I think this change is very good. But send_sigqueue() and
> > send_group_sigqueue() have a very subtle difference which I was never
> > able to understand.
> >
> > Let's suppose that sigqueue is already queued, and the signal is ignored
> > (the latter means we should re-schedule cpu timer or handle overrruns).
> > In that case send_sigqueue() returns 0, but send_group_sigqueue() returns 1.
> >
> > I think this is not the problem (in fact, I think this patch makes the
> > behaviour more correct), but I hope Thomas can take a look and confirm.
>
> It should not change anything. We should never have a signal enqueued
> when it's ignored anyway.
Well, it _is_ possible. Suppose that the signal is both ignored and blocked.
Now, if the task unblocks the signal, it could be ignored, queued, and
sig_ignored() == T.
But yes, I think you are right, this can't change anything. I just wanted
to be sure there is no subtle reason to prefer one way or another.
> Roland, any insight why this is different aside of a copy and paste
> error ?
I guess this was the reason for the difference.
Oleg.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2008-02-29 11:29 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-02-22 12:56 [PATCH 3/3] Consolidate send_sigqueue and send_group_sigqueue Pavel Emelyanov
2008-02-22 14:41 ` Oleg Nesterov
2008-02-28 4:54 ` Thomas Gleixner
2008-02-28 6:17 ` Oleg Nesterov
[not found] ` <20080228113633.7431C2700FD@magilla.localdomain>
2008-02-28 15:36 ` Oleg Nesterov
2008-02-28 20:14 ` Roland McGrath
2008-02-29 11:32 ` Oleg Nesterov
2008-02-28 22:32 ` Thomas Gleixner
2008-02-28 22:41 ` Roland McGrath
2008-02-29 8:04 ` Thomas Gleixner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).