From: Al Viro <viro@ftp.linux.org.uk>
To: hans-christian.egtvedt@atmel.com
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH 6/6] avr32: deal with double restarts
Date: Wed, 15 Dec 2010 10:39:58 +0000 [thread overview]
Message-ID: <E1PSom6-0008UE-DQ@ZenIV.linux.org.uk> (raw)
a) take handling of reschedule, signals and keychains into a new helper -
work_pending(). All looping is done there now; asm glue calls that if
we have anything for it to do.
b) do_signal() gets explicit "may restart" flag as an argument; after
the first call during that loop it gets unconditional 0.
c) sigreturn() sets a thread flag - TIF_NORESTART. It is included into
the "work_pending() has something to do" mask. work_pending() clears
it, clearing its may_restart flag if it had done so.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
arch/avr32/include/asm/thread_info.h | 3 ++
arch/avr32/kernel/entry-avr32b.S | 45 ++++------------------------
arch/avr32/kernel/signal.c | 55 ++++++++++++++++++++++++----------
3 files changed, 48 insertions(+), 55 deletions(-)
diff --git a/arch/avr32/include/asm/thread_info.h b/arch/avr32/include/asm/thread_info.h
index 7a9c03d..1e8fa49 100644
--- a/arch/avr32/include/asm/thread_info.h
+++ b/arch/avr32/include/asm/thread_info.h
@@ -85,6 +85,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_RESTORE_SIGMASK 7 /* restore signal mask in do_signal */
#define TIF_CPU_GOING_TO_SLEEP 8 /* CPU is entering sleep 0 mode */
#define TIF_NOTIFY_RESUME 9 /* callback before returning to user */
+#define TIF_NORESTART 10
#define TIF_FREEZE 29
#define TIF_DEBUG 30 /* debugging enabled */
#define TIF_USERSPACE 31 /* true if FS sets userspace */
@@ -98,6 +99,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_CPU_GOING_TO_SLEEP (1 << TIF_CPU_GOING_TO_SLEEP)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
+#define _TIF_NORESTART (1 << TIF_NORESTART)
#define _TIF_FREEZE (1 << TIF_FREEZE)
/* Note: The masks below must never span more than 16 bits! */
@@ -106,6 +108,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_WORK_MASK \
((1 << TIF_SIGPENDING) \
| _TIF_NOTIFY_RESUME \
+ | _TIF_NORESTART \
| (1 << TIF_NEED_RESCHED) \
| (1 << TIF_POLLING_NRFLAG) \
| (1 << TIF_BREAKPOINT) \
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 5e6beb2..bb455b7 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -271,28 +271,11 @@ syscall_exit_work:
unmask_interrupts
call syscall_trace
mask_interrupts
- ld.w r1, r0[TI_flags]
-
-1: bld r1, TIF_NEED_RESCHED
- brcc 2f
- unmask_interrupts
- call schedule
- mask_interrupts
- ld.w r1, r0[TI_flags]
- rjmp 1b
-
-2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NOTIFY_RESUME
- tst r1, r2
- breq 3f
- unmask_interrupts
mov r12, sp
mov r11, r0
- call do_notify_resume
- mask_interrupts
- ld.w r1, r0[TI_flags]
- rjmp 1b
-
-3: bld r1, TIF_BREAKPOINT
+ mov r10, 1
+ call work_pending
+ bld r12, TIF_BREAKPOINT
brcc syscall_exit_cont
rjmp enter_monitor_mode
@@ -576,29 +559,13 @@ irq_exit_work:
mtsr SYSREG_SR, r8
sub pc, -2
get_thread_info r0
- ld.w r1, r0[TI_flags]
fault_exit_work:
- bld r1, TIF_NEED_RESCHED
- brcc 1f
- unmask_interrupts
- call schedule
- mask_interrupts
- ld.w r1, r0[TI_flags]
- rjmp fault_exit_work
-
-1: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NOTIFY_RESUME
- tst r1, r2
- breq 2f
- unmask_interrupts
mov r12, sp
mov r11, r0
- call do_notify_resume
- mask_interrupts
- ld.w r1, r0[TI_flags]
- rjmp fault_exit_work
-
-2: bld r1, TIF_BREAKPOINT
+ mov r10, 0
+ call work_pending
+ bld r12, TIF_BREAKPOINT
brcc fault_resume_user
rjmp enter_monitor_mode
diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c
index 3b4bb5a..f0c6d71 100644
--- a/arch/avr32/kernel/signal.c
+++ b/arch/avr32/kernel/signal.c
@@ -45,6 +45,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
+ set_thread_flag(TIF_NORESTART);
+
#define COPY(x) err |= __get_user(regs->x, &sc->x)
COPY(sr);
COPY(pc);
@@ -262,7 +264,7 @@ fail:
* doesn't want to handle. Thus you cannot kill init even with a
* SIGKILL even by mistake.
*/
-static void do_signal(struct pt_regs *regs, int syscall)
+static void do_signal(struct pt_regs *regs, int may_restart)
{
siginfo_t info;
int signr;
@@ -283,7 +285,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
oldset = ¤t->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (syscall) {
+ if (may_restart) {
switch (regs->r12) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
@@ -315,20 +317,41 @@ static void do_signal(struct pt_regs *regs, int syscall)
handle_signal(signr, &ka, &info, oldset, regs);
}
-asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
+asmlinkage int work_pending(struct pt_regs *regs, struct thread_info *ti, int may_restart)
{
- int syscall = 0;
-
- if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR)
- syscall = 1;
-
- if (ti->flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
- do_signal(regs, syscall);
-
- if (ti->flags & _TIF_NOTIFY_RESUME) {
- clear_thread_flag(TIF_NOTIFY_RESUME);
- tracehook_notify_resume(regs);
- if (current->replacement_session_keyring)
- key_replace_session_keyring();
+ int flags = ti->flags;
+ if (unlikely(flags & _TIF_NORESTART)) {
+ ti->flags &= ~_TIF_NORESTART;
+ may_restart = 0;
+ }
+ while (1) {
+ if (flags & _TIF_NEED_RESCHED) {
+ local_irq_enable();
+ schedule();
+ local_irq_disable();
+ flags = ti->flags;
+ continue;
+ }
+ if (flags & _TIF_SIGPENDING) {
+ local_irq_enable();
+ if ((sysreg_read(SR) & MODE_MASK) != MODE_SUPERVISOR)
+ may_restart = 0;
+ do_signal(regs, may_restart);
+ may_restart = 0;
+ local_irq_disable();
+ flags = ti->flags;
+ continue;
+ }
+ if (flags & _TIF_NOTIFY_RESUME) {
+ ti->flags &= ~_TIF_NOTIFY_RESUME;
+ local_irq_enable();
+ tracehook_notify_resume(regs);
+ if (current->replacement_session_keyring)
+ key_replace_session_keyring();
+ local_irq_disable();
+ flags = ti->flags;
+ continue;
+ }
+ return flags;
}
}
--
1.5.6.5
next reply other threads:[~2010-12-15 10:40 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-15 10:39 Al Viro [this message]
2011-01-13 20:28 ` [PATCH 6/6] avr32: deal with double restarts Hans-Christian Egtvedt
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=E1PSom6-0008UE-DQ@ZenIV.linux.org.uk \
--to=viro@ftp.linux.org.uk \
--cc=hans-christian.egtvedt@atmel.com \
--cc=linux-kernel@vger.kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.