summaryrefslogtreecommitdiffstats
path: root/sys/i386/linux/linux_sysvec.c
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2005-10-14 12:43:47 +0000
committerdavidxu <davidxu@FreeBSD.org>2005-10-14 12:43:47 +0000
commit3fbdb3c21524d9d95278ada1d61b4d1e6bee654b (patch)
tree95d82b1a11b0c187223f8ac12f020b19901fa750 /sys/i386/linux/linux_sysvec.c
parent6b2407fb7677ef2b8cef5c0925b3fe88a6ec7ca4 (diff)
downloadFreeBSD-src-3fbdb3c21524d9d95278ada1d61b4d1e6bee654b.zip
FreeBSD-src-3fbdb3c21524d9d95278ada1d61b4d1e6bee654b.tar.gz
1. Change prototype of trapsignal and sendsig to use ksiginfo_t *, most
changes in MD code are trivial, before this change, trapsignal and sendsig use discrete parameters, now they uses member fields of ksiginfo_t structure. For sendsig, this change allows us to pass POSIX realtime signal value to user code. 2. Remove cpu_thread_siginfo, it is no longer needed because we now always generate ksiginfo_t data and feed it to libpthread. 3. Add p_sigqueue to proc structure to hold shared signals which were blocked by all threads in the proc. 4. Add td_sigqueue to thread structure to hold all signals delivered to thread. 5. i386 and amd64 now return POSIX standard si_code, other arches will be fixed. 6. In this sigqueue implementation, pending signal set is kept as before, an extra siginfo list holds additional siginfo_t data for signals. kernel code uses psignal() still behavior as before, it won't be failed even under memory pressure, only exception is when deleting a signal, we should call sigqueue_delete to remove signal from sigqueue but not SIGDELSET. Current there is no kernel code will deliver a signal with additional data, so kernel should be as stable as before, a ksiginfo can carry more information, for example, allow signal to be delivered but throw away siginfo data if memory is not enough. SIGKILL and SIGSTOP have fast path in sigqueue_add, because they can not be caught or masked. The sigqueue() syscall allows user code to queue a signal to target process, if resource is unavailable, EAGAIN will be returned as specification said. Just before thread exits, signal queue memory will be freed by sigqueue_flush. Current, all signals are allowed to be queued, not only realtime signals. Earlier patch reviewed by: jhb, deischen Tested on: i386, amd64
Diffstat (limited to 'sys/i386/linux/linux_sysvec.c')
-rw-r--r--sys/i386/linux/linux_sysvec.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index db1b617..8916183 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -107,8 +107,7 @@ static int elf_linux_fixup(register_t **stack_base,
struct image_params *iparams);
static void linux_prepsyscall(struct trapframe *tf, int *args, u_int *code,
caddr_t *params);
-static void linux_sendsig(sig_t catcher, int sig, sigset_t *mask,
- u_long code);
+static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
static void exec_linux_setregs(struct thread *td, u_long entry,
u_long stack, u_long ps_strings);
@@ -267,15 +266,18 @@ extern int _ucodesel, _udatasel;
extern unsigned long linux_sznonrtsigcode;
static void
-linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
+linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
struct sigacts *psp;
struct trapframe *regs;
struct l_rt_sigframe *fp, frame;
+ int sig, code;
int oonstack;
+ sig = ksi->ksi_signo;
+ code = ksi->ksi_code;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
mtx_assert(&psp->ps_mtx, MA_OWNED);
@@ -315,7 +317,7 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
/* Fill in POSIX parts */
frame.sf_si.lsi_signo = sig;
frame.sf_si.lsi_code = code;
- frame.sf_si.lsi_addr = (void *)regs->tf_err;
+ frame.sf_si.lsi_addr = ksi->ksi_addr;
/*
* Build the signal context to be used by sigreturn.
@@ -400,7 +402,7 @@ linux_rt_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
* specified pc, psl.
*/
static void
-linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
+linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct thread *td = curthread;
struct proc *p = td->td_proc;
@@ -408,17 +410,19 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
struct trapframe *regs;
struct l_sigframe *fp, frame;
l_sigset_t lmask;
+ int sig, code;
int oonstack, i;
PROC_LOCK_ASSERT(p, MA_OWNED);
psp = p->p_sigacts;
+ sig = ksi->ksi_signo;
+ code = ksi->ksi_code;
mtx_assert(&psp->ps_mtx, MA_OWNED);
if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
- linux_rt_sendsig(catcher, sig, mask, code);
+ linux_rt_sendsig(catcher, ksi, mask);
return;
}
-
regs = td->td_frame;
oonstack = sigonstack(regs->tf_esp);
@@ -475,7 +479,7 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
frame.sf_sc.sc_esp_at_signal = regs->tf_esp;
frame.sf_sc.sc_ss = regs->tf_ss;
frame.sf_sc.sc_err = regs->tf_err;
- frame.sf_sc.sc_trapno = bsd_to_linux_trapcode(code);
+ frame.sf_sc.sc_trapno = bsd_to_linux_trapcode(ksi->ksi_trapno);
for (i = 0; i < (LINUX_NSIG_WORDS-1); i++)
frame.sf_extramask[i] = lmask.__bits[i+1];
@@ -522,6 +526,7 @@ linux_sigreturn(struct thread *td, struct linux_sigreturn_args *args)
struct trapframe *regs;
l_sigset_t lmask;
int eflags, i;
+ ksiginfo_t ksi;
regs = td->td_frame;
@@ -562,7 +567,12 @@ linux_sigreturn(struct thread *td, struct linux_sigreturn_args *args)
*/
#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
if (!CS_SECURE(frame.sf_sc.sc_cs)) {
- trapsignal(td, SIGBUS, T_PROTFLT);
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGBUS;
+ ksi.ksi_code = BUS_OBJERR;
+ ksi.ksi_trapno = T_PROTFLT;
+ ksi.ksi_addr = (void *)regs->tf_eip;
+ trapsignal(td, &ksi);
return(EINVAL);
}
@@ -618,6 +628,7 @@ linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args)
stack_t ss;
struct trapframe *regs;
int eflags;
+ ksiginfo_t ksi;
regs = td->td_frame;
@@ -660,7 +671,12 @@ linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args)
*/
#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
if (!CS_SECURE(context->sc_cs)) {
- trapsignal(td, SIGBUS, T_PROTFLT);
+ ksiginfo_init_trap(&ksi);
+ ksi.ksi_signo = SIGBUS;
+ ksi.ksi_code = BUS_OBJERR;
+ ksi.ksi_trapno = T_PROTFLT;
+ ksi.ksi_addr = (void *)regs->tf_eip;
+ trapsignal(td, &ksi);
return(EINVAL);
}
OpenPOWER on IntegriCloud