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

This implements support for ppoll() and pselect6()..

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
Paul Mundt 2006-09-27 17:27:00 +09:00
parent a2d1a5fae6
commit 9f23e7e94f
5 changed files with 121 additions and 123 deletions

View file

@ -371,12 +371,12 @@ work_pending:
! r8: current_thread_info
! t: result of "tst #_TIF_NEED_RESCHED, r0"
bf/s work_resched
tst #_TIF_SIGPENDING, r0
tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
work_notifysig:
bt/s restore_all
mov r15, r4
mov #0, r5
mov r12, r6 ! set arg2(save_r0)
mov r12, r5 ! set arg1(save_r0)
mov r0, r6
mov.l 2f, r1
mova restore_all, r0
jmp @r1
@ -414,7 +414,7 @@ work_resched:
.align 2
1: .long schedule
2: .long do_signal
2: .long do_notify_resume
.align 2
syscall_exit_work:

View file

@ -29,13 +29,10 @@
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
#define DEBUG_SIG 0
#undef DEBUG
#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.
*/
@ -44,51 +41,17 @@ sys_sigsuspend(old_sigset_t mask,
unsigned long r5, unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
sigset_t saveset;
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
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
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;
}
current->state = TASK_INTERRUPTIBLE;
schedule();
set_thread_flag(TIF_RESTORE_SIGMASK);
return -ERESTARTNOHAND;
}
asmlinkage int
@ -349,7 +312,7 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
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)
{
struct sigframe __user *frame;
@ -369,10 +332,9 @@ static void setup_frame(int sig, struct k_sigaction *ka,
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],
sizeof(frame->extramask));
}
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
@ -403,21 +365,22 @@ static void setup_frame(int sig, struct k_sigaction *ka,
set_fs(USER_DS);
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
current->comm, current->pid, frame, regs->pc, regs->pr);
#endif
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
current->comm, current->pid, frame, regs->pc, regs->pr);
flush_cache_sigtramp(regs->pr);
if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
return;
return 0;
give_sigsegv:
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)
{
struct rt_sigframe __user *frame;
@ -478,28 +441,31 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
set_fs(USER_DS);
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
current->comm, current->pid, frame, regs->pc, regs->pr);
#endif
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
current->comm, current->pid, frame, regs->pc, regs->pr);
flush_cache_sigtramp(regs->pr);
if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
return;
return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
}
/*
* OK, we're invoking a handler
*/
static void
static int
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs)
{
int ret;
/* Are we from a system call? */
if (regs->tra >= 0) {
/* If so, check system call restarting.. */
@ -540,19 +506,23 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up the stack frame */
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
setup_frame(sig, ka, oldset, regs);
ret = setup_frame(sig, ka, oldset, regs);
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
if (ret == 0) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
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,
* the kernel can handle, and then we build all the user-level signal handling
* 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;
int signr;
struct k_sigaction ka;
sigset_t *oldset;
/*
* 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)
* if so.
*/
if (!user_mode(regs))
return 1;
return;
if (try_to_freeze())
goto no_signal;
if (!oldset)
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
handle_signal(signr, &ka, &info, oldset, regs);
return 1;
if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
/* 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:
@ -606,5 +585,19 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, unsigned int save_r0)
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);
}

View file

@ -319,34 +319,35 @@ ENTRY(sys_call_table)
.long sys_mq_getsetattr
.long sys_kexec_load
.long sys_waitid
.long sys_add_key /* 285 */
.long sys_ni_syscall /* 285 */
.long sys_add_key
.long sys_request_key
.long sys_keyctl
.long sys_ioprio_set
.long sys_ioprio_get
.long sys_inotify_init /* 290 */
.long sys_ioprio_get /* 290 */
.long sys_inotify_init
.long sys_inotify_add_watch
.long sys_inotify_rm_watch
.long sys_migrate_pages
.long sys_openat
.long sys_mkdirat /* 295 */
.long sys_openat /* 295 */
.long sys_mkdirat
.long sys_mknodat
.long sys_fchownat
.long sys_futimesat
.long sys_fstatat64
.long sys_unlinkat /* 300 */
.long sys_fstatat64 /* 300 */
.long sys_unlinkat
.long sys_renameat
.long sys_linkat
.long sys_symlinkat
.long sys_readlinkat
.long sys_fchmodat /* 305 */
.long sys_readlinkat /* 305 */
.long sys_fchmodat
.long sys_faccessat
.long sys_ni_syscall /* Reserved for pselect6 */
.long sys_ni_syscall /* Reserved for ppoll */
.long sys_unshare
.long sys_set_robust_list /* 310 */
.long sys_pselect6
.long sys_ppoll
.long sys_unshare /* 310 */
.long sys_set_robust_list
.long sys_get_robust_list
.long sys_splice
.long sys_sync_file_range
.long sys_tee
.long sys_vmsplice /* 315 */
.long sys_tee /* 315 */
.long sys_vmsplice

View file

@ -94,6 +94,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
#define TIF_SIGPENDING 2 /* signal pending */
#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_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 18
@ -102,6 +103,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)

View file

@ -292,39 +292,40 @@
#define __NR_mq_getsetattr (__NR_mq_open+5)
#define __NR_kexec_load 283
#define __NR_waitid 284
#define __NR_add_key 285
#define __NR_request_key 286
#define __NR_keyctl 287
#define __NR_ioprio_set 288
#define __NR_ioprio_get 289
#define __NR_inotify_init 290
#define __NR_inotify_add_watch 291
#define __NR_inotify_rm_watch 292
#define __NR_migrate_pages 293
#define __NR_openat 294
#define __NR_mkdirat 295
#define __NR_mknodat 296
#define __NR_fchownat 297
#define __NR_futimesat 298
#define __NR_fstatat64 299
#define __NR_unlinkat 300
#define __NR_renameat 301
#define __NR_linkat 302
#define __NR_symlinkat 303
#define __NR_readlinkat 304
#define __NR_fchmodat 305
#define __NR_faccessat 305
#define __NR_pselect6 307
#define __NR_ppoll 308
#define __NR_unshare 309
#define __NR_set_robust_list 310
#define __NR_get_robust_list 311
#define __NR_splice 312
#define __NR_sync_file_range 313
#define __NR_tee 314
#define __NR_vmsplice 315
/* #define __NR_sys_setaltroot 285 */
#define __NR_add_key 286
#define __NR_request_key 287
#define __NR_keyctl 288
#define __NR_ioprio_set 289
#define __NR_ioprio_get 290
#define __NR_inotify_init 291
#define __NR_inotify_add_watch 292
#define __NR_inotify_rm_watch 293
#define __NR_migrate_pages 294
#define __NR_openat 295
#define __NR_mkdirat 296
#define __NR_mknodat 297
#define __NR_fchownat 298
#define __NR_futimesat 299
#define __NR_newfstatat 300
#define __NR_unlinkat 301
#define __NR_renameat 302
#define __NR_linkat 303
#define __NR_symlinkat 304
#define __NR_readlinkat 305
#define __NR_fchmodat 306
#define __NR_faccessat 307
#define __NR_pselect6 308
#define __NR_ppoll 309
#define __NR_unshare 310
#define __NR_set_robust_list 311
#define __NR_get_robust_list 312
#define __NR_splice 313
#define __NR_sync_file_range 314
#define __NR_tee 315
#define __NR_vmsplice 316
#define NR_syscalls 316
#define NR_syscalls 317
#ifdef __KERNEL__
@ -466,6 +467,7 @@ __syscall_return(type,__sc0); \
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#ifdef __KERNEL_SYSCALLS__