Commit 56bfc42f authored by Paul Mundt's avatar Paul Mundt

sh: TS_RESTORE_SIGMASK conversion.

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: default avatarPaul Mundt <lethal@linux-sh.org>
parent b195e466
...@@ -19,6 +19,7 @@ struct thread_info { ...@@ -19,6 +19,7 @@ struct thread_info {
struct task_struct *task; /* main task structure */ struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */ struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */ unsigned long flags; /* low level flags */
__u32 status; /* thread synchronous flags */
__u32 cpu; __u32 cpu;
int preempt_count; /* 0 => preemptable, <0 => BUG */ int preempt_count; /* 0 => preemptable, <0 => BUG */
mm_segment_t addr_limit; /* thread address space */ mm_segment_t addr_limit; /* thread address space */
...@@ -111,7 +112,6 @@ extern void free_thread_info(struct thread_info *ti); ...@@ -111,7 +112,6 @@ extern void free_thread_info(struct thread_info *ti);
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_SIGPENDING 1 /* signal pending */ #define TIF_SIGPENDING 1 /* signal pending */
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */ #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_SINGLESTEP 4 /* singlestepping active */
#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ #define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
#define TIF_SECCOMP 6 /* secure computing */ #define TIF_SECCOMP 6 /* secure computing */
...@@ -125,7 +125,6 @@ extern void free_thread_info(struct thread_info *ti); ...@@ -125,7 +125,6 @@ extern void free_thread_info(struct thread_info *ti);
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP) #define _TIF_SECCOMP (1 << TIF_SECCOMP)
...@@ -149,13 +148,32 @@ extern void free_thread_info(struct thread_info *ti); ...@@ -149,13 +148,32 @@ extern void free_thread_info(struct thread_info *ti);
/* work to do on any return to u-space */ /* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \ #define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \
_TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \ _TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \
_TIF_SINGLESTEP | _TIF_RESTORE_SIGMASK | \ _TIF_SINGLESTEP | _TIF_NOTIFY_RESUME | \
_TIF_NOTIFY_RESUME | _TIF_SYSCALL_TRACEPOINT) _TIF_SYSCALL_TRACEPOINT)
/* work to do on interrupt/exception return */ /* work to do on interrupt/exception return */
#define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \ #define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
_TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP)) _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 /* __KERNEL__ */
#endif /* __ASM_SH_THREAD_INFO_H */ #endif /* __ASM_SH_THREAD_INFO_H */
...@@ -933,7 +933,7 @@ ret_with_reschedule: ...@@ -933,7 +933,7 @@ ret_with_reschedule:
pta restore_all, tr1 pta restore_all, tr1
movi (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r8 movi _TIF_SIGPENDING, r8
and r8, r7, r8 and r8, r7, r8
pta work_notifysig, tr0 pta work_notifysig, tr0
bne r8, ZERO, tr0 bne r8, ZERO, tr0
......
...@@ -133,7 +133,7 @@ work_pending: ...@@ -133,7 +133,7 @@ work_pending:
! r8: current_thread_info ! r8: current_thread_info
! t: result of "tst #_TIF_NEED_RESCHED, r0" ! t: result of "tst #_TIF_NEED_RESCHED, r0"
bf/s work_resched bf/s work_resched
tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 tst #_TIF_SIGPENDING, r0
work_notifysig: work_notifysig:
bt/s __restore_all bt/s __restore_all
mov r15, r4 mov r15, r4
......
...@@ -67,7 +67,8 @@ sys_sigsuspend(old_sigset_t mask, ...@@ -67,7 +67,8 @@ sys_sigsuspend(old_sigset_t mask,
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule(); schedule();
set_thread_flag(TIF_RESTORE_SIGMASK); set_restore_sigmask();
return -ERESTARTNOHAND; return -ERESTARTNOHAND;
} }
...@@ -590,7 +591,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) ...@@ -590,7 +591,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
if (try_to_freeze()) if (try_to_freeze())
goto no_signal; goto no_signal;
if (test_thread_flag(TIF_RESTORE_SIGMASK)) if (current_thread_info()->status & TS_RESTORE_SIGMASK)
oldset = &current->saved_sigmask; oldset = &current->saved_sigmask;
else else
oldset = &current->blocked; oldset = &current->blocked;
...@@ -602,12 +603,13 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) ...@@ -602,12 +603,13 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(signr, &ka, &info, oldset, if (handle_signal(signr, &ka, &info, oldset,
regs, save_r0) == 0) { 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, * sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply * and will be restored by sigreturn, so we can simply
* 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, tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP)); test_thread_flag(TIF_SINGLESTEP));
...@@ -631,10 +633,12 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) ...@@ -631,10 +633,12 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
} }
} }
/* if there's no signal to deliver, we just put the saved sigmask /*
* back */ * If there's no signal to deliver, we just put the saved sigmask
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { * back.
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); sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
} }
} }
......
...@@ -101,7 +101,7 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -101,7 +101,7 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (try_to_freeze()) if (try_to_freeze())
goto no_signal; goto no_signal;
if (test_thread_flag(TIF_RESTORE_SIGMASK)) if (current_thread_info()->status & TS_RESTORE_SIGMASK)
oldset = &current->saved_sigmask; oldset = &current->saved_sigmask;
else if (!oldset) else if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
...@@ -115,11 +115,9 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -115,11 +115,9 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
/* /*
* If a signal was successfully delivered, the * If a signal was successfully delivered, the
* saved sigmask is in its frame, and we can * 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)) current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signr, &info, &ka, regs, 0); tracehook_signal_handler(signr, &info, &ka, regs, 0);
return 1; return 1;
} }
...@@ -146,8 +144,8 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -146,8 +144,8 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
} }
/* No signal to deliver -- put the saved sigmask back */ /* No signal to deliver -- put the saved sigmask back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
clear_thread_flag(TIF_RESTORE_SIGMASK); current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
} }
...@@ -176,6 +174,7 @@ sys_sigsuspend(old_sigset_t mask, ...@@ -176,6 +174,7 @@ sys_sigsuspend(old_sigset_t mask,
while (1) { while (1) {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule(); schedule();
set_restore_sigmask();
regs->pc += 4; /* because sys_sigreturn decrements the pc */ regs->pc += 4; /* because sys_sigreturn decrements the pc */
if (do_signal(regs, &saveset)) { if (do_signal(regs, &saveset)) {
/* pc now points at signal handler. Need to decrement /* pc now points at signal handler. Need to decrement
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment