mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ingo Molnar <mingo@elte.hu>
To: Roland McGrath <roland@redhat.com>
Cc: "Thomas Gleixner" <tglx@linutronix.de>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Linus Torvalds" <torvalds@linux-foundation.org>,
	linux-kernel@vger.kernel.org,
	"Elias Oltmanns" <eo@nebensachen.de>,
	"Török Edwin" <edwintorok@gmail.com>,
	"Arjan van de Ven" <arjan@infradead.org>
Subject: Re: [PATCH] x86_64: fix delayed signals
Date: Fri, 11 Jul 2008 07:46:05 +0200	[thread overview]
Message-ID: <20080711054605.GA17851@elte.hu> (raw)
In-Reply-To: <20080710215039.2A143154218@magilla.localdomain>


* Roland McGrath <roland@redhat.com> wrote:

> On three of the several paths in entry_64.S that call 
> do_notify_resume() on the way back to user mode, we fail to properly 
> check again for newly-arrived work that requires another call to 
> do_notify_resume() before going to user mode.  These paths set the 
> mask to check only _TIF_NEED_RESCHED, but this is wrong.  The other 
> paths that lead to do_notify_resume() do this correctly already, and 
> entry_32.S does it correctly in all cases.

nice find! Roland, is this related to the thread started by Elias 
Oltmanns yesterday:

    http://lkml.org/lkml/2008/7/10/57

which is also related to the thread started by Edwin Török:

    http://lkml.org/lkml/2008/6/28/50

? The weight of complains seems to be on the 64-bit side, in those 
threads 32-bit systems seem to be implicated as well by latencytop. 
Perhaps the 64-bit delays are related to the bug you fix and we could 
chalk up the 32-bit delays to IO delays?

more people Cc:-ed: if your delays happen on 64-bit x86 systems - does 
Roland's patch (also repeated below) fix those delay issues?

	Ingo

------------------------->
Subject: x86: fix delayed signals
From: Roland McGrath <roland@redhat.com>

On three of the several paths in entry_64.S that call
do_notify_resume() on the way back to user mode, we fail to properly
check again for newly-arrived work that requires another call to
do_notify_resume() before going to user mode.  These paths set the
mask to check only _TIF_NEED_RESCHED, but this is wrong.  The other
paths that lead to do_notify_resume() do this correctly already, and
entry_32.S does it correctly in all cases.

All paths back to user mode have to check all the _TIF_WORK_MASK
flags at the last possible stage, with interrupts disabled.
Otherwise, we miss any flags (TIF_SIGPENDING for example) that were
set any time after we entered do_notify_resume().  More work flags
can be set (or left set) synchronously inside do_notify_resume(), as
TIF_SIGPENDING can be, or asynchronously by interrupts or other CPUs
(which then send an asynchronous interrupt).

