sh: TS_RESTORE_SIGMASK conversion.
authorPaul Mundt <lethal@linux-sh.org>
Wed, 14 Oct 2009 07:05:42 +0000 (16:05 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Wed, 14 Oct 2009 07:05:42 +0000 (16:05 +0900)
Replace TIF_RESTORE_SIGMASK with TS_RESTORE_SIGMASK and define our own
set_restore_sigmask() function.  This saves the costly SMP-safe set_bit
operation, which we do not need for the sigmask flag since TIF_SIGPENDING
always has to be set too.

Based on the x86 and powerpc change.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/include/asm/thread_info.h
arch/sh/kernel/cpu/sh5/entry.S
arch/sh/kernel/entry-common.S
arch/sh/kernel/signal_32.c
arch/sh/kernel/signal_64.c

index bdeb9d4..23eeed8 100644 (file)
@@ -19,6 +19,7 @@ struct thread_info {
        struct task_struct      *task;          /* main task structure */
        struct exec_domain      *exec_domain;   /* execution domain */
        unsigned long           flags;          /* low level flags */
+       __u32                   status;         /* thread synchronous flags */
        __u32                   cpu;
        int                     preempt_count; /* 0 => preemptable, <0 => BUG */
        mm_segment_t            addr_limit;     /* thread address space */
@@ -111,7 +112,6 @@ extern void free_thread_info(struct thread_info *ti);
 #define TIF_SYSCALL_TRACE      0       /* syscall trace active */
 #define TIF_SIGPENDING         1       /* signal pending */
 #define TIF_NEED_RESCHED       2       /* rescheduling necessary */
-#define TIF_RESTORE_SIGMASK    3       /* restore signal mask in do_signal() */
 #define TIF_SINGLESTEP         4       /* singlestepping active */
 #define TIF_SYSCALL_AUDIT      5       /* syscall auditing active */
 #define TIF_SECCOMP            6       /* secure computing */
@@ -125,7 +125,6 @@ extern void free_thread_info(struct thread_info *ti);
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
-#define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 #define _TIF_SINGLESTEP                (1 << TIF_SINGLESTEP)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
@@ -149,13 +148,32 @@ extern void free_thread_info(struct thread_info *ti);
 /* work to do on any return to u-space */
 #define _TIF_ALLWORK_MASK      (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING      | \
                                 _TIF_NEED_RESCHED  | _TIF_SYSCALL_AUDIT   | \
-                                _TIF_SINGLESTEP    | _TIF_RESTORE_SIGMASK | \
-                                _TIF_NOTIFY_RESUME | _TIF_SYSCALL_TRACEPOINT)
+                                _TIF_SINGLESTEP    | _TIF_NOTIFY_RESUME   | \
+                                _TIF_SYSCALL_TRACEPOINT)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK         (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
                                 _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP))
 
+/*
+ * Thread-synchronous status.
+ *
+ * This is different from the flags in that nobody else
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ */
+#define TS_RESTORE_SIGMASK     0x0001  /* restore signal mask in do_signal() */
+
+#ifndef __ASSEMBLY__
+#define HAVE_SET_RESTORE_SIGMASK       1
+static inline void set_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       ti->status |= TS_RESTORE_SIGMASK;
+       set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags);
+}
+#endif /* !__ASSEMBLY__ */
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASM_SH_THREAD_INFO_H */
index b0aacf6..8f13f73 100644 (file)
@@ -933,7 +933,7 @@ ret_with_reschedule:
 
        pta     restore_all, tr1
 
-       movi    (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r8
+       movi    _TIF_SIGPENDING, r8
        and     r8, r7, r8
        pta     work_notifysig, tr0
        bne     r8, ZERO, tr0
index 3eb8493..f0abd58 100644 (file)
@@ -133,7 +133,7 @@ work_pending:
        ! r8: current_thread_info
        ! t:  result of "tst    #_TIF_NEED_RESCHED, r0"
        bf/s    work_resched
-        tst    #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
+        tst    #_TIF_SIGPENDING, r0
 work_notifysig:
        bt/s    __restore_all
         mov    r15, r4
index 3db3742..12815ce 100644 (file)
@@ -67,7 +67,8 @@ sys_sigsuspend(old_sigset_t mask,
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
+       set_restore_sigmask();
+
        return -ERESTARTNOHAND;
 }
 
@@ -590,7 +591,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
        if (try_to_freeze())
                goto no_signal;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
                oldset = &current->saved_sigmask;
        else
                oldset = &current->blocked;
@@ -602,12 +603,13 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
                /* Whee!  Actually deliver the signal.  */
                if (handle_signal(signr, &ka, &info, oldset,
                                  regs, save_r0) == 0) {
-                       /* a signal was successfully delivered; the saved
+                       /*
+                        * A signal was successfully delivered; the saved
                         * sigmask will have been stored in the signal frame,
                         * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+                        * clear the TS_RESTORE_SIGMASK flag
+                        */
+                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
 
                        tracehook_signal_handler(signr, &info, &ka, regs,
                                        test_thread_flag(TIF_SINGLESTEP));
@@ -631,10 +633,12 @@ no_signal:
                }
        }
 
-       /* if there's no signal to deliver, we just put the saved sigmask
-        * back */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
+       /*
+        * If there's no signal to deliver, we just put the saved sigmask
+        * back.
+        */
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
+               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
        }
 }
index 74793c8..feb3ddd 100644 (file)
@@ -101,7 +101,7 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
        if (try_to_freeze())
                goto no_signal;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
                oldset = &current->saved_sigmask;
        else if (!oldset)
                oldset = &current->blocked;
@@ -115,11 +115,9 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
                        /*
                         * If a signal was successfully delivered, the
                         * saved sigmask is in its frame, and we can
-                        * clear the TIF_RESTORE_SIGMASK flag.
+                        * clear the TS_RESTORE_SIGMASK flag.
                         */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-
+                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
                        tracehook_signal_handler(signr, &info, &ka, regs, 0);
                        return 1;
                }
@@ -146,8 +144,8 @@ no_signal:
        }
 
        /* No signal to deliver -- put the saved sigmask back */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
+               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
        }
 
@@ -176,6 +174,7 @@ sys_sigsuspend(old_sigset_t mask,
        while (1) {
                current->state = TASK_INTERRUPTIBLE;
                schedule();
+               set_restore_sigmask();
                regs->pc += 4;    /* because sys_sigreturn decrements the pc */
                if (do_signal(regs, &saveset)) {
                        /* pc now points at signal handler. Need to decrement