Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f23e7e9 authored by Paul Mundt's avatar Paul Mundt
Browse files

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



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

Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent a2d1a5fa
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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:
+65 −72
Original line number Diff line number Diff line
@@ -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;
	}
	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",
	pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
		 current->comm, current->pid, frame, regs->pc, regs->pr);
#endif

	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",
	pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
		 current->comm, current->pid, frame, regs->pc, regs->pr);
#endif

	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,13 +506,14 @@ 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;

	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))
@@ -555,6 +522,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
		spin_unlock_irq(&current->sighand->siglock);
	}

	return ret;
}

/*
 * Note that 'init' is a special process: it doesn't get signals it doesn't
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
@@ -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);
}
+16 −15
Original line number Diff line number Diff line
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -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)

+34 −32
Original line number Diff line number Diff line
@@ -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__