There are many different scenarios that could hit this bug, most of
them races.  The simplest one to demonstrate does not require any
race: when one signal has done handler setup at the check before
returning from a syscall, and there is another signal pending that
should be handled.  The second signal's handler should interrupt the
first signal handler before it actually starts (so the interrupted PC
is still at the handler's entry point).  Instead, it runs away until
the next kernel entry (next syscall, tick, etc).

This test behaves correctly on 32-bit kernels, and fails on 64-bit
(either 32-bit or 64-bit test binary).  With this fix, it works.

    #define _GNU_SOURCE
    #include <stdio.h>
    #include <signal.h>
    #include <string.h>
    #include <sys/ucontext.h>

    #ifndef REG_RIP
    #define REG_RIP REG_EIP
    #endif

    static sig_atomic_t hit1, hit2;

    static void
    handler (int sig, siginfo_t *info, void *ctx)
    {
      ucontext_t *uc = ctx;

      if ((void *) uc->uc_mcontext.gregs[REG_RIP] == &handler)
        {
          if (sig == SIGUSR1)
            hit1 = 1;
          else
            hit2 = 1;
        }

      printf ("%s at %#lx\n", strsignal (sig),
              uc->uc_mcontext.gregs[REG_RIP]);
    }

    int
    main (void)
    {
      struct sigaction sa;
      sigset_t set;

      sigemptyset (&sa.sa_mask);
      sa.sa_flags = SA_SIGINFO;
      sa.sa_sigaction = &handler;

      if (sigaction (SIGUSR1, &sa, NULL)
          || sigaction (SIGUSR2, &sa, NULL))
        return 2;

      sigemptyset (&set);
      sigaddset (&set, SIGUSR1);
      sigaddset (&set, SIGUSR2);
      if (sigprocmask (SIG_BLOCK, &set, NULL))
        return 3;

      printf ("main at %p, handler at %p\n", &main, &handler);

      raise (SIGUSR1);
      raise (SIGUSR2);

      if (sigprocmask (SIG_UNBLOCK, &set, NULL))
        return 4;

      if (hit1 + hit2 == 1)
        {
          puts ("PASS");
          return 0;
        }

      puts ("FAIL");
      return 1;
    }

Signed-off-by: Roland McGrath <roland@redhat.com>
---
 arch/x86/kernel/entry_64.S |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 556a8df..968cf54 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -305,7 +305,7 @@ sysret_signal:
 	leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
 	xorl %esi,%esi # oldset -> arg2
 	call ptregscall_common
-1:	movl $_TIF_NEED_RESCHED,%edi
+1:	movl $_TIF_WORK_MASK,%edi
 	/* Use IRET because user could have changed frame. This
 	   works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
 	DISABLE_INTERRUPTS(CLBR_NONE)
@@ -393,7 +393,7 @@ int_signal:
 	movq %rsp,%rdi		# &ptregs -> arg1
 	xorl %esi,%esi		# oldset -> arg2
 	call do_notify_resume
-1:	movl $_TIF_NEED_RESCHED,%edi	
+1:	movl $_TIF_WORK_MASK,%edi
 int_restore_rest:
 	RESTORE_REST
 	DISABLE_INTERRUPTS(CLBR_NONE)
@@ -647,9 +647,8 @@ retint_signal:
 	RESTORE_REST
 	DISABLE_INTERRUPTS(CLBR_NONE)
 	TRACE_IRQS_OFF
-	movl $_TIF_NEED_RESCHED,%edi
 	GET_THREAD_INFO(%rcx)
-	jmp retint_check
+	jmp retint_with_reschedule
 
 #ifdef CONFIG_PREEMPT
 	/* Returning to kernel space. Check if we need preemption */

  parent reply	other threads:[~2008-07-11  5:46 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-10 21:50 Roland McGrath
2008-07-10 22:06 ` Linus Torvalds
2008-07-10 22:42   ` Roland McGrath
2008-07-10 22:51     ` Linus Torvalds
2008-07-10 23:02       ` Linus Torvalds
2008-07-11  0:52       ` Roland McGrath
2008-07-11  1:18         ` Linus Torvalds
2008-07-11  1:27           ` Roland McGrath
2008-07-11  1:48         ` Linus Torvalds
2008-07-11  2:02           ` Linus Torvalds
2008-07-11  2:22             ` Linus Torvalds
2008-07-11  2:26               ` Linus Torvalds
2008-07-12 12:24             ` Andi Kleen
2008-07-11  5:46 ` Ingo Molnar [this message]
2008-07-11 11:13   ` Török Edwin
2008-07-11 12:24   ` Elias Oltmanns
2008-07-11 17:58   ` Linus Torvalds
2008-07-11 18:07     ` Roland McGrath
2008-07-11 18:16       ` Linus Torvalds
2008-07-11 18:17         ` Linus Torvalds
2008-07-11 18:10     ` Linus Torvalds
2008-07-11 18:31       ` Linus Torvalds
2008-07-11 22:53         ` Arjan van de Ven
2008-07-12 10:33           ` Török Edwin
2008-07-11 20:37       ` Linus Torvalds
2008-07-11 23:22         ` Linus Torvalds
2008-07-12 10:32           ` Török Edwin
2008-07-12 13:42             ` Török Edwin
2008-07-12 14:55               ` Arjan van de Ven
2008-07-12 18:00                 ` Linus Torvalds
2008-07-12 18:15                   ` Arjan van de Ven
2008-07-12 18:28                     ` Linus Torvalds
2008-07-12 17:29             ` Linus Torvalds
2008-07-12 20:26               ` Török Edwin
2008-07-12 20:47                 ` Linus Torvalds
2008-07-12 20:57                 ` Denys Vlasenko
2008-07-13 10:46                   ` Oleg Nesterov
2008-07-13 12:34                     ` Denys Vlasenko
2008-07-13 18:36                     ` Linus Torvalds
2008-07-13 18:45                       ` Peter T. Breuer
2008-07-12 12:27     ` Andi Kleen
2008-07-12 17:41       ` Linus Torvalds
2008-07-13  9:38         ` Andi Kleen
2008-07-13 17:32           ` Linus Torvalds
2008-07-13 18:59             ` Andi Kleen
2008-07-13 19:08               ` Linus Torvalds

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080711054605.GA17851@elte.hu \
    --to=mingo@elte.hu \
    --cc=akpm@linux-foundation.org \
    --cc=arjan@infradead.org \
    --cc=edwintorok@gmail.com \
    --cc=eo@nebensachen.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=roland@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®