diff options
author | davidxu <davidxu@FreeBSD.org> | 2005-10-14 12:43:47 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2005-10-14 12:43:47 +0000 |
commit | 3fbdb3c21524d9d95278ada1d61b4d1e6bee654b (patch) | |
tree | 95d82b1a11b0c187223f8ac12f020b19901fa750 /sys/i386/linux/linux_sysvec.c | |
parent | 6b2407fb7677ef2b8cef5c0925b3fe88a6ec7ca4 (diff) | |
download | FreeBSD-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.c | 36 |
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); } |