提交 9f23e7e9 编写于 作者: P Paul Mundt

sh: pselect6 and ppoll, along with signal trampoline rework.

This implements support for ppoll() and pselect6()..
Signed-off-by: NPaul Mundt <lethal@linux-sh.org>
上级 a2d1a5fa
...@@ -371,12 +371,12 @@ work_pending: ...@@ -371,12 +371,12 @@ 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, r0 tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
work_notifysig: work_notifysig:
bt/s restore_all bt/s restore_all
mov r15, r4 mov r15, r4
mov #0, r5 mov r12, r5 ! set arg1(save_r0)
mov r12, r6 ! set arg2(save_r0) mov r0, r6
mov.l 2f, r1 mov.l 2f, r1
mova restore_all, r0 mova restore_all, r0
jmp @r1 jmp @r1
...@@ -414,7 +414,7 @@ work_resched: ...@@ -414,7 +414,7 @@ work_resched:
.align 2 .align 2
1: .long schedule 1: .long schedule
2: .long do_signal 2: .long do_notify_resume
.align 2 .align 2
syscall_exit_work: syscall_exit_work:
......
...@@ -29,13 +29,10 @@ ...@@ -29,13 +29,10 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#define DEBUG_SIG 0 #undef DEBUG
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset,
unsigned int save_r0);
/* /*
* Atomically swap in the new signal mask, and wait for a signal. * Atomically swap in the new signal mask, and wait for a signal.
*/ */
...@@ -44,51 +41,17 @@ sys_sigsuspend(old_sigset_t mask, ...@@ -44,51 +41,17 @@ sys_sigsuspend(old_sigset_t mask,
unsigned long r5, unsigned long r6, unsigned long r7, unsigned long r5, unsigned long r6, unsigned long r7,
struct pt_regs regs) struct pt_regs regs)
{ {
sigset_t saveset;
mask &= _BLOCKABLE; mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked; current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask); siginitset(&current->blocked, mask);
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
regs.regs[0] = -EINTR; current->state = TASK_INTERRUPTIBLE;
while (1) { schedule();
current->state = TASK_INTERRUPTIBLE; set_thread_flag(TIF_RESTORE_SIGMASK);
schedule(); return -ERESTARTNOHAND;
if (do_signal(&regs, &saveset, regs.regs[0]))
return -EINTR;
}
}
asmlinkage int
sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
sigset_t saveset, newset;
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
return -EINVAL;
if (copy_from_user(&newset, unewset, sizeof(newset)))
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
regs.regs[0] = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal(&regs, &saveset, regs.regs[0]))
return -EINTR;
}
} }
asmlinkage int asmlinkage int
...@@ -349,7 +312,7 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) ...@@ -349,7 +312,7 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
return (void __user *)((sp - frame_size) & -8ul); return (void __user *)((sp - frame_size) & -8ul);
} }
static void setup_frame(int sig, struct k_sigaction *ka, static int setup_frame(int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs *regs) sigset_t *set, struct pt_regs *regs)
{ {
struct sigframe __user *frame; struct sigframe __user *frame;
...@@ -369,10 +332,9 @@ static void setup_frame(int sig, struct k_sigaction *ka, ...@@ -369,10 +332,9 @@ static void setup_frame(int sig, struct k_sigaction *ka,
err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
if (_NSIG_WORDS > 1) { if (_NSIG_WORDS > 1)
err |= __copy_to_user(frame->extramask, &set->sig[1], err |= __copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask)); sizeof(frame->extramask));
}
/* Set up to return from userspace. If provided, use a stub /* Set up to return from userspace. If provided, use a stub
already in userspace. */ already in userspace. */
...@@ -403,21 +365,22 @@ static void setup_frame(int sig, struct k_sigaction *ka, ...@@ -403,21 +365,22 @@ static void setup_frame(int sig, struct k_sigaction *ka,
set_fs(USER_DS); set_fs(USER_DS);
#if DEBUG_SIG pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", current->comm, current->pid, frame, regs->pc, regs->pr);
current->comm, current->pid, frame, regs->pc, regs->pr);
#endif
flush_cache_sigtramp(regs->pr); flush_cache_sigtramp(regs->pr);
if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode)) if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES); flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
return;
return 0;
give_sigsegv: give_sigsegv:
force_sigsegv(sig, current); force_sigsegv(sig, current);
return -EFAULT;
} }
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs) sigset_t *set, struct pt_regs *regs)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
...@@ -478,28 +441,31 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -478,28 +441,31 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
set_fs(USER_DS); set_fs(USER_DS);
#if DEBUG_SIG pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", current->comm, current->pid, frame, regs->pc, regs->pr);
current->comm, current->pid, frame, regs->pc, regs->pr);
#endif
flush_cache_sigtramp(regs->pr); flush_cache_sigtramp(regs->pr);
if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode)) if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES); flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
return;
return 0;
give_sigsegv: give_sigsegv:
force_sigsegv(sig, current); force_sigsegv(sig, current);
return -EFAULT;
} }
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void static int
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs) sigset_t *oldset, struct pt_regs *regs)
{ {
int ret;
/* Are we from a system call? */ /* Are we from a system call? */
if (regs->tra >= 0) { if (regs->tra >= 0) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
...@@ -540,19 +506,23 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -540,19 +506,23 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up the stack frame */ /* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame(sig, ka, info, oldset, regs); ret = setup_rt_frame(sig, ka, info, oldset, regs);
else else
setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (ka->sa.sa_flags & SA_ONESHOT) if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL; ka->sa.sa_handler = SIG_DFL;
spin_lock_irq(&current->sighand->siglock); if (ret == 0) {
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); spin_lock_irq(&current->sighand->siglock);
if (!(ka->sa.sa_flags & SA_NODEFER)) sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
sigaddset(&current->blocked,sig); if (!(ka->sa.sa_flags & SA_NODEFER))
recalc_sigpending(); sigaddset(&current->blocked,sig);
spin_unlock_irq(&current->sighand->siglock); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
return ret;
} }
/* /*
...@@ -564,11 +534,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -564,11 +534,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
* the kernel can handle, and then we build all the user-level signal handling * the kernel can handle, and then we build all the user-level signal handling
* stack-frames in one go after that. * stack-frames in one go after that.
*/ */
int do_signal(struct pt_regs *regs, sigset_t *oldset, unsigned int save_r0) static void do_signal(struct pt_regs *regs, unsigned int save_r0)
{ {
siginfo_t info; siginfo_t info;
int signr; int signr;
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -577,19 +548,27 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, unsigned int save_r0) ...@@ -577,19 +548,27 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, unsigned int save_r0)
* if so. * if so.
*/ */
if (!user_mode(regs)) if (!user_mode(regs))
return 1; return;
if (try_to_freeze()) if (try_to_freeze())
goto no_signal; goto no_signal;
if (!oldset) if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &ka, &info, oldset, regs); if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
return 1; /* 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);
}
} }
no_signal: no_signal:
...@@ -606,5 +585,19 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, unsigned int save_r0) ...@@ -606,5 +585,19 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, unsigned int save_r0)
regs->regs[3] = __NR_restart_syscall; regs->regs[3] = __NR_restart_syscall;
} }
} }
return 0;
/* 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);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
}
asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0,
__u32 thread_info_flags)
{
/* deal with pending signal delivery */
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
do_signal(regs, save_r0);
} }
...@@ -319,34 +319,35 @@ ENTRY(sys_call_table) ...@@ -319,34 +319,35 @@ ENTRY(sys_call_table)
.long sys_mq_getsetattr .long sys_mq_getsetattr
.long sys_kexec_load .long sys_kexec_load
.long sys_waitid .long sys_waitid
.long sys_add_key /* 285 */ .long sys_ni_syscall /* 285 */
.long sys_add_key
.long sys_request_key .long sys_request_key
.long sys_keyctl .long sys_keyctl
.long sys_ioprio_set .long sys_ioprio_set
.long sys_ioprio_get .long sys_ioprio_get /* 290 */
.long sys_inotify_init /* 290 */ .long sys_inotify_init
.long sys_inotify_add_watch .long sys_inotify_add_watch
.long sys_inotify_rm_watch .long sys_inotify_rm_watch
.long sys_migrate_pages .long sys_migrate_pages
.long sys_openat .long sys_openat /* 295 */
.long sys_mkdirat /* 295 */ .long sys_mkdirat
.long sys_mknodat .long sys_mknodat
.long sys_fchownat .long sys_fchownat
.long sys_futimesat .long sys_futimesat
.long sys_fstatat64 .long sys_fstatat64 /* 300 */
.long sys_unlinkat /* 300 */ .long sys_unlinkat
.long sys_renameat .long sys_renameat
.long sys_linkat .long sys_linkat
.long sys_symlinkat .long sys_symlinkat
.long sys_readlinkat .long sys_readlinkat /* 305 */
.long sys_fchmodat /* 305 */ .long sys_fchmodat
.long sys_faccessat .long sys_faccessat
.long sys_ni_syscall /* Reserved for pselect6 */ .long sys_pselect6
.long sys_ni_syscall /* Reserved for ppoll */ .long sys_ppoll
.long sys_unshare .long sys_unshare /* 310 */
.long sys_set_robust_list /* 310 */ .long sys_set_robust_list
.long sys_get_robust_list .long sys_get_robust_list
.long sys_splice .long sys_splice
.long sys_sync_file_range .long sys_sync_file_range
.long sys_tee .long sys_tee /* 315 */
.long sys_vmsplice /* 315 */ .long sys_vmsplice
...@@ -94,6 +94,7 @@ static inline struct thread_info *current_thread_info(void) ...@@ -94,6 +94,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */ #define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
#define TIF_SIGPENDING 2 /* signal pending */ #define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_RESTORE_SIGMASK 4 /* restore signal mask in do_signal() */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 18 #define TIF_MEMDIE 18
...@@ -102,6 +103,7 @@ static inline struct thread_info *current_thread_info(void) ...@@ -102,6 +103,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#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_USEDFPU (1<<TIF_USEDFPU) #define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
......
...@@ -292,39 +292,40 @@ ...@@ -292,39 +292,40 @@
#define __NR_mq_getsetattr (__NR_mq_open+5) #define __NR_mq_getsetattr (__NR_mq_open+5)
#define __NR_kexec_load 283 #define __NR_kexec_load 283
#define __NR_waitid 284 #define __NR_waitid 284
#define __NR_add_key 285 /* #define __NR_sys_setaltroot 285 */
#define __NR_request_key 286 #define __NR_add_key 286
#define __NR_keyctl 287 #define __NR_request_key 287
#define __NR_ioprio_set 288 #define __NR_keyctl 288
#define __NR_ioprio_get 289 #define __NR_ioprio_set 289
#define __NR_inotify_init 290 #define __NR_ioprio_get 290
#define __NR_inotify_add_watch 291 #define __NR_inotify_init 291
#define __NR_inotify_rm_watch 292 #define __NR_inotify_add_watch 292
#define __NR_migrate_pages 293 #define __NR_inotify_rm_watch 293
#define __NR_openat 294 #define __NR_migrate_pages 294
#define __NR_mkdirat 295 #define __NR_openat 295
#define __NR_mknodat 296 #define __NR_mkdirat 296
#define __NR_fchownat 297 #define __NR_mknodat 297
#define __NR_futimesat 298 #define __NR_fchownat 298
#define __NR_fstatat64 299 #define __NR_futimesat 299
#define __NR_unlinkat 300 #define __NR_newfstatat 300
#define __NR_renameat 301 #define __NR_unlinkat 301
#define __NR_linkat 302 #define __NR_renameat 302
#define __NR_symlinkat 303 #define __NR_linkat 303
#define __NR_readlinkat 304 #define __NR_symlinkat 304
#define __NR_fchmodat 305 #define __NR_readlinkat 305
#define __NR_faccessat 305 #define __NR_fchmodat 306
#define __NR_pselect6 307 #define __NR_faccessat 307
#define __NR_ppoll 308 #define __NR_pselect6 308
#define __NR_unshare 309 #define __NR_ppoll 309
#define __NR_set_robust_list 310 #define __NR_unshare 310
#define __NR_get_robust_list 311 #define __NR_set_robust_list 311
#define __NR_splice 312 #define __NR_get_robust_list 312
#define __NR_sync_file_range 313 #define __NR_splice 313
#define __NR_tee 314 #define __NR_sync_file_range 314
#define __NR_vmsplice 315 #define __NR_tee 315
#define __NR_vmsplice 316
#define NR_syscalls 316 #define NR_syscalls 317
#ifdef __KERNEL__ #ifdef __KERNEL__
...@@ -466,6 +467,7 @@ __syscall_return(type,__sc0); \ ...@@ -466,6 +467,7 @@ __syscall_return(type,__sc0); \
#define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#ifdef __KERNEL_SYSCALLS__ #ifdef __KERNEL_SYSCALLS__
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册