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

Commit 7b3e2fc8 authored by Ralf Baechle's avatar Ralf Baechle
Browse files

[MIPS] Add support for TIF_RESTORE_SIGMASK.


    
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>

---
parent ac171c46
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -58,8 +58,8 @@ ATTRIB_NORET void cpu_idle(void)
	}
}

extern int do_signal(sigset_t *oldset, struct pt_regs *regs);
extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
extern int do_signal(struct pt_regs *regs);
extern int do_signal32(struct pt_regs *regs);

/*
 * Native o32 and N64 ABI without DSP ASE
+50 −36
Original line number Diff line number Diff line
@@ -39,8 +39,6 @@

#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))

int do_signal(sigset_t *oldset, struct pt_regs *regs);

/*
 * Atomically swap in the new signal mask, and wait for a signal.
 */
@@ -50,7 +48,7 @@ save_static_function(sys_sigsuspend);
__attribute_used__ noinline static int
_sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
{
	sigset_t saveset, newset;
	sigset_t newset;
	sigset_t __user *uset;

	uset = (sigset_t __user *) regs.regs[4];
@@ -59,19 +57,15 @@ _sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
	sigdelsetmask(&newset, ~_BLOCKABLE);

	spin_lock_irq(&current->sighand->siglock);
	saveset = current->blocked;
	current->saved_sigmask = current->blocked;
	current->blocked = newset;
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);

	regs.regs[2] = EINTR;
	regs.regs[7] = 1;
	while (1) {
	current->state = TASK_INTERRUPTIBLE;
	schedule();
		if (do_signal(&saveset, &regs))
			return -EINTR;
	}
	set_thread_flag(TIF_RESTORE_SIGMASK);
	return -ERESTARTNOHAND;
}
#endif

@@ -79,7 +73,7 @@ save_static_function(sys_rt_sigsuspend);
__attribute_used__ noinline static int
_sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
{
	sigset_t saveset, newset;
	sigset_t newset;
	sigset_t __user *unewset;
	size_t sigsetsize;

@@ -94,19 +88,15 @@ _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
	sigdelsetmask(&newset, ~_BLOCKABLE);

	spin_lock_irq(&current->sighand->siglock);
	saveset = current->blocked;
	current->saved_sigmask = current->blocked;
	current->blocked = newset;
        recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);

	regs.regs[2] = EINTR;
	regs.regs[7] = 1;
	while (1) {
	current->state = TASK_INTERRUPTIBLE;
	schedule();
		if (do_signal(&saveset, &regs))
			return -EINTR;
	}
	set_thread_flag(TIF_RESTORE_SIGMASK);
	return -ERESTARTNOHAND;
}

#ifdef CONFIG_TRAD_SIGNALS
@@ -315,11 +305,11 @@ int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
	       current->comm, current->pid,
	       frame, regs->cp0_epc, frame->regs[31]);
#endif
        return 1;
        return 0;

give_sigsegv:
	force_sigsegv(signr, current);
	return 0;
	return -EFAULT;
}
#endif

@@ -375,11 +365,11 @@ int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
	       current->comm, current->pid,
	       frame, regs->cp0_epc, regs->regs[31]);
#endif
	return 1;
	return 0;

give_sigsegv:
	force_sigsegv(signr, current);
	return 0;
	return -EFAULT;
}

static inline int handle_signal(unsigned long sig, siginfo_t *info,
@@ -420,9 +410,10 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info,
	return ret;
}

int do_signal(sigset_t *oldset, struct pt_regs *regs)
int do_signal(struct pt_regs *regs)
{
	struct k_sigaction ka;
	sigset_t *oldset;
	siginfo_t info;
	int signr;

@@ -437,12 +428,26 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
	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)
		return handle_signal(signr, &info, &ka, oldset, regs);
	if (signr > 0) {
		/* Whee!  Actually deliver the signal.  */
		if (handle_signal(signr, &info, &ka, 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:
	/*
@@ -463,18 +468,27 @@ no_signal:
			regs->cp0_epc -= 4;
		}
	}

	/*
	 * 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);
	}

	return 0;
}

/*
 * notification of userspace execution resumption
 * - triggered by current->work.notify_resume
 * - triggered by the TIF_WORK_MASK flags
 */
asmlinkage void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
	__u32 thread_info_flags)
{
	/* deal with pending signal delivery */
	if (thread_info_flags & _TIF_SIGPENDING) {
		current->thread.abi->do_signal(oldset, regs);
	}
	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
		current->thread.abi->do_signal(regs);
}
+4 −4
Original line number Diff line number Diff line
@@ -694,11 +694,11 @@ int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
	       current->comm, current->pid,
	       frame, regs->cp0_epc, frame->sf_code);
#endif
	return 1;
	return 0;

give_sigsegv:
	force_sigsegv(signr, current);
	return 0;
	return -EFAULT;
}

int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
@@ -765,11 +765,11 @@ int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
	       current->comm, current->pid,
	       frame, regs->cp0_epc, frame->rs_code);
#endif
	return 1;
	return 0;

give_sigsegv:
	force_sigsegv(signr, current);
	return 0;
	return -EFAULT;
}

static inline int handle_signal(unsigned long sig, siginfo_t *info,
+2 −2
Original line number Diff line number Diff line
@@ -186,9 +186,9 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
	       current->comm, current->pid,
	       frame, regs->cp0_epc, regs->regs[31]);
#endif
	return 1;
	return 0;

give_sigsegv:
	force_sigsegv(signr, current);
	return 0;
	return -EFAULT;
}
+2 −2
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2005 by Ralf Baechle
 * Copyright (C) 2005, 06 by Ralf Baechle (ralf@linux-mips.org)
 * Copyright (C) 2005 MIPS Technologies, Inc.
 */
#ifndef _ASM_ABI_H
@@ -13,7 +13,7 @@
#include <asm/siginfo.h>

struct mips_abi {
	int (* const do_signal)(sigset_t *oldset, struct pt_regs *regs);
	int (* const do_signal)(struct pt_regs *regs);
	int (* const setup_frame)(struct k_sigaction * ka,
	                          struct pt_regs *regs, int signr,
	                          sigset_t *set);
Loading