? alpha/alpha/1 ? kern/s.diff ? kern/sched_ule.c.patched ? sys/itimerspec.h ? sys/posix-timer.h ? sys/signal.h.save Index: alpha/alpha/machdep.c =================================================================== RCS file: /home/ncvs/src/sys/alpha/alpha/machdep.c,v retrieving revision 1.235 diff -u -r1.235 machdep.c --- alpha/alpha/machdep.c 4 Apr 2005 21:53:51 -0000 1.235 +++ alpha/alpha/machdep.c 11 Oct 2005 06:33:47 -0000 @@ -211,11 +211,10 @@ #define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(vm_offset_t)) - 2) #ifdef COMPAT_43 -void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code); +void osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); #endif #ifdef COMPAT_FREEBSD4 -static void freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, - u_long code); +static void freebsd4_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); #endif static void get_fpcontext(struct thread *td, mcontext_t *mcp); @@ -1107,7 +1106,7 @@ */ #ifdef COMPAT_43 void -osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +osendsig(sig_t catcher, ksiginfo_t *kp, sigset_t *mask) { struct proc *p; struct thread *td; @@ -1115,10 +1114,14 @@ struct trapframe *frame; struct sigacts *psp; int oonstack, fsize, rndfsize; + int sig; + int code; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + sig = kp->ksi_signo; + code = kp->ksi_code; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); @@ -1177,7 +1180,7 @@ /* Fill in POSIX parts */ ksi.si_signo = sig; ksi.si_code = code; - ksi.si_value.sigval_ptr = NULL; /* XXX */ + ksi.si_value = kp->ksi_value; /* * copy the frame out to userland. @@ -1212,7 +1215,7 @@ #ifdef COMPAT_FREEBSD4 static void -freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +freebsd4_sendsig(sig_t catcher, ksiginfo_t *kp, sigset_t *mask) { struct proc *p; struct thread *td; @@ -1220,10 +1223,14 @@ struct sigacts *psp; struct sigframe4 sf, *sfp; int oonstack, rndfsize; + int sig; + int code; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + sig = kp->ksi_signo; + code = kp->ksi_code; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); @@ -1308,9 +1315,7 @@ frame->tf_regs[FRAME_A1] = (u_int64_t)&(sfp->sf_si); /* Fill in POSIX parts */ - sf.sf_si.si_signo = sig; - sf.sf_si.si_code = code; - sf.sf_si.si_addr = (void*)frame->tf_regs[FRAME_TRAPARG_A0]; + sf.sf_si = kp->ksi_info; } else frame->tf_regs[FRAME_A1] = code; @@ -1323,7 +1328,7 @@ #endif /* COMPAT_FREEBSD4 */ void -sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +sendsig(sig_t catcher, ksiginfo_t *kp, sigset_t *mask) { struct proc *p; struct thread *td; @@ -1331,21 +1336,25 @@ struct sigacts *psp; struct sigframe sf, *sfp; int oonstack, rndfsize; + int sig; + int code; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + sig = kp->ksi_signo; + code = kp->ksi_code; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); #ifdef COMPAT_FREEBSD4 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { - freebsd4_sendsig(catcher, sig, mask, code); + freebsd4_sendsig(catcher, kp, mask); return; } #endif #ifdef COMPAT_43 if (SIGISMEMBER(psp->ps_osigset, sig)) { - osendsig(catcher, sig, mask, code); + osendsig(catcher, kp, mask); return; } #endif @@ -1432,9 +1441,7 @@ frame->tf_regs[FRAME_A1] = (u_int64_t)&(sfp->sf_si); /* Fill in POSIX parts */ - sf.sf_si.si_signo = sig; - sf.sf_si.si_code = code; - sf.sf_si.si_addr = (void*)frame->tf_regs[FRAME_TRAPARG_A0]; + sf.sf_si = kp->ksi_info; } else frame->tf_regs[FRAME_A1] = code; @@ -1446,25 +1453,6 @@ } /* - * Build siginfo_t for SA thread - */ -void -cpu_thread_siginfo(int sig, u_long code, siginfo_t *si) -{ - struct proc *p; - struct thread *td; - - td = curthread; - p = td->td_proc; - PROC_LOCK_ASSERT(p, MA_OWNED); - - bzero(si, sizeof(*si)); - si->si_signo = sig; - si->si_code = code; - /* XXXKSE fill other fields */ -} - -/* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). Index: alpha/alpha/trap.c =================================================================== RCS file: /home/ncvs/src/sys/alpha/alpha/trap.c,v retrieving revision 1.125 diff -u -r1.125 trap.c --- alpha/alpha/trap.c 28 Sep 2005 07:03:01 -0000 1.125 +++ alpha/alpha/trap.c 11 Oct 2005 06:33:49 -0000 @@ -264,6 +264,7 @@ #ifdef SMP register_t s; #endif + ksiginfo_t ksi; /* * Find our per-cpu globals. @@ -585,7 +586,12 @@ framep->tf_regs[FRAME_TRAPARG_A0] = a0; framep->tf_regs[FRAME_TRAPARG_A1] = a1; framep->tf_regs[FRAME_TRAPARG_A2] = a2; - trapsignal(td, i, ucode); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = i; + ksi.ksi_code = ucode; + ksi.ksi_addr = (void *)a0; + trapsignal(td, &ksi); + out: if (user) { framep->tf_regs[FRAME_SP] = alpha_pal_rdusp(); Index: alpha/linux/linux_sysvec.c =================================================================== RCS file: /home/ncvs/src/sys/alpha/linux/linux_sysvec.c,v retrieving revision 1.95 diff -u -r1.95 linux_sysvec.c --- alpha/linux/linux_sysvec.c 29 Jul 2005 19:40:38 -0000 1.95 +++ alpha/linux/linux_sysvec.c 11 Oct 2005 06:33:49 -0000 @@ -77,7 +77,7 @@ SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); -void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code); +void osendsig(sig_t catcher, ksiginfo_t *kp, sigset_t *mask); static int elf_linux_fixup(register_t **stack_base, struct image_params *iparams); Index: alpha/osf1/osf1_signal.c =================================================================== RCS file: /home/ncvs/src/sys/alpha/osf1/osf1_signal.c,v retrieving revision 1.42 diff -u -r1.42 osf1_signal.c --- alpha/osf1/osf1_signal.c 28 Sep 2005 07:03:01 -0000 1.42 +++ alpha/osf1/osf1_signal.c 11 Oct 2005 06:33:49 -0000 @@ -459,7 +459,7 @@ */ void -osf1_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +osf1_sendsig(sig_t catcher, ksiginfo_t *kp, sigset_t *mask) { int fsize, oonstack, rndfsize; struct thread *td; @@ -467,10 +467,14 @@ osiginfo_t *sip, ksi; struct trapframe *frame; struct sigacts *psp; + int sig; + int code; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + sig = kp->ksi_signo; + code = kp->ksi_code; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); @@ -526,7 +530,7 @@ /* Fill in POSIX parts */ ksi.si_signo = sig; ksi.si_code = code; - ksi.si_value.sigval_ptr = NULL; /* XXX */ + ksi.si_value = kp->ksi_value; /* * copy the frame out to userland. Index: alpha/osf1/osf1_signal.h =================================================================== RCS file: /home/ncvs/src/sys/alpha/osf1/osf1_signal.h,v retrieving revision 1.3 diff -u -r1.3 osf1_signal.h --- alpha/osf1/osf1_signal.h 20 Mar 2002 18:58:46 -0000 1.3 +++ alpha/osf1/osf1_signal.h 11 Oct 2005 06:33:49 -0000 @@ -61,7 +61,7 @@ void bsd_to_osf1_sigset(const sigset_t *, osf1_sigset_t *); void osf1_to_bsd_sigaltstack(const struct osf1_sigaltstack *, struct sigaltstack *); void osf1_to_bsd_sigset(const osf1_sigset_t *, sigset_t *); -void osf1_sendsig(sig_t, int , sigset_t *, u_long ); +void osf1_sendsig(sig_t, struct ksiginfo *, sigset_t *); #endif /* !_OSF1_SIGNAL_H */ Index: amd64/amd64/machdep.c =================================================================== RCS file: /home/ncvs/src/sys/amd64/amd64/machdep.c,v retrieving revision 1.640 diff -u -r1.640 machdep.c --- amd64/amd64/machdep.c 27 Sep 2005 18:15:57 -0000 1.640 +++ amd64/amd64/machdep.c 11 Oct 2005 06:33:50 -0000 @@ -237,11 +237,7 @@ * specified pc, psl. */ void -sendsig(catcher, sig, mask, code) - sig_t catcher; - int sig; - sigset_t *mask; - u_long code; +sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct sigframe sf, *sfp; struct proc *p; @@ -250,10 +246,12 @@ char *sp; struct trapframe *regs; int oonstack; + int sig; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + sig = ksi->ksi_signo; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; @@ -297,13 +295,13 @@ sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; /* Fill in POSIX parts */ + sf.sf_si = ksi->ksi_info; sf.sf_si.si_signo = sig; - sf.sf_si.si_code = code; - regs->tf_rcx = regs->tf_addr; /* arg 4 in %rcx */ + regs->tf_rcx = (register_t)ksi->ksi_addr; /* arg 4 in %rcx */ } else { /* Old FreeBSD-style arguments. */ - regs->tf_rsi = code; /* arg 2 in %rsi */ - regs->tf_rcx = regs->tf_addr; /* arg 4 in %rcx */ + regs->tf_rsi = ksi->ksi_code; /* arg 2 in %rsi */ + regs->tf_rcx = (register_t)ksi->ksi_addr; /* arg 4 in %rcx */ sf.sf_ahu.sf_handler = catcher; } mtx_unlock(&psp->ps_mtx); @@ -329,28 +327,6 @@ } /* - * Build siginfo_t for SA thread - */ -void -cpu_thread_siginfo(int sig, u_long code, siginfo_t *si) -{ - struct proc *p; - struct thread *td; - struct trapframe *regs; - - td = curthread; - p = td->td_proc; - regs = td->td_frame; - PROC_LOCK_ASSERT(p, MA_OWNED); - - bzero(si, sizeof(*si)); - si->si_signo = sig; - si->si_code = code; - si->si_addr = (void *)regs->tf_addr; - /* XXXKSE fill other fields */ -} - -/* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). @@ -374,6 +350,7 @@ const ucontext_t *ucp; long rflags; int cs, error, ret; + ksiginfo_t ksi; error = copyin(uap->sigcntxp, &uc, sizeof(uc)); if (error != 0) @@ -407,7 +384,12 @@ cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { printf("sigreturn: cs = 0x%x\n", cs); - trapsignal(td, SIGBUS, T_PROTFLT); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_code = BUS_OBJERR; + ksi.ksi_trap = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_rip; + trapsignal(td, &ksi); return (EINVAL); } Index: amd64/amd64/trap.c =================================================================== RCS file: /home/ncvs/src/sys/amd64/amd64/trap.c,v retrieving revision 1.294 diff -u -r1.294 trap.c --- amd64/amd64/trap.c 1 Oct 2005 18:56:16 -0000 1.294 +++ amd64/amd64/trap.c 11 Oct 2005 06:33:50 -0000 @@ -161,6 +161,8 @@ struct proc *p = td->td_proc; u_int sticks = 0; int i = 0, ucode = 0, type, code; + register_t addr = 0; + ksiginfo_t ksi; PCPU_LAZY_INC(cnt.v_trap); type = frame.tf_trapno; @@ -241,13 +243,14 @@ sticks = td->td_sticks; td->td_frame = &frame; + addr = frame.tf_rip; if (td->td_ucred != p->p_ucred) cred_update_thread(td); switch (type) { case T_PRIVINFLT: /* privileged instruction fault */ - ucode = type; i = SIGILL; + ucode = ILL_PRVOPC; break; case T_BPTFLT: /* bpt instruction fault */ @@ -255,6 +258,7 @@ enable_intr(); frame.tf_rflags &= ~PSL_T; i = SIGTRAP; + ucode = (type == T_TRCTRAP ? TRAP_TRACE : TRAP_BRKPT); break; case T_ARITHTRAP: /* arithmetic trap */ @@ -265,16 +269,26 @@ break; case T_PROTFLT: /* general protection fault */ + i = SIGBUS; + ucode = BUS_OBJERR; + break; case T_STKFLT: /* stack fault */ case T_SEGNPFLT: /* segment not present fault */ + i = SIGBUS; + ucode = BUS_ADRERR; + break; case T_TSSFLT: /* invalid TSS fault */ + i = SIGBUS; + ucode = BUS_OBJERR; + break; case T_DOUBLEFLT: /* double fault */ default: - ucode = code + BUS_SEGM_FAULT ; i = SIGBUS; + ucode = BUS_RESERVED; break; case T_PAGEFLT: /* page fault */ + addr = frame.tf_addr; if (td->td_pflags & TDP_SA) thread_user_enter(td); i = trap_pfault(&frame, TRUE); @@ -283,7 +297,12 @@ if (i == 0) goto user; - ucode = T_PAGEFLT; + if (i == SIGSEGV) + ucode = SEGV_MAPERR; + else { + i = SIGSEGV; /* XXX hack */ + ucode = SEGV_ACCERR; + } break; case T_DIVIDE: /* integer divide fault */ @@ -331,7 +350,7 @@ break; case T_FPOPFLT: /* FPU operand fetch fault */ - ucode = T_FPOPFLT; + ucode = ILL_COPROC; i = SIGILL; break; @@ -472,7 +491,12 @@ if (*p->p_sysent->sv_transtrap) i = (*p->p_sysent->sv_transtrap)(i, type); - trapsignal(td, i, ucode); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = i; + ksi.ksi_code = ucode; + ksi.ksi_trap = type; + ksi.ksi_addr = (void *)addr; + trapsignal(td, &ksi); #ifdef DEBUG if (type <= MAX_TRAP_MSG) { @@ -689,6 +713,7 @@ struct thread *td = curthread; struct proc *p = td->td_proc; register_t orig_tf_rflags; + register_t orig_tf_rip; u_int sticks; int error; int narg; @@ -696,6 +721,7 @@ register_t *argp; u_int code; int reg, regcnt; + ksiginfo_t ksi; /* * note: PCPU_LAZY_INC() can only be used if we can afford @@ -723,6 +749,7 @@ params = (caddr_t)frame.tf_rsp + sizeof(register_t); code = frame.tf_rax; orig_tf_rflags = frame.tf_rflags; + orig_tf_rip = frame.tf_rip; if (p->p_sysent->sv_prepsyscall) { /* @@ -826,7 +853,12 @@ */ if (orig_tf_rflags & PSL_T) { frame.tf_rflags &= ~PSL_T; - trapsignal(td, SIGTRAP, 0); + + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGTRAP; + ksi.ksi_code = TRAP_TRACE; + ksi.ksi_addr = (void *)orig_tf_rip; + trapsignal(td, &ksi); } /* Index: amd64/ia32/ia32_signal.c =================================================================== RCS file: /home/ncvs/src/sys/amd64/ia32/ia32_signal.c,v retrieving revision 1.11 diff -u -r1.11 ia32_signal.c --- amd64/ia32/ia32_signal.c 27 Sep 2005 18:04:20 -0000 1.11 +++ amd64/ia32/ia32_signal.c 11 Oct 2005 06:33:51 -0000 @@ -79,7 +79,7 @@ #include #ifdef COMPAT_FREEBSD4 -static void freebsd4_ia32_sendsig(sig_t, int, sigset_t *, u_long); +static void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *); #endif static void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp); static int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp); @@ -295,18 +295,23 @@ */ #ifdef COMPAT_FREEBSD4 static void -freebsd4_ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct ia32_sigframe4 sf, *sfp; + struct ia32_siginfo siginfo; struct proc *p; struct thread *td; struct sigacts *psp; struct trapframe *regs; int oonstack; + int sig; td = curthread; p = td->td_proc; + siginfo_to_ia32siginfo(&ksi->ksi_info, &siginfo); + PROC_LOCK_ASSERT(p, MA_OWNED); + sig = siginfo.si_signo; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; @@ -362,13 +367,12 @@ sf.sf_ah = (u_int32_t)(uintptr_t)catcher; /* Fill in POSIX parts */ + sf.sf_si = siginfo; sf.sf_si.si_signo = sig; - sf.sf_si.si_code = code; - sf.sf_si.si_addr = regs->tf_addr; } else { /* Old FreeBSD-style arguments. */ - sf.sf_siginfo = code; - sf.sf_addr = regs->tf_addr; + sf.sf_siginfo = siginfo.si_code; + sf.sf_addr = (u_int32_t)siginfo.si_addr; sf.sf_ah = (u_int32_t)(uintptr_t)catcher; } mtx_unlock(&psp->ps_mtx); @@ -400,23 +404,27 @@ #endif /* COMPAT_FREEBSD4 */ void -ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct ia32_sigframe sf, *sfp; + struct ia32_siginfo siginfo; struct proc *p; struct thread *td; struct sigacts *psp; char *sp; struct trapframe *regs; int oonstack; + int sig; + siginfo_to_ia32siginfo(&ksi->ksi_info, &siginfo); td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + sig = siginfo.si_signo; psp = p->p_sigacts; #ifdef COMPAT_FREEBSD4 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { - freebsd4_ia32_sendsig(catcher, sig, mask, code); + freebsd4_ia32_sendsig(catcher, ksi, mask); return; } #endif @@ -479,13 +487,12 @@ sf.sf_ah = (u_int32_t)(uintptr_t)catcher; /* Fill in POSIX parts */ + sf.sf_si = siginfo; sf.sf_si.si_signo = sig; - sf.sf_si.si_code = code; - sf.sf_si.si_addr = regs->tf_addr; } else { /* Old FreeBSD-style arguments. */ - sf.sf_siginfo = code; - sf.sf_addr = regs->tf_addr; + sf.sf_siginfo = siginfo.si_code; + sf.sf_addr = (u_int32_t)siginfo.si_addr; sf.sf_ah = (u_int32_t)(uintptr_t)catcher; } mtx_unlock(&psp->ps_mtx); @@ -540,6 +547,7 @@ struct trapframe *regs; const struct ia32_ucontext4 *ucp; int cs, eflags, error; + ksiginfo_t ksi; error = copyin(uap->sigcntxp, &uc, sizeof(uc)); if (error != 0) @@ -573,7 +581,12 @@ cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { printf("freebsd4_sigreturn: cs = 0x%x\n", cs); - trapsignal(td, SIGBUS, T_PROTFLT); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_code = BUS_OBJERR; + ksi.ksi_trap = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_rip; + trapsignal(td, &ksi); return (EINVAL); } @@ -617,6 +630,7 @@ struct trapframe *regs; const struct ia32_ucontext *ucp; int cs, eflags, error, ret; + ksiginfo_t ksi; error = copyin(uap->sigcntxp, &uc, sizeof(uc)); if (error != 0) @@ -650,7 +664,12 @@ cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { printf("sigreturn: cs = 0x%x\n", cs); - trapsignal(td, SIGBUS, T_PROTFLT); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_code = BUS_OBJERR; + ksi.ksi_trap = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_rip; + trapsignal(td, &ksi); return (EINVAL); } @@ -722,3 +741,18 @@ pcb->pcb_flags |= PCB_FULLCTX; td->td_retval[1] = 0; } + +void +siginfo_to_ia32siginfo(siginfo_t *src, struct ia32_siginfo *dst) +{ + dst->si_signo = src->si_signo; + dst->si_errno = src->si_errno; + dst->si_code = src->si_code; + dst->si_pid = src->si_pid; + dst->si_uid = src->si_uid; + dst->si_status = src->si_status; + dst->si_addr = dst->si_addr; + dst->si_value.sigval_int = src->si_value.sigval_int; + dst->si_band = src->si_band; + dst->__spare__[0] = src->si_trap; +} Index: amd64/ia32/ia32_syscall.c =================================================================== RCS file: /home/ncvs/src/sys/amd64/ia32/ia32_syscall.c,v retrieving revision 1.8 diff -u -r1.8 ia32_syscall.c --- amd64/ia32/ia32_syscall.c 12 Apr 2005 23:18:53 -0000 1.8 +++ amd64/ia32/ia32_syscall.c 11 Oct 2005 06:33:51 -0000 @@ -95,12 +95,14 @@ struct thread *td = curthread; struct proc *p = td->td_proc; register_t orig_tf_rflags; + register_t orig_tf_rip; u_int sticks; int error; int narg; u_int32_t args[8]; u_int64_t args64[8]; u_int code; + ksiginfo_t ksi; /* * note: PCPU_LAZY_INC() can only be used if we can afford @@ -115,6 +117,7 @@ params = (caddr_t)frame.tf_rsp + sizeof(u_int32_t); code = frame.tf_rax; orig_tf_rflags = frame.tf_rflags; + orig_tf_rip = frame.tf_rip; if (p->p_sysent->sv_prepsyscall) { /* @@ -227,7 +230,11 @@ */ if (orig_tf_rflags & PSL_T) { frame.tf_rflags &= ~PSL_T; - trapsignal(td, SIGTRAP, 0); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGTRAP; + ksi.ksi_code = TRAP_TRACE; + ksi.ksi_addr = (void *)orig_tf_rip; + trapsignal(td, &ksi); } /* Index: amd64/linux32/linux32_sysvec.c =================================================================== RCS file: /home/ncvs/src/sys/amd64/linux32/linux32_sysvec.c,v retrieving revision 1.9 diff -u -r1.9 linux32_sysvec.c --- amd64/linux32/linux32_sysvec.c 22 Sep 2005 15:46:21 -0000 1.9 +++ amd64/linux32/linux32_sysvec.c 11 Oct 2005 06:33:52 -0000 @@ -120,8 +120,7 @@ static register_t *linux_copyout_strings(struct image_params *imgp); 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); static void linux32_fixlimits(struct image_params *imgp); @@ -275,7 +274,7 @@ 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; @@ -283,7 +282,11 @@ struct trapframe *regs; struct l_rt_sigframe *fp, frame; int oonstack; - + int sig; + int code; + + 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); @@ -323,7 +326,7 @@ /* Fill in POSIX parts */ frame.sf_si.lsi_signo = sig; frame.sf_si.lsi_code = code; - frame.sf_si.lsi_addr = PTROUT(regs->tf_err); + frame.sf_si.lsi_addr = PTROUT(ksi->ksi_addr); /* * Build the signal context to be used by sigreturn. @@ -411,7 +414,7 @@ * 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; @@ -420,13 +423,16 @@ struct l_sigframe *fp, frame; l_sigset_t lmask; int oonstack, i; + int sig, code; + 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); 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; } @@ -534,6 +540,7 @@ struct trapframe *regs; l_sigset_t lmask; int eflags, i; + ksiginfo_t ksi; regs = td->td_frame; @@ -574,7 +581,12 @@ */ #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_trap = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_rip; + trapsignal(td, &ksi); return(EINVAL); } @@ -627,6 +639,7 @@ stack_t ss; struct trapframe *regs; int eflags; + ksiginfo_t ksi; regs = td->td_frame; @@ -669,7 +682,12 @@ */ #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_trap = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_rip; + trapsignal(td, &ksi); return(EINVAL); } Index: arm/arm/machdep.c =================================================================== RCS file: /home/ncvs/src/sys/arm/arm/machdep.c,v retrieving revision 1.17 diff -u -r1.17 machdep.c --- arm/arm/machdep.c 3 Oct 2005 14:17:45 -0000 1.17 +++ arm/arm/machdep.c 11 Oct 2005 06:33:52 -0000 @@ -101,11 +101,10 @@ int _min_bzero_size = 0; void -sendsig(catcher, sig, mask, code) +sendsig(catcher, ksi, mask) sig_t catcher; - int sig; + ksiginfo_t *ksi; sigset_t *mask; - u_long code; { struct thread *td = curthread; struct proc *p = td->td_proc; @@ -113,6 +112,8 @@ struct sigframe *fp, frame; struct sigacts *psp = td->td_proc->p_sigacts; int onstack; + int sig; + int code; onstack = sigonstack(td->td_frame->tf_usr_sp); @@ -130,8 +131,7 @@ /* make the stack aligned */ fp = (struct sigframe *)STACKALIGN(fp); /* Populate the siginfo frame. */ - frame.sf_si.si_signo = sig; - frame.sf_si.si_code = code; + frame.sf_si = ksi->ksi_info; frame.sf_uc.uc_sigmask = *mask; frame.sf_uc.uc_link = NULL; frame.sf_uc.uc_flags = (td->td_pflags & TDP_ALTSTACK ) @@ -436,17 +436,6 @@ } /* - * Build siginfo_t for SA thread - */ -void -cpu_thread_siginfo(int sig, u_long code, siginfo_t *si) -{ - bzero(si, sizeof(*si)); - si->si_signo = sig; - si->si_code = code; -} - -/* * Get machine context. */ int Index: arm/arm/trap.c =================================================================== RCS file: /home/ncvs/src/sys/arm/arm/trap.c,v retrieving revision 1.17 diff -u -r1.17 trap.c --- arm/arm/trap.c 23 Jun 2005 11:39:18 -0000 1.17 +++ arm/arm/trap.c 11 Oct 2005 06:33:52 -0000 @@ -184,8 +184,12 @@ static __inline void call_trapsignal(struct thread *td, int sig, u_long code) { + ksiginfo_t ksi; - trapsignal(td, sig, code); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = sig; + ksi.ksi_code = (int)code; + trapsignal(td, &ksi); } static __inline int @@ -875,7 +879,7 @@ nap = 4; break; default: - trapsignal(td, SIGILL, 0); + call_trapsignal(td, SIGILL, 0); userret(td, frame, td->td_sticks); return; } @@ -993,7 +997,7 @@ * don't take an alignment fault trying to read the opcode. */ if (__predict_false(((frame->tf_pc - INSN_SIZE) & 3) != 0)) { - trapsignal(td, SIGILL, 0); + call_trapsignal(td, SIGILL, 0); userret(td, frame, td->td_sticks); return; } Index: arm/arm/undefined.c =================================================================== RCS file: /home/ncvs/src/sys/arm/arm/undefined.c,v retrieving revision 1.8 diff -u -r1.8 undefined.c --- arm/arm/undefined.c 12 Apr 2005 23:18:53 -0000 1.8 +++ arm/arm/undefined.c 11 Oct 2005 06:33:52 -0000 @@ -134,11 +134,17 @@ gdb_trapper(u_int addr, u_int insn, struct trapframe *frame, int code) { struct thread *td; + ksiginfo_t ksi; + td = (curthread == NULL) ? &thread0 : curthread; if (insn == GDB_BREAKPOINT || insn == GDB5_BREAKPOINT) { if (code == FAULT_USER) { - trapsignal(td, SIGTRAP, 0); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGTRAP; + ksi.ksi_code = TRAP_BRKPT; + ksi.ksi_addr = (u_int32_t *)addr; + trapsignal(td, &ksi); return 0; } #if 0 @@ -179,6 +185,7 @@ #ifdef VERBOSE_ARM32 int s; #endif + ksiginfo_t ksi; /* Enable interrupts if they were enabled before the exception. */ if (!(frame->tf_spsr & I32_bit)) @@ -200,7 +207,11 @@ * don't take an alignment fault trying to read the opcode. */ if (__predict_false((fault_pc & 3) != 0)) { - trapsignal(td, SIGILL, 0); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGILL; + ksi.ksi_code = ILL_ILLADR; + ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc; + trapsignal(td, &ksi); userret(td, frame, 0); return; } @@ -256,7 +267,11 @@ if (uh == NULL && (fault_code & FAULT_USER)) { /* Fault has not been handled */ - trapsignal(td, SIGILL, 0); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGILL; + ksi.ksi_code = ILL_ILLOPC; + ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc; + trapsignal(td, &ksi); } if ((fault_code & FAULT_USER) == 0) { Index: compat/ia32/ia32_signal.h =================================================================== RCS file: /home/ncvs/src/sys/compat/ia32/ia32_signal.h,v retrieving revision 1.7 diff -u -r1.7 ia32_signal.h --- compat/ia32/ia32_signal.h 5 Apr 2005 22:41:49 -0000 1.7 +++ compat/ia32/ia32_signal.h 11 Oct 2005 06:33:52 -0000 @@ -203,6 +203,7 @@ extern char freebsd4_ia32_sigcode[]; extern int sz_ia32_sigcode; extern int sz_freebsd4_ia32_sigcode; -extern void ia32_sendsig(sig_t, int, sigset_t *, u_long); +extern void ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *); extern void ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings); +extern void siginfo_to_ia32siginfo(siginfo_t *src, struct ia32_siginfo *dst); Index: compat/linux/linux_misc.c =================================================================== RCS file: /home/ncvs/src/sys/compat/linux/linux_misc.c,v retrieving revision 1.170 diff -u -r1.170 linux_misc.c --- compat/linux/linux_misc.c 7 Jul 2005 19:17:55 -0000 1.170 +++ compat/linux/linux_misc.c 11 Oct 2005 06:33:53 -0000 @@ -862,7 +862,7 @@ p = td->td_proc; PROC_LOCK(p); - SIGDELSET(p->p_siglist, SIGCHLD); + sigqueue_delete(&p->p_sigqueue, SIGCHLD); PROC_UNLOCK(p); if (args->status) { Index: compat/svr4/svr4_signal.h =================================================================== RCS file: /home/ncvs/src/sys/compat/svr4/svr4_signal.h,v retrieving revision 1.11 diff -u -r1.11 svr4_signal.h --- compat/svr4/svr4_signal.h 25 Feb 2005 19:34:10 -0000 1.11 +++ compat/svr4/svr4_signal.h 11 Oct 2005 06:33:53 -0000 @@ -133,10 +133,12 @@ #define SVR4_MINSIGSTKSZ 8192 +struct ksiginfo; + void bsd_to_svr4_sigaltstack(const struct sigaltstack *, struct svr4_sigaltstack *); void bsd_to_svr4_sigset(const sigset_t *, svr4_sigset_t *); void svr4_to_bsd_sigaltstack(const struct svr4_sigaltstack *, struct sigaltstack *); void svr4_to_bsd_sigset(const svr4_sigset_t *, sigset_t *); -void svr4_sendsig(sig_t, int, sigset_t *, u_long); +void svr4_sendsig(sig_t, struct ksiginfo *, sigset_t *); #endif /* !_SVR4_SIGNAL_H_ */ Index: fs/procfs/procfs_ctl.c =================================================================== RCS file: /home/ncvs/src/sys/fs/procfs/procfs_ctl.c,v retrieving revision 1.53 diff -u -r1.53 procfs_ctl.c --- fs/procfs/procfs_ctl.c 6 Jan 2005 18:10:40 -0000 1.53 +++ fs/procfs/procfs_ctl.c 11 Oct 2005 06:33:56 -0000 @@ -215,7 +215,7 @@ p->p_flag &= ~P_TRACED; /* remove pending SIGTRAP, else the process will die */ - SIGDELSET(p->p_siglist, SIGTRAP); + sigqueue_delete_proc(p, SIGTRAP); PROC_UNLOCK(p); /* give process back to original parent */ Index: i386/i386/machdep.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/machdep.c,v retrieving revision 1.617 diff -u -r1.617 machdep.c --- i386/i386/machdep.c 13 Jul 2005 11:32:10 -0000 1.617 +++ i386/i386/machdep.c 11 Oct 2005 06:33:58 -0000 @@ -171,11 +171,10 @@ int cold = 1; #ifdef COMPAT_43 -static void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code); +static void osendsig(sig_t catcher, ksiginfo_t *, sigset_t *mask); #endif #ifdef COMPAT_FREEBSD4 -static void freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, - u_long code); +static void freebsd4_sendsig(sig_t catcher, ksiginfo_t *, sigset_t *mask); #endif long Maxmem = 0; @@ -261,22 +260,20 @@ */ #ifdef COMPAT_43 static void -osendsig(catcher, sig, mask, code) - sig_t catcher; - int sig; - sigset_t *mask; - u_long code; +osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct osigframe sf, *fp; struct proc *p; struct thread *td; struct sigacts *psp; struct trapframe *regs; + int sig; int oonstack; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + sig = ksi->ksi_signo; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; @@ -304,12 +301,12 @@ /* Signal handler installed with SA_SIGINFO. */ sf.sf_arg2 = (register_t)&fp->sf_siginfo; sf.sf_siginfo.si_signo = sig; - sf.sf_siginfo.si_code = code; + sf.sf_siginfo.si_code = ksi->ksi_code; sf.sf_ahu.sf_action = (__osiginfohandler_t *)catcher; } else { /* Old FreeBSD-style arguments. */ - sf.sf_arg2 = code; - sf.sf_addr = regs->tf_err; + sf.sf_arg2 = ksi->ksi_code; + sf.sf_addr = (register_t)ksi->ksi_addr; sf.sf_ahu.sf_handler = catcher; } mtx_unlock(&psp->ps_mtx); @@ -391,22 +388,20 @@ #ifdef COMPAT_FREEBSD4 static void -freebsd4_sendsig(catcher, sig, mask, code) - sig_t catcher; - int sig; - sigset_t *mask; - u_long code; +freebsd4_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct sigframe4 sf, *sfp; struct proc *p; struct thread *td; struct sigacts *psp; struct trapframe *regs; + int sig; int oonstack; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + sig = ksi->ksi_signo; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; @@ -446,13 +441,12 @@ sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; /* Fill in POSIX parts */ - sf.sf_si.si_signo = sig; - sf.sf_si.si_code = code; - sf.sf_si.si_addr = (void *)regs->tf_err; + sf.sf_si = ksi->ksi_info; + sf.sf_si.si_signo = sig; /* maybe a translated signal. */ } else { /* Old FreeBSD-style arguments. */ - sf.sf_siginfo = code; - sf.sf_addr = regs->tf_err; + sf.sf_siginfo = ksi->ksi_code; + sf.sf_addr = (register_t)ksi->ksi_addr; sf.sf_ahu.sf_handler = catcher; } mtx_unlock(&psp->ps_mtx); @@ -512,11 +506,7 @@ #endif /* COMPAT_FREEBSD4 */ void -sendsig(catcher, sig, mask, code) - sig_t catcher; - int sig; - sigset_t *mask; - u_long code; +sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct sigframe sf, *sfp; struct proc *p; @@ -524,22 +514,24 @@ struct sigacts *psp; char *sp; struct trapframe *regs; + int sig; int oonstack; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + sig = ksi->ksi_signo; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); #ifdef COMPAT_FREEBSD4 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { - freebsd4_sendsig(catcher, sig, mask, code); + freebsd4_sendsig(catcher, ksi, mask); return; } #endif #ifdef COMPAT_43 if (SIGISMEMBER(psp->ps_osigset, sig)) { - osendsig(catcher, sig, mask, code); + osendsig(catcher, ksi, mask); return; } #endif @@ -585,13 +577,12 @@ sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; /* Fill in POSIX parts */ - sf.sf_si.si_signo = sig; - sf.sf_si.si_code = code; - sf.sf_si.si_addr = (void *)regs->tf_err; + sf.sf_si = ksi->ksi_info; + sf.sf_si.si_signo = sig; /* maybe a translated signal */ } else { /* Old FreeBSD-style arguments. */ - sf.sf_siginfo = code; - sf.sf_addr = regs->tf_err; + sf.sf_siginfo = ksi->ksi_code; + sf.sf_addr = (register_t)ksi->ksi_addr; sf.sf_ahu.sf_handler = catcher; } mtx_unlock(&psp->ps_mtx); @@ -650,26 +641,6 @@ } /* - * Build siginfo_t for SA thread - */ -void -cpu_thread_siginfo(int sig, u_long code, siginfo_t *si) -{ - struct proc *p; - struct thread *td; - - td = curthread; - p = td->td_proc; - PROC_LOCK_ASSERT(p, MA_OWNED); - - bzero(si, sizeof(*si)); - si->si_signo = sig; - si->si_code = code; - si->si_addr = (void *)td->td_frame->tf_err; - /* XXXKSE fill other fields */ -} - -/* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). @@ -693,6 +664,7 @@ struct osigcontext *scp; struct proc *p = td->td_proc; int eflags, error; + ksiginfo_t ksi; regs = td->td_frame; error = copyin(uap->sigcntxp, &sc, sizeof(sc)); @@ -715,8 +687,12 @@ return (EINVAL); /* Go back to user mode if both flags are set. */ - if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) - trapsignal(td, SIGBUS, 0); + if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) { + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); + } if (vm86->vm86_has_vme) { eflags = (tf->tf_eflags & ~VME_USERCHANGE) | @@ -757,7 +733,12 @@ * other selectors, invalid %eip's and invalid %esp's. */ if (!CS_SECURE(scp->sc_cs)) { - trapsignal(td, SIGBUS, T_PROTFLT); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_code = BUS_OBJERR; + ksi.ksi_trap = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); return (EINVAL); } regs->tf_ds = scp->sc_ds; @@ -811,6 +792,7 @@ struct trapframe *regs; const struct ucontext4 *ucp; int cs, eflags, error; + ksiginfo_t ksi; error = copyin(uap->sigcntxp, &uc, sizeof(uc)); if (error != 0) @@ -833,9 +815,12 @@ return (EINVAL); /* Go back to user mode if both flags are set. */ - if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) - trapsignal(td, SIGBUS, 0); - + if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) { + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); + } if (vm86->vm86_has_vme) { eflags = (tf->tf_eflags & ~VME_USERCHANGE) | (eflags & VME_USERCHANGE) | PSL_VM; @@ -880,7 +865,12 @@ cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { printf("freebsd4_sigreturn: cs = 0x%x\n", cs); - trapsignal(td, SIGBUS, T_PROTFLT); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_code = BUS_OBJERR; + ksi.ksi_trap = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); return (EINVAL); } @@ -918,6 +908,7 @@ struct trapframe *regs; const ucontext_t *ucp; int cs, eflags, error, ret; + ksiginfo_t ksi; error = copyin(uap->sigcntxp, &uc, sizeof(uc)); if (error != 0) @@ -940,8 +931,12 @@ return (EINVAL); /* Go back to user mode if both flags are set. */ - if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) - trapsignal(td, SIGBUS, 0); + if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) { + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); + } if (vm86->vm86_has_vme) { eflags = (tf->tf_eflags & ~VME_USERCHANGE) | @@ -987,7 +982,12 @@ cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { printf("sigreturn: cs = 0x%x\n", cs); - trapsignal(td, SIGBUS, T_PROTFLT); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_code = BUS_OBJERR; + ksi.ksi_trap = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); return (EINVAL); } Index: i386/i386/trap.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/trap.c,v retrieving revision 1.281 diff -u -r1.281 trap.c --- i386/i386/trap.c 1 Oct 2005 18:56:18 -0000 1.281 +++ i386/i386/trap.c 11 Oct 2005 06:33:59 -0000 @@ -175,7 +175,9 @@ struct proc *p = td->td_proc; u_int sticks = 0; int i = 0, ucode = 0, type, code; + register_t addr = 0; vm_offset_t eva; + ksiginfo_t ksi; #ifdef POWERFAIL_NMI static int lastalert = 0; #endif @@ -274,13 +276,14 @@ sticks = td->td_sticks; td->td_frame = &frame; + addr = frame.tf_eip; if (td->td_ucred != p->p_ucred) cred_update_thread(td); switch (type) { case T_PRIVINFLT: /* privileged instruction fault */ - ucode = type; i = SIGILL; + ucode = ILL_PRVOPC; break; case T_BPTFLT: /* bpt instruction fault */ @@ -288,6 +291,7 @@ enable_intr(); frame.tf_eflags &= ~PSL_T; i = SIGTRAP; + ucode = (type == T_TRCTRAP ? TRAP_TRACE : TRAP_BRKPT); break; case T_ARITHTRAP: /* arithmetic trap */ @@ -314,14 +318,21 @@ goto user; break; } - /* FALLTHROUGH */ - + i = SIGBUS; + ucode = (type == T_PROTFLT) ? BUS_OBJERR : BUS_ADRERR; + break; case T_SEGNPFLT: /* segment not present fault */ + i = SIGBUS; + ucode = BUS_ADRERR; + break; case T_TSSFLT: /* invalid TSS fault */ + i = SIGBUS; + ucode = BUS_OBJERR; + break; case T_DOUBLEFLT: /* double fault */ default: - ucode = code + BUS_SEGM_FAULT ; i = SIGBUS; + ucode = BUS_RESERVED; break; case T_PAGEFLT: /* page fault */ @@ -339,7 +350,7 @@ type = frame.tf_trapno = T_PRIVINFLT; /* Proceed as in that case. */ - ucode = type; + ucode = ILL_PRVOPC; i = SIGILL; break; } @@ -349,7 +360,13 @@ if (i == 0) goto user; - ucode = T_PAGEFLT; + if (i == SIGSEGV) + ucode = SEGV_MAPERR; + else { + i = SIGSEGV; /* XXX hack */ + ucode = SEGV_ACCERR; + } + addr = eva; break; case T_DIVIDE: /* integer divide fault */ @@ -413,7 +430,7 @@ break; case T_FPOPFLT: /* FPU operand fetch fault */ - ucode = T_FPOPFLT; + ucode = ILL_COPROC; i = SIGILL; break; @@ -634,7 +651,12 @@ if (*p->p_sysent->sv_transtrap) i = (*p->p_sysent->sv_transtrap)(i, type); - trapsignal(td, i, ucode); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = i; + ksi.ksi_code = ucode; + ksi.ksi_addr = (void *)addr; + ksi.ksi_trap = type; + trapsignal(td, &ksi); #ifdef DEBUG if (type <= MAX_TRAP_MSG) { @@ -874,11 +896,13 @@ struct thread *td = curthread; struct proc *p = td->td_proc; register_t orig_tf_eflags; + register_t orig_tf_eip; u_int sticks; int error; int narg; int args[8]; u_int code; + ksiginfo_t ksi; /* * note: PCPU_LAZY_INC() can only be used if we can afford @@ -904,6 +928,7 @@ params = (caddr_t)frame.tf_esp + sizeof(int); code = frame.tf_eax; orig_tf_eflags = frame.tf_eflags; + orig_tf_eip = frame.tf_eip; if (p->p_sysent->sv_prepsyscall) { /* @@ -1017,7 +1042,11 @@ */ if ((orig_tf_eflags & PSL_T) && !(orig_tf_eflags & PSL_VM)) { frame.tf_eflags &= ~PSL_T; - trapsignal(td, SIGTRAP, 0); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGTRAP; + ksi.ksi_code = TRAP_TRACE; + ksi.ksi_addr = (void *)orig_tf_eip; + trapsignal(td, &ksi); } /* Index: i386/include/trap.h =================================================================== RCS file: /home/ncvs/src/sys/i386/include/trap.h,v retrieving revision 1.14 diff -u -r1.14 trap.h --- i386/include/trap.h 7 Apr 2004 20:46:05 -0000 1.14 +++ i386/include/trap.h 11 Oct 2005 06:34:00 -0000 @@ -63,25 +63,6 @@ #define T_XMMFLT 29 /* SIMD floating-point exception */ #define T_RESERVED 30 /* reserved (unknown) */ -/* XXX most of the following codes aren't used, but could be. */ - -/* definitions for */ -#define ILL_RESAD_FAULT T_RESADFLT -#define ILL_PRIVIN_FAULT T_PRIVINFLT -#define ILL_RESOP_FAULT T_RESOPFLT -#define ILL_ALIGN_FAULT T_ALIGNFLT -#define ILL_FPOP_FAULT T_FPOPFLT /* coprocessor operand fault */ - -/* portable macros for SIGFPE/ARITHTRAP */ -#define FPE_INTOVF 1 /* integer overflow */ -#define FPE_INTDIV 2 /* integer divide by zero */ -#define FPE_FLTDIV 3 /* floating point divide by zero */ -#define FPE_FLTOVF 4 /* floating point overflow */ -#define FPE_FLTUND 5 /* floating point underflow */ -#define FPE_FLTRES 6 /* floating point inexact result */ -#define FPE_FLTINV 7 /* invalid floating point operation */ -#define FPE_FLTSUB 8 /* subscript out of range */ - /* old FreeBSD macros, deprecated */ #define FPE_INTOVF_TRAP 0x1 /* integer overflow */ #define FPE_INTDIV_TRAP 0x2 /* integer divide by zero */ @@ -91,12 +72,6 @@ #define FPE_FPU_NP_TRAP 0x6 /* floating point unit not present */ #define FPE_SUBRNG_TRAP 0x7 /* subrange out of bounds */ -/* codes for SIGBUS */ -#define BUS_PAGE_FAULT T_PAGEFLT /* page fault protection base */ -#define BUS_SEGNP_FAULT T_SEGNPFLT /* segment not present */ -#define BUS_STK_FAULT T_STKFLT /* stack segment */ -#define BUS_SEGM_FAULT T_RESERVED /* segment protection base */ - /* Trap's coming from user mode */ #define T_USER 0x100 Index: i386/linux/linux_sysvec.c =================================================================== RCS file: /home/ncvs/src/sys/i386/linux/linux_sysvec.c,v retrieving revision 1.138 diff -u -r1.138 linux_sysvec.c --- i386/linux/linux_sysvec.c 29 Jul 2005 19:40:39 -0000 1.138 +++ i386/linux/linux_sysvec.c 11 Oct 2005 06:34:00 -0000 @@ -107,8 +107,7 @@ 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 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 @@ /* 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 @@ * 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 @@ 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); @@ -522,6 +526,7 @@ struct trapframe *regs; l_sigset_t lmask; int eflags, i; + ksiginfo_t ksi; regs = td->td_frame; @@ -562,7 +567,12 @@ */ #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_trap = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); return(EINVAL); } @@ -618,6 +628,7 @@ stack_t ss; struct trapframe *regs; int eflags; + ksiginfo_t ksi; regs = td->td_frame; @@ -660,7 +671,12 @@ */ #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_trap = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); return(EINVAL); } Index: i386/svr4/svr4_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/i386/svr4/svr4_machdep.c,v retrieving revision 1.35 diff -u -r1.35 svr4_machdep.c --- i386/svr4/svr4_machdep.c 6 Jan 2005 22:18:17 -0000 1.35 +++ i386/svr4/svr4_machdep.c 11 Oct 2005 06:34:00 -0000 @@ -411,11 +411,10 @@ * will return to the user pc, psl. */ void -svr4_sendsig(catcher, sig, mask, code) +svr4_sendsig(catcher, ksi, mask) sig_t catcher; - int sig; + ksiginfo_t ksi; sigset_t *mask; - u_long code; { register struct thread *td = curthread; struct proc *p = td->td_proc; @@ -423,11 +422,15 @@ struct svr4_sigframe *fp, frame; struct sigacts *psp; int oonstack; + int sig; + int code; #if defined(DEBUG_SVR4) printf("svr4_sendsig(%d)\n", sig); #endif PROC_LOCK_ASSERT(p, MA_OWNED); + sig = ksi->ksi_signo; + code = ksi->ksi_code; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); Index: ia64/ia32/ia32_signal.c =================================================================== RCS file: /home/ncvs/src/sys/ia64/ia32/ia32_signal.c,v retrieving revision 1.9 diff -u -r1.9 ia32_signal.c --- ia64/ia32/ia32_signal.c 27 Sep 2005 18:04:20 -0000 1.9 +++ ia64/ia32/ia32_signal.c 11 Oct 2005 06:34:01 -0000 @@ -98,9 +98,9 @@ * sendsig() means that at least untrapped signals will work. */ void -ia32_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { - sendsig(catcher, sig, mask, code); + sendsig(catcher, ksi, mask); } #ifdef COMPAT_FREEBSD4 Index: ia64/ia32/ia32_trap.c =================================================================== RCS file: /home/ncvs/src/sys/ia64/ia32/ia32_trap.c,v retrieving revision 1.5 diff -u -r1.5 ia32_trap.c --- ia64/ia32/ia32_trap.c 12 Apr 2005 23:18:54 -0000 1.5 +++ ia64/ia32/ia32_trap.c 11 Oct 2005 06:34:01 -0000 @@ -61,6 +61,7 @@ register_t eflags; u_int code; int error, i, narg; + ksiginfo_t ksi; PCPU_LAZY_INC(cnt.v_syscall); @@ -168,7 +169,11 @@ */ if ((eflags & PSL_T) && !(eflags & PSL_VM)) { ia64_set_eflag(ia64_get_eflag() & ~PSL_T); - trapsignal(td, SIGTRAP, 0); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGTRAP; + ksi.ksi_code = TRAP_TRACE; + ksi.ksi_addr = (void *)tf->tf_special.iip; + trapsignal(td, &ksi); } #ifdef KTRACE @@ -201,6 +206,7 @@ uint64_t ucode; int sig; u_int sticks; + ksiginfo_t ksi; KASSERT(TRAPF_USERMODE(tf), ("%s: In kernel mode???", __func__)); @@ -284,7 +290,11 @@ KASSERT(sig != 0, ("%s: signal not set", __func__)); - trapsignal(td, sig, ucode); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = sig; + ksi.ksi_code = (int)ucode; /* XXX */ + /* ksi.ksi_addr */ + trapsignal(td, &ksi); out: userret(td, tf, sticks); Index: ia64/ia64/machdep.c =================================================================== RCS file: /home/ncvs/src/sys/ia64/ia64/machdep.c,v retrieving revision 1.202 diff -u -r1.202 machdep.c --- ia64/ia64/machdep.c 9 Sep 2005 19:18:36 -0000 1.202 +++ ia64/ia64/machdep.c 11 Oct 2005 06:34:03 -0000 @@ -878,7 +878,7 @@ * Send an interrupt (signal) to a process. */ void -sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct proc *p; struct thread *td; @@ -887,10 +887,14 @@ struct sigframe sf, *sfp; u_int64_t sbs, sp; int oonstack; + int sig; + u_long code; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + sig = ksi->ksi_signo; + code = ksi->ksi_code; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); tf = td->td_frame; @@ -926,8 +930,8 @@ /* Fill in the siginfo structure for POSIX handlers. */ if (SIGISMEMBER(psp->ps_siginfo, sig)) { + sf.sf_si = ksi->ksi_info; sf.sf_si.si_signo = sig; - sf.sf_si.si_code = code; sf.sf_si.si_addr = (void*)tf->tf_special.ifa; code = (u_int64_t)&sfp->sf_si; } @@ -979,25 +983,6 @@ } /* - * Build siginfo_t for SA thread - */ -void -cpu_thread_siginfo(int sig, u_long code, siginfo_t *si) -{ - struct proc *p; - struct thread *td; - - td = curthread; - p = td->td_proc; - PROC_LOCK_ASSERT(p, MA_OWNED); - - bzero(si, sizeof(*si)); - si->si_signo = sig; - si->si_code = code; - /* XXXKSE fill other fields */ -} - -/* * System call to cleanup state after a signal * has been taken. Reset signal mask and * stack state from context left by sendsig (above). Index: ia64/ia64/trap.c =================================================================== RCS file: /home/ncvs/src/sys/ia64/ia64/trap.c,v retrieving revision 1.115 diff -u -r1.115 trap.c --- ia64/ia64/trap.c 9 Sep 2005 19:18:36 -0000 1.115 +++ ia64/ia64/trap.c 11 Oct 2005 06:34:05 -0000 @@ -361,6 +361,7 @@ uint64_t ucode; int error, sig, user; u_int sticks; + ksiginfo_t ksi; user = TRAPF_USERMODE(tf) ? 1 : 0; @@ -869,7 +870,10 @@ if (print_usertrap) printtrap(vector, tf, 1, user); - trapsignal(td, sig, ucode); + ksiginfo_init(&ksi); + ksi.ksi_signo = sig; + ksi.ksi_code = ucode; + trapsignal(td, &ksi); out: if (user) { Index: kern/init_sysent.c =================================================================== RCS file: /home/ncvs/src/sys/kern/init_sysent.c,v retrieving revision 1.197 diff -u -r1.197 init_sysent.c --- kern/init_sysent.c 27 Sep 2005 14:36:58 -0000 1.197 +++ kern/init_sysent.c 11 Oct 2005 06:34:06 -0000 @@ -2,7 +2,7 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/kern/init_sysent.c,v 1.197 2005/09/27 14:36:58 csjp Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.199 2005/09/27 14:32:04 csjp Exp */ @@ -485,4 +485,5 @@ { SYF_MPSAFE | AS(auditctl_args), (sy_call_t *)lkmressys, AUE_NULL }, /* 453 = auditctl */ { SYF_MPSAFE | AS(_umtx_op_args), (sy_call_t *)_umtx_op, AUE_NULL }, /* 454 = _umtx_op */ { SYF_MPSAFE | AS(thr_new_args), (sy_call_t *)thr_new, AUE_NULL }, /* 455 = thr_new */ + { SYF_MPSAFE | AS(sigqueue_args), (sy_call_t *)sigqueue, AUE_NULL }, /* 456 = sigqueue */ }; Index: kern/kern_exec.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_exec.c,v retrieving revision 1.278 diff -u -r1.278 kern_exec.c --- kern/kern_exec.c 4 Oct 2005 04:02:33 -0000 1.278 +++ kern/kern_exec.c 11 Oct 2005 06:34:07 -0000 @@ -666,7 +666,7 @@ * single thread mode. */ if (p->p_flag & P_TRACED) - tdsignal(td, SIGTRAP, SIGTARGET_TD); + tdsignal(td, SIGTRAP, NULL, SIGTARGET_TD); /* clear "fork but no exec" flag, as we _are_ execing */ p->p_acflag &= ~AFORK; Index: kern/kern_exit.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_exit.c,v retrieving revision 1.265 diff -u -r1.265 kern_exit.c --- kern/kern_exit.c 2 Sep 2005 20:20:01 -0000 1.265 +++ kern/kern_exit.c 11 Oct 2005 06:34:08 -0000 @@ -207,8 +207,8 @@ PROC_LOCK(p); stopprofclock(p); p->p_flag &= ~(P_TRACED | P_PPWAIT); - SIGEMPTYSET(p->p_siglist); - SIGEMPTYSET(td->td_siglist); + sigqueue_flush(&p->p_sigqueue); + sigqueue_flush(&td->td_sigqueue); /* * Stop the real interval timer. If the handler is currently Index: kern/kern_kse.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_kse.c,v retrieving revision 1.218 diff -u -r1.218 kern_kse.c --- kern/kern_kse.c 30 Sep 2005 06:09:41 -0000 1.218 +++ kern/kern_kse.c 11 Oct 2005 06:34:08 -0000 @@ -210,7 +210,7 @@ if (uap->data > 0) { td2->td_flags &= ~TDF_INTERRUPT; mtx_unlock_spin(&sched_lock); - tdsignal(td2, (int)uap->data, SIGTARGET_TD); + tdsignal(td2, (int)uap->data, NULL, SIGTARGET_TD); } else { mtx_unlock_spin(&sched_lock); } @@ -342,6 +342,7 @@ PROC_LOCK(p); if (error) psignal(p, SIGSEGV); + sigqueue_flush(&td->td_sigqueue); mtx_lock_spin(&sched_lock); upcall_remove(td); if (p->p_numthreads != 1) { @@ -697,8 +698,8 @@ * SA threading will make a special thread to handle them. */ if (first && sa) { - SIGSETOR(p->p_siglist, td->td_siglist); - SIGEMPTYSET(td->td_siglist); + sigqueue_move_set(&td->td_sigqueue, &p->p_sigqueue, + &td->td_sigqueue.sq_signals); SIGFILLSET(td->td_sigmask); SIG_CANTMASK(td->td_sigmask); } @@ -1094,10 +1095,9 @@ * debugged. */ void -thread_signal_add(struct thread *td, int sig) +thread_signal_add(struct thread *td, ksiginfo_t *ksi) { struct proc *p; - siginfo_t siginfo; struct sigacts *ps; int error; @@ -1106,11 +1106,11 @@ ps = p->p_sigacts; mtx_assert(&ps->ps_mtx, MA_OWNED); - cpu_thread_siginfo(sig, 0, &siginfo); mtx_unlock(&ps->ps_mtx); - SIGADDSET(td->td_sigmask, sig); + SIGADDSET(td->td_sigmask, ksi->ksi_signo); PROC_UNLOCK(p); - error = copyout(&siginfo, &td->td_mailbox->tm_syncsig, sizeof(siginfo)); + error = copyout(&ksi->ksi_info, &td->td_mailbox->tm_syncsig, + sizeof(siginfo_t)); if (error) { PROC_LOCK(p); sigexit(td, SIGSEGV); @@ -1315,6 +1315,7 @@ wakeup(&kg->kg_completed); WITNESS_WARN(WARN_PANIC, &p->p_mtx.mtx_object, "thread exiting in userret"); + sigqueue_flush(&td->td_sigqueue); mtx_lock_spin(&sched_lock); thread_stopped(p); thread_exit(); Index: kern/kern_sig.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_sig.c,v retrieving revision 1.306 diff -u -r1.306 kern_sig.c --- kern/kern_sig.c 6 Jun 2005 05:13:10 -0000 1.306 +++ kern/kern_sig.c 11 Oct 2005 06:34:12 -0000 @@ -71,6 +71,9 @@ #include #include #include +#include +#include +#include #include @@ -90,10 +93,14 @@ static void filt_sigdetach(struct knote *kn); static int filt_signal(struct knote *kn, long hint); static struct thread *sigtd(struct proc *p, int sig, int prop); -static int kern_sigtimedwait(struct thread *td, sigset_t set, - siginfo_t *info, struct timespec *timeout); -static void do_tdsignal(struct thread *td, int sig, sigtarget_t target); +static int kern_sigtimedwait(struct thread *, sigset_t, + ksiginfo_t *, struct timespec *); +static int do_tdsignal(struct thread *, int, ksiginfo_t *, sigtarget_t); +static void sigqueue_start(void); +static ksiginfo_t * ksiginfo_alloc(void); +static void ksiginfo_free(ksiginfo_t *); +static uma_zone_t ksiginfo_zone = NULL; struct filterops sig_filtops = { 0, filt_sigattach, filt_sigdetach, filt_signal }; @@ -102,6 +109,31 @@ &kern_logsigexit, 0, "Log processes quitting on abnormal signals to syslog(3)"); +SYSCTL_NODE(_kern, OID_AUTO, sigqueue, CTLFLAG_RW, 0, "POSIX real time signal"); + +static int max_pending_per_proc = 128; +SYSCTL_INT(_kern_sigqueue, OID_AUTO, max_pending_per_proc, CTLFLAG_RW, + &max_pending_per_proc, 0, "Max pending signals per proc"); + +static int queue_rt_signal_only = 1; +SYSCTL_INT(_kern_sigqueue, OID_AUTO, queue_rt_signal_only, CTLFLAG_RW, + &queue_rt_signal_only, 0, "Only rt signal is queued"); + +static int preallocate_siginfo = 1024; +TUNABLE_INT("kern.sigqueue.preallocate", &preallocate_siginfo); +SYSCTL_INT(_kern_sigqueue, OID_AUTO, preallocate, CTLFLAG_RD, + &preallocate_siginfo, 0, "Preallocated signal memory size"); + +static int signal_overflow = 0; +SYSCTL_INT(_kern_sigqueue, OID_AUTO, signal_overflow, CTLFLAG_RD, + &signal_overflow, 0, "Number of signals overflew"); + +static int signal_alloc_fail = 0; +SYSCTL_INT(_kern_sigqueue, OID_AUTO, signal_alloc_fail, CTLFLAG_RD, + &signal_alloc_fail, 0, "signals failed to be allocated"); + +SYSINIT(signal, SI_SUB_P1003_1B, SI_ORDER_FIRST+3, sigqueue_start, NULL); + /* * Policy -- Can ucred cr1 send SIGIO to process cr2? * Should use cr_cansignal() once cr_cansignal() allows SIGIO and SIGURG @@ -174,6 +206,266 @@ SA_KILL|SA_PROC, /* SIGUSR2 */ }; +static void +sigqueue_start(void) +{ + ksiginfo_zone = uma_zcreate("ksiginfo", sizeof(ksiginfo_t), + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); + uma_prealloc(ksiginfo_zone, preallocate_siginfo); +} + +static ksiginfo_t * +ksiginfo_alloc(void) +{ + if (ksiginfo_zone != NULL) + return ((ksiginfo_t *)uma_zalloc(ksiginfo_zone, M_NOWAIT)); + return (NULL); +} + +static void +ksiginfo_free(ksiginfo_t *ksi) +{ + uma_zfree(ksiginfo_zone, ksi); +} + +void +sigqueue_init(sigqueue_t *list, struct proc *p) +{ + SIGEMPTYSET(list->sq_signals); + TAILQ_INIT(&list->sq_list); + list->sq_proc = p; + list->sq_flags = SQ_INIT; +} + +/* + * Get a signal's ksiginfo. + * Return: + * 0 - signal not found + * others - signal number + */ +int +sigqueue_get(sigqueue_t *sq, int signo, ksiginfo_t *si) +{ + struct proc *p = sq->sq_proc; + struct ksiginfo *ksi, *next; + int count = 0; + + KASSERT(sq->sq_flags & SQ_INIT, ("sigqueue not inited")); + + ksiginfo_init(si); + if (!SIGISMEMBER(sq->sq_signals, signo)) + return (0); + + for (ksi = TAILQ_FIRST(&sq->sq_list); ksi != NULL; ksi = next) { + next = TAILQ_NEXT(ksi, ksi_link); + if (ksi->ksi_signo == signo) { + if (count == 0) { + TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link); + ksiginfo_copy(ksi, si); + ksiginfo_free(ksi); + if (p != NULL) + p->p_pendingcnt--; + } + count++; + } + } + + if (count <= 1) + SIGDELSET(sq->sq_signals, signo); + si->ksi_signo = signo; + return (signo); +} + +int +sigqueue_add(sigqueue_t *sq, int signo, ksiginfo_t *si) +{ + struct proc *p = sq->sq_proc; + struct ksiginfo *ksi; + int ret = 0; + + KASSERT(sq->sq_flags & SQ_INIT, ("sigqueue not inited")); + + if (ksiginfo_zone != NULL && si != NULL) { + if (p != NULL && p->p_pendingcnt > max_pending_per_proc) { + signal_overflow++; + ret = EAGAIN; + } else if ((ksi = ksiginfo_alloc()) == NULL) { + signal_alloc_fail++; + ret = EAGAIN; +#ifdef DIAGNOSTIC + printf("Out of memory allocating siginfo for pid %d\n", + p->p_pid); +#endif + } else { + if (p != NULL) + p->p_pendingcnt++; + ksiginfo_copy(si, ksi); + ksi->ksi_signo = signo; + TAILQ_INSERT_TAIL(&sq->sq_list, ksi, ksi_link); + } + } + + if (ret != 0) + return (ret); + + SIGADDSET(sq->sq_signals, signo); + return (ret); +} + +void +sigqueue_flush(sigqueue_t *sq) +{ + struct proc *p = sq->sq_proc; + ksiginfo_t *ksi; + + KASSERT(sq->sq_flags & SQ_INIT, ("sigqueue not inited")); + + while ((ksi = TAILQ_FIRST(&sq->sq_list)) != NULL) { + TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link); + ksiginfo_free(ksi); + if (p != NULL) + p->p_pendingcnt--; + } + + SIGEMPTYSET(sq->sq_signals); +} + +void +sigqueue_collect_set(sigqueue_t *sq, sigset_t *set) +{ + ksiginfo_t *ksi; + + KASSERT(sq->sq_flags & SQ_INIT, ("sigqueue not inited")); + + TAILQ_FOREACH(ksi, &sq->sq_list, ksi_link) + SIGADDSET(*set, ksi->ksi_signo); +} + +void +sigqueue_move_set(sigqueue_t *src, sigqueue_t *dst, sigset_t *setp) +{ + sigset_t tmp, set; + struct proc *p1, *p2; + ksiginfo_t *ksi, *next; + + KASSERT(src->sq_flags & SQ_INIT, ("src sigqueue not inited")); + KASSERT(dst->sq_flags & SQ_INIT, ("dst sigqueue not inited")); + /* + * make a copy, this allows setp to point to src or dst + * sq_signals without trouble. + */ + set = *setp; + p1 = src->sq_proc; + p2 = dst->sq_proc; + /* Move siginfo to target list */ + for (ksi = TAILQ_FIRST(&src->sq_list); ksi != NULL; ksi = next) { + next = TAILQ_NEXT(ksi, ksi_link); + if (SIGISMEMBER(set, ksi->ksi_signo)) { + TAILQ_REMOVE(&src->sq_list, ksi, ksi_link); + if (p1 != NULL) + p1->p_pendingcnt--; + TAILQ_INSERT_TAIL(&dst->sq_list, ksi, ksi_link); + if (p2 != NULL) + p2->p_pendingcnt++; + } + } + + /* Move pending bits to target list */ + tmp = src->sq_signals; + SIGSETAND(tmp, set); + SIGSETOR(dst->sq_signals, tmp); + SIGSETNAND(src->sq_signals, tmp); + + /* Finally, rescan src queue and set pending bits for it */ + sigqueue_collect_set(src, &src->sq_signals); +} + +void +sigqueue_move(sigqueue_t *src, sigqueue_t *dst, int signo) +{ + sigset_t set; + + SIGEMPTYSET(set); + SIGADDSET(set, signo); + sigqueue_move_set(src, dst, &set); +} + +void +sigqueue_delete_set(sigqueue_t *sq, sigset_t *set) +{ + struct proc *p = sq->sq_proc; + ksiginfo_t *ksi, *next; + + KASSERT(sq->sq_flags & SQ_INIT, ("src sigqueue not inited")); + + /* Remove siginfo queue */ + for (ksi = TAILQ_FIRST(&sq->sq_list); ksi != NULL; ksi = next) { + next = TAILQ_NEXT(ksi, ksi_link); + if (SIGISMEMBER(*set, ksi->ksi_signo)) { + TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link); + ksiginfo_free(ksi); + if (p != NULL) + p->p_pendingcnt--; + } + } + SIGSETNAND(sq->sq_signals, *set); + /* Finally, rescan queue and set pending bits for it */ + sigqueue_collect_set(sq, &sq->sq_signals); +} + +void +sigqueue_delete(sigqueue_t *sq, int signo) +{ + sigset_t set; + + SIGEMPTYSET(set); + SIGADDSET(set, signo); + sigqueue_delete_set(sq, &set); +} + +/* Remove a set of signals for a process */ +void +sigqueue_delete_set_proc(struct proc *p, sigset_t *set) +{ + sigqueue_t worklist; + struct thread *td0; + + PROC_LOCK_ASSERT(p, MA_OWNED); + + sigqueue_init(&worklist, NULL); + sigqueue_move_set(&p->p_sigqueue, &worklist, set); + + mtx_lock_spin(&sched_lock); + FOREACH_THREAD_IN_PROC(p, td0) + sigqueue_move_set(&td0->td_sigqueue, &worklist, set); + mtx_unlock_spin(&sched_lock); + + sigqueue_flush(&worklist); +} + +void +sigqueue_delete_proc(struct proc *p, int signo) +{ + sigset_t set; + + SIGEMPTYSET(set); + SIGADDSET(set, signo); + sigqueue_delete_set_proc(p, &set); +} + +void +sigqueue_delete_stopmask_proc(struct proc *p) +{ + sigset_t set; + + SIGEMPTYSET(set); + SIGADDSET(set, SIGSTOP); + SIGADDSET(set, SIGTSTP); + SIGADDSET(set, SIGTTIN); + SIGADDSET(set, SIGTTOU); + sigqueue_delete_set_proc(p, &set); +} + /* * Determine signal that should be delivered to process p, the current * process, 0 if none. If there is a pending stop signal with default @@ -193,7 +485,7 @@ /* * Arrange for ast() to handle unmasked pending signals on return to user - * mode. This must be called whenever a signal is added to td_siglist or + * mode. This must be called whenever a signal is added to td_sigqueue or * unmasked in td_sigmask. */ void @@ -208,22 +500,21 @@ /* * If our mask changed we may have to move signal that were - * previously masked by all threads to our siglist. + * previously masked by all threads to our sigqueue. */ - set = p->p_siglist; + set = p->p_sigqueue.sq_signals; if (p->p_flag & P_SA) - saved = p->p_siglist; + saved = p->p_sigqueue.sq_signals; SIGSETNAND(set, td->td_sigmask); - SIGSETNAND(p->p_siglist, set); - SIGSETOR(td->td_siglist, set); - + if (! SIGISEMPTY(set)) + sigqueue_move_set(&p->p_sigqueue, &td->td_sigqueue, &set); if (SIGPENDING(td)) { mtx_lock_spin(&sched_lock); td->td_flags |= TDF_NEEDSIGCHK | TDF_ASTPENDING; mtx_unlock_spin(&sched_lock); } if ((p->p_flag & P_SA) && !(p->p_flag & P_SIGEVENT)) { - if (!SIGSETEQ(saved, p->p_siglist)) { + if (!SIGSETEQ(saved, p->p_sigqueue.sq_signals)) { /* pending set changed */ p->p_flag |= P_SIGEVENT; wakeup(&p->p_siglist); @@ -283,7 +574,6 @@ int flags; { struct sigacts *ps; - struct thread *td0; struct proc *p = td->td_proc; if (!_SIG_VALID(sig)) @@ -382,16 +672,12 @@ (sigprop(sig) & SA_IGNORE && ps->ps_sigact[_SIG_IDX(sig)] == SIG_DFL)) { if ((p->p_flag & P_SA) && - SIGISMEMBER(p->p_siglist, sig)) { + SIGISMEMBER(p->p_sigqueue.sq_signals, sig)) { p->p_flag |= P_SIGEVENT; wakeup(&p->p_siglist); } /* never to be seen again */ - SIGDELSET(p->p_siglist, sig); - mtx_lock_spin(&sched_lock); - FOREACH_THREAD_IN_PROC(p, td0) - SIGDELSET(td0->td_siglist, sig); - mtx_unlock_spin(&sched_lock); + sigqueue_delete_proc(p, sig); if (sig != SIGCONT) /* easier in psignal */ SIGADDSET(ps->ps_sigignore, sig); @@ -596,11 +882,7 @@ if (sigprop(sig) & SA_IGNORE) { if (sig != SIGCONT) SIGADDSET(ps->ps_sigignore, sig); - SIGDELSET(p->p_siglist, sig); - /* - * There is only one thread at this point. - */ - SIGDELSET(td->td_siglist, sig); + sigqueue_delete_proc(p, sig); } ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL; } @@ -726,18 +1008,13 @@ } #endif /* COMPAT_43 */ -#ifndef _SYS_SYSPROTO_H_ -struct sigpending_args { - sigset_t *set; -}; -#endif /* * MPSAFE */ int sigwait(struct thread *td, struct sigwait_args *uap) { - siginfo_t info; + ksiginfo_t ksi; sigset_t set; int error; @@ -747,7 +1024,7 @@ return (0); } - error = kern_sigtimedwait(td, set, &info, NULL); + error = kern_sigtimedwait(td, set, &ksi, NULL); if (error) { if (error == ERESTART) return (error); @@ -755,13 +1032,7 @@ return (0); } - error = copyout(&info.si_signo, uap->sig, sizeof(info.si_signo)); - /* Repost if we got an error. */ - if (error && info.si_signo) { - PROC_LOCK(td->td_proc); - tdsignal(td, info.si_signo, SIGTARGET_TD); - PROC_UNLOCK(td->td_proc); - } + error = copyout(&ksi.ksi_signo, uap->sig, sizeof(ksi.ksi_signo)); td->td_retval[0] = error; return (0); } @@ -774,7 +1045,7 @@ struct timespec ts; struct timespec *timeout; sigset_t set; - siginfo_t info; + ksiginfo_t ksi; int error; if (uap->timeout) { @@ -790,20 +1061,15 @@ if (error) return (error); - error = kern_sigtimedwait(td, set, &info, timeout); + error = kern_sigtimedwait(td, set, &ksi, timeout); if (error) return (error); if (uap->info) - error = copyout(&info, uap->info, sizeof(info)); - /* Repost if we got an error. */ - if (error && info.si_signo) { - PROC_LOCK(td->td_proc); - tdsignal(td, info.si_signo, SIGTARGET_TD); - PROC_UNLOCK(td->td_proc); - } else { - td->td_retval[0] = info.si_signo; - } + error = copyout(&ksi.ksi_info, uap->info, sizeof(siginfo_t)); + + if (error == 0) + td->td_retval[0] = ksi.ksi_signo; return (error); } @@ -813,7 +1079,7 @@ int sigwaitinfo(struct thread *td, struct sigwaitinfo_args *uap) { - siginfo_t info; + ksiginfo_t ksi; sigset_t set; int error; @@ -821,26 +1087,21 @@ if (error) return (error); - error = kern_sigtimedwait(td, set, &info, NULL); + error = kern_sigtimedwait(td, set, &ksi, NULL); if (error) return (error); if (uap->info) - error = copyout(&info, uap->info, sizeof(info)); - /* Repost if we got an error. */ - if (error && info.si_signo) { - PROC_LOCK(td->td_proc); - tdsignal(td, info.si_signo, SIGTARGET_TD); - PROC_UNLOCK(td->td_proc); - } else { - td->td_retval[0] = info.si_signo; - } + error = copyout(&ksi.ksi_info, uap->info, sizeof(siginfo_t)); + + if (error == 0) + td->td_retval[0] = ksi.ksi_signo; return (error); } static int -kern_sigtimedwait(struct thread *td, sigset_t waitset, siginfo_t *info, - struct timespec *timeout) +kern_sigtimedwait(struct thread *td, sigset_t waitset, ksiginfo_t *ksi, + struct timespec *timeout) { struct sigacts *ps; sigset_t savedmask; @@ -870,7 +1131,7 @@ for (i = 1; i <= _SIG_MAXSIG; ++i) { if (!SIGISMEMBER(waitset, i)) continue; - if (SIGISMEMBER(td->td_siglist, i)) { + if (SIGISMEMBER(td->td_sigqueue.sq_signals, i)) { SIGFILLSET(td->td_sigmask); SIG_CANTMASK(td->td_sigmask); SIGDELSET(td->td_sigmask, i); @@ -878,13 +1139,12 @@ sig = cursig(td); i = 0; mtx_unlock(&ps->ps_mtx); - } else if (SIGISMEMBER(p->p_siglist, i)) { + } else if (SIGISMEMBER(p->p_sigqueue.sq_signals, i)) { if (p->p_flag & P_SA) { p->p_flag |= P_SIGEVENT; wakeup(&p->p_siglist); } - SIGDELSET(p->p_siglist, i); - SIGADDSET(td->td_siglist, i); + sigqueue_move(&p->p_sigqueue, &td->td_sigqueue, i); SIGFILLSET(td->td_sigmask); SIG_CANTMASK(td->td_sigmask); SIGDELSET(td->td_sigmask, i); @@ -936,11 +1196,11 @@ goto again; out: - td->td_sigmask = savedmask; - signotify(td); if (sig) { sig_t action; + sigqueue_get(&td->td_sigqueue, sig, ksi); + ksi->ksi_signo = sig; error = 0; mtx_lock(&ps->ps_mtx); action = ps->ps_sigact[_SIG_IDX(sig)]; @@ -951,15 +1211,18 @@ #endif _STOPEVENT(p, S_SIG, sig); - SIGDELSET(td->td_siglist, sig); - bzero(info, sizeof(*info)); - info->si_signo = sig; - info->si_code = 0; } + td->td_sigmask = savedmask; + signotify(td); PROC_UNLOCK(p); return (error); } +#ifndef _SYS_SYSPROTO_H_ +struct sigpending_args { + sigset_t *set; +}; +#endif /* * MPSAFE */ @@ -969,13 +1232,13 @@ struct sigpending_args *uap; { struct proc *p = td->td_proc; - sigset_t siglist; + sigset_t pending; PROC_LOCK(p); - siglist = p->p_siglist; - SIGSETOR(siglist, td->td_siglist); + pending = p->p_sigqueue.sq_signals; + SIGSETOR(pending, td->td_sigqueue.sq_signals); PROC_UNLOCK(p); - return (copyout(&siglist, uap->set, sizeof(sigset_t))); + return (copyout(&pending, uap->set, sizeof(sigset_t))); } #ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */ @@ -993,13 +1256,13 @@ struct osigpending_args *uap; { struct proc *p = td->td_proc; - sigset_t siglist; + sigset_t pending; PROC_LOCK(p); - siglist = p->p_siglist; - SIGSETOR(siglist, td->td_siglist); + pending = p->p_sigqueue.sq_signals; + SIGSETOR(pending, td->td_sigqueue.sq_signals); PROC_UNLOCK(p); - SIG2OSIG(siglist, td->td_retval[0]); + SIG2OSIG(pending, td->td_retval[0]); return (0); } #endif /* COMPAT_43 */ @@ -1107,11 +1370,8 @@ #endif /* COMPAT_43 */ /* - * Suspend process until signal, providing mask to be set + * Suspend calling thread until signal, providing mask to be set * in the meantime. - ***** XXXKSE this doesn't make sense under KSE. - ***** Do we suspend the thread or all threads in the process? - ***** How do we suspend threads running NOW on another processor? */ #ifndef _SYS_SYSPROTO_H_ struct sigsuspend_args { @@ -1431,10 +1691,62 @@ if ((u_int)uap->signum > _SIG_MAXSIG) return (EINVAL); + return (killpg1(td, uap->signum, uap->pgid, 0)); } #endif /* COMPAT_43 */ +#ifndef _SYS_SYSPROTO_H_ +struct sigqueue_args { + pid_t pid; + int signum; + /* union sigval */ void *value; +}; +#endif + +int +sigqueue(struct thread *td, struct sigqueue_args *uap) +{ + ksiginfo_t ksi; + struct thread *td2; + struct proc *p; + int prop; + int error; + + if ((u_int)uap->signum > _SIG_MAXSIG) + return (EINVAL); + + /* + * Specification says sigqueue can only send signal to + * single process + */ + if (uap->pid < 0) + return (EINVAL); + + if ((p = pfind(uap->pid)) == NULL) { + if ((p = zpfind(uap->pid)) == NULL) + return (ESRCH); + } + error = p_cansignal(td, p, uap->signum); + if (error == 0 && uap->signum != 0 && p->p_state != PRS_ZOMBIE) { + prop = sigprop(uap->signum); + /* + * Find a thread to deliver the signal to. + */ + td2 = sigtd(p, uap->signum, prop); + + ksiginfo_init(&ksi); + ksi.ksi_signo = uap->signum; + ksi.ksi_code = SI_QUEUE; + ksi.ksi_pid = td->td_proc->p_pid; + ksi.ksi_uid = td->td_ucred->cr_ruid; + ksi.ksi_value.sigval_ptr = uap->value; + error = tdsignal(td2, uap->signum, &ksi, SIGTARGET_P); + } + PROC_UNLOCK(p); + return (error); +} + /* * Send a signal to a process group. */ @@ -1485,14 +1797,19 @@ * MPSAFE */ void -trapsignal(struct thread *td, int sig, u_long code) +trapsignal(struct thread *td, ksiginfo_t *ksi) { struct sigacts *ps; struct proc *p; - siginfo_t siginfo; int error; + int sig; + int code; p = td->td_proc; + sig = ksi->ksi_signo; + code = ksi->ksi_code; + KASSERT(_SIG_VALID(sig), ("invalid signal")); + if (td->td_pflags & TDP_SA) { if (td->td_mailbox == NULL) thread_user_enter(td); @@ -1521,9 +1838,8 @@ &td->td_sigmask, code); #endif if (!(td->td_pflags & TDP_SA)) - (*p->p_sysent->sv_sendsig)( - ps->ps_sigact[_SIG_IDX(sig)], sig, - &td->td_sigmask, code); + (*p->p_sysent->sv_sendsig)(ps->ps_sigact[_SIG_IDX(sig)], + ksi, &td->td_sigmask); else if (td->td_mailbox == NULL) { mtx_unlock(&ps->ps_mtx); /* UTS caused a sync signal */ @@ -1531,12 +1847,11 @@ p->p_sig = sig; /* XXX to verify code */ sigexit(td, sig); } else { - cpu_thread_siginfo(sig, code, &siginfo); mtx_unlock(&ps->ps_mtx); SIGADDSET(td->td_sigmask, sig); PROC_UNLOCK(p); - error = copyout(&siginfo, &td->td_mailbox->tm_syncsig, - sizeof(siginfo)); + error = copyout(&ksi->ksi_info, &td->td_mailbox->tm_syncsig, + sizeof(siginfo_t)); PROC_LOCK(p); /* UTS memory corrupted */ if (error) @@ -1561,7 +1876,7 @@ mtx_unlock(&ps->ps_mtx); p->p_code = code; /* XXX for core dump/debugger */ p->p_sig = sig; /* XXX to verify code */ - tdsignal(td, sig, SIGTARGET_TD); + tdsignal(td, sig, ksi, SIGTARGET_TD); } PROC_UNLOCK(p); } @@ -1630,39 +1945,42 @@ */ td = sigtd(p, sig, prop); - tdsignal(td, sig, SIGTARGET_P); + tdsignal(td, sig, NULL, SIGTARGET_P); } /* * MPSAFE */ -void -tdsignal(struct thread *td, int sig, sigtarget_t target) +int +tdsignal(struct thread *td, int sig, ksiginfo_t *ksi, sigtarget_t target) { sigset_t saved; struct proc *p = td->td_proc; + int ret; if (p->p_flag & P_SA) - saved = p->p_siglist; - do_tdsignal(td, sig, target); + saved = p->p_sigqueue.sq_signals; + ret = do_tdsignal(td, sig, ksi, target); if ((p->p_flag & P_SA) && !(p->p_flag & P_SIGEVENT)) { - if (!SIGSETEQ(saved, p->p_siglist)) { + if (!SIGSETEQ(saved, p->p_sigqueue.sq_signals)) { /* pending set changed */ p->p_flag |= P_SIGEVENT; wakeup(&p->p_siglist); } } + return (ret); } -static void -do_tdsignal(struct thread *td, int sig, sigtarget_t target) +static int +do_tdsignal(struct thread *td, int sig, ksiginfo_t *ksi, sigtarget_t target) { struct proc *p; - register sig_t action; - sigset_t *siglist; + sig_t action; + sigqueue_t *sigqueue; struct thread *td0; - register int prop; + int prop; struct sigacts *ps; + int ret = 0; if (!_SIG_VALID(sig)) panic("do_tdsignal(): invalid signal"); @@ -1681,16 +1999,17 @@ * thread that unblocks it. Otherwise, assign it to this thread now. */ if (target == SIGTARGET_TD) { - siglist = &td->td_siglist; + sigqueue = &td->td_sigqueue; } else { if (!SIGISMEMBER(td->td_sigmask, sig)) - siglist = &td->td_siglist; + sigqueue = &td->td_sigqueue; else - siglist = &p->p_siglist; + sigqueue = &p->p_sigqueue; } /* * If the signal is being ignored, + * or process is exiting or thread is exiting, * then we forget about it immediately. * (Note: we don't set SIGCONT in ps_sigignore, * and if it is set to SIG_IGN, @@ -1700,7 +2019,7 @@ if (SIGISMEMBER(ps->ps_sigignore, sig) || (p->p_flag & P_WEXIT)) { mtx_unlock(&ps->ps_mtx); - return; + return (ret); } if (SIGISMEMBER(td->td_sigmask, sig)) action = SIG_HOLD; @@ -1710,19 +2029,9 @@ action = SIG_DFL; mtx_unlock(&ps->ps_mtx); - if (prop & SA_CONT) { - SIG_STOPSIGMASK(p->p_siglist); - /* - * XXX Should investigate leaving STOP and CONT sigs only in - * the proc's siglist. - */ - mtx_lock_spin(&sched_lock); - FOREACH_THREAD_IN_PROC(p, td0) - SIG_STOPSIGMASK(td0->td_siglist); - mtx_unlock_spin(&sched_lock); - } - - if (prop & SA_STOP) { + if (prop & SA_CONT) + sigqueue_delete_stopmask_proc(p); + else if (prop & SA_STOP) { /* * If sending a tty stop signal to a member of an orphaned * process group, discard the signal here if the action @@ -1732,16 +2041,14 @@ if ((prop & SA_TTYSTOP) && (p->p_pgrp->pg_jobc == 0) && (action == SIG_DFL)) - return; - SIG_CONTSIGMASK(p->p_siglist); - mtx_lock_spin(&sched_lock); - FOREACH_THREAD_IN_PROC(p, td0) - SIG_CONTSIGMASK(td0->td_siglist); - mtx_unlock_spin(&sched_lock); + return (ret); + sigqueue_delete_proc(p, SIGCONT); p->p_flag &= ~P_CONTINUED; } - SIGADDSET(*siglist, sig); + ret = sigqueue_add(sigqueue, sig, ksi); + if (ret != 0) + return (ret); signotify(td); /* uses schedlock */ /* * Defer further processing for signals which are held, @@ -1749,7 +2056,7 @@ */ if (action == SIG_HOLD && !((prop & SA_CONT) && (p->p_flag & P_STOPPED_SIG))) - return; + return (ret); /* * SIGKILL: Remove procfs STOPEVENTs. */ @@ -1795,10 +2102,10 @@ if (prop & SA_CONT) { /* * If SIGCONT is default (or ignored), we continue the - * process but don't leave the signal in siglist as + * process but don't leave the signal in sigqueue as * it has no further action. If SIGCONT is held, we * continue the process and leave the signal in - * siglist. If the process catches SIGCONT, let it + * sigqueue. If the process catches SIGCONT, let it * handle the signal itself. If it isn't waiting on * an event, it goes back to run state. * Otherwise, process goes back to sleep state. @@ -1806,7 +2113,7 @@ p->p_flag &= ~P_STOPPED_SIG; p->p_flag |= P_CONTINUED; if (action == SIG_DFL) { - SIGDELSET(*siglist, sig); + sigqueue_delete(sigqueue, sig); } else if (action == SIG_CATCH) { /* * The process wants to catch it so it needs @@ -1836,7 +2143,7 @@ * Just make sure the signal STOP bit set. */ p->p_flag |= P_STOPPED_SIG; - SIGDELSET(*siglist, sig); + sigqueue_delete(sigqueue, sig); goto out; } @@ -1885,11 +2192,10 @@ } thread_stopped(p); if (p->p_numthreads == p->p_suspcount) { - SIGDELSET(p->p_siglist, p->p_xstat); - FOREACH_THREAD_IN_PROC(p, td0) - SIGDELSET(td0->td_siglist, p->p_xstat); - } - mtx_unlock_spin(&sched_lock); + mtx_unlock_spin(&sched_lock); + sigqueue_delete_proc(p, p->p_xstat); + } else + mtx_unlock_spin(&sched_lock); goto out; } else @@ -1897,7 +2203,7 @@ /* NOTREACHED */ } else { /* Not in "NORMAL" state. discard the signal. */ - SIGDELSET(*siglist, sig); + sigqueue_delete(sigqueue, sig); goto out; } @@ -1914,6 +2220,7 @@ out: /* If we jump here, sched_lock should not be owned. */ mtx_assert(&sched_lock, MA_NOTOWNED); + return (ret); } /* @@ -1957,12 +2264,14 @@ * be awakened. */ if ((prop & SA_CONT) && action == SIG_DFL) { - SIGDELSET(p->p_siglist, sig); + mtx_unlock_spin(&sched_lock); + sigqueue_delete(&p->p_sigqueue, sig); /* * It may be on either list in this state. * Remove from both for now. */ - SIGDELSET(td->td_siglist, sig); + sigqueue_delete(&td->td_sigqueue, sig); + mtx_lock_spin(&sched_lock); return; } @@ -2074,7 +2383,7 @@ for (;;) { int traced = (p->p_flag & P_TRACED) || (p->p_stops & S_SIG); - sigpending = td->td_siglist; + sigpending = td->td_sigqueue.sq_signals; SIGSETNAND(sigpending, td->td_sigmask); if (p->p_flag & P_PPWAIT) @@ -2094,7 +2403,7 @@ * only if P_TRACED was on when they were posted. */ if (SIGISMEMBER(ps->ps_sigignore, sig) && (traced == 0)) { - SIGDELSET(td->td_siglist, sig); + sigqueue_delete(&td->td_sigqueue, sig); if (td->td_pflags & TDP_SA) SIGADDSET(td->td_sigmask, sig); continue; @@ -2107,35 +2416,38 @@ newsig = ptracestop(td, sig); mtx_lock(&ps->ps_mtx); + if (sig == newsig) + continue; /* * If parent wants us to take the signal, * then it will leave it in p->p_xstat; * otherwise we just look for signals again. */ - SIGDELSET(td->td_siglist, sig); /* clear old signal */ + sigqueue_delete(&td->td_sigqueue, sig); /* clear old signal */ if (td->td_pflags & TDP_SA) SIGADDSET(td->td_sigmask, sig); if (newsig == 0) continue; sig = newsig; - /* - * If the traced bit got turned off, go back up - * to the top to rescan signals. This ensures - * that p_sig* and p_sigact are consistent. - */ - if ((p->p_flag & P_TRACED) == 0) - continue; /* - * Put the new signal into td_siglist. If the + * Put the new signal into td_sigqueue. If the * signal is being masked, look for other signals. */ - SIGADDSET(td->td_siglist, sig); + sigqueue_add(&td->td_sigqueue, sig, NULL); if (td->td_pflags & TDP_SA) SIGDELSET(td->td_sigmask, sig); if (SIGISMEMBER(td->td_sigmask, sig)) continue; signotify(td); + + /* + * If the traced bit got turned off, go back up + * to the top to rescan signals. This ensures + * that p_sig* and p_sigact are consistent. + */ + if ((p->p_flag & P_TRACED) == 0) + continue; } prop = sigprop(sig); @@ -2228,7 +2540,7 @@ */ return (sig); } - SIGDELSET(td->td_siglist, sig); /* take the signal! */ + sigqueue_delete(&td->td_sigqueue, sig); /* take the signal! */ } /* NOTREACHED */ } @@ -2284,6 +2596,7 @@ register struct proc *p = td->td_proc; struct sigacts *ps; sig_t action; + ksiginfo_t ksi; sigset_t returnmask; int code; @@ -2292,7 +2605,9 @@ PROC_LOCK_ASSERT(p, MA_OWNED); ps = p->p_sigacts; mtx_assert(&ps->ps_mtx, MA_OWNED); - SIGDELSET(td->td_siglist, sig); + sigqueue_get(&td->td_sigqueue, sig, &ksi); + ksi.ksi_signo = sig; + action = ps->ps_sigact[_SIG_IDX(sig)]; #ifdef KTRACE if (KTRPOINT(td, KTR_PSIG)) @@ -2364,10 +2679,9 @@ p->p_sig = 0; } if (td->td_pflags & TDP_SA) - thread_signal_add(curthread, sig); + thread_signal_add(curthread, &ksi); else - (*p->p_sysent->sv_sendsig)(action, sig, - &returnmask, code); + (*p->p_sysent->sv_sendsig)(action, &ksi, &returnmask); } } Index: kern/kern_thr.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_thr.c,v retrieving revision 1.34 diff -u -r1.34 kern_thr.c --- kern/kern_thr.c 10 Jul 2005 23:31:10 -0000 1.34 +++ kern/kern_thr.c 11 Oct 2005 06:34:12 -0000 @@ -279,6 +279,7 @@ suword((void *)uap->state, 1); PROC_LOCK(p); + sigqueue_flush(&td->td_sigqueue); mtx_lock_spin(&sched_lock); /* @@ -319,7 +320,7 @@ error = EINVAL; goto out; } - tdsignal(ttd, uap->sig, SIGTARGET_TD); + tdsignal(ttd, uap->sig, NULL, SIGTARGET_TD); out: PROC_UNLOCK(p); return (error); Index: kern/kern_thread.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_thread.c,v retrieving revision 1.217 diff -u -r1.217 kern_thread.c --- kern/kern_thread.c 30 Sep 2005 06:09:41 -0000 1.217 +++ kern/kern_thread.c 11 Oct 2005 06:34:12 -0000 @@ -277,6 +277,7 @@ TAILQ_INIT(&p->p_ksegrps); /* all ksegrps in proc */ TAILQ_INIT(&p->p_threads); /* all threads in proc */ TAILQ_INIT(&p->p_suspended); /* Threads suspended */ + sigqueue_init(&p->p_sigqueue, p); p->p_numksegrps = 0; p->p_numthreads = 0; @@ -454,6 +455,7 @@ KASSERT(kg != NULL, ("thread exiting without a kse group")); CTR3(KTR_PROC, "thread_exit: thread %p (pid %ld, %s)", td, (long)p->p_pid, p->p_comm); + KASSERT(TAILQ_EMPTY(&td->td_sigqueue.sq_list), ("signal pending")); if (td->td_standin != NULL) { /* @@ -625,6 +627,7 @@ td->td_kflags = 0; LIST_INIT(&td->td_contested); + sigqueue_init(&td->td_sigqueue, p); callout_init(&td->td_slpcallout, CALLOUT_MPSAFE); TAILQ_INSERT_HEAD(&p->p_threads, td, td_plist); TAILQ_INSERT_HEAD(&kg->kg_threads, td, td_kglist); @@ -875,6 +878,10 @@ (p->p_flag & P_SINGLE_BOUNDARY) && return_instead) return (1); + /* If thread will exit, flush its pending signals */ + if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td)) + sigqueue_flush(&td->td_sigqueue); + mtx_lock_spin(&sched_lock); thread_stopped(p); /* Index: kern/subr_trap.c =================================================================== RCS file: /home/ncvs/src/sys/kern/subr_trap.c,v retrieving revision 1.281 diff -u -r1.281 subr_trap.c --- kern/subr_trap.c 28 Mar 2005 12:52:46 -0000 1.281 +++ kern/subr_trap.c 11 Oct 2005 06:34:12 -0000 @@ -155,6 +155,7 @@ int sig; #if defined(DEV_NPX) && !defined(SMP) int ucode; + ksiginfo_t ksi; #endif td = curthread; @@ -217,7 +218,10 @@ PCB_NPXTRAP); ucode = npxtrap(); if (ucode != -1) { - trapsignal(td, SIGFPE, ucode); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGFPE; + ksi.ksi_code = ucode; + trapsignal(td, &ksi); } } #endif Index: kern/syscalls.c =================================================================== RCS file: /home/ncvs/src/sys/kern/syscalls.c,v retrieving revision 1.182 diff -u -r1.182 syscalls.c --- kern/syscalls.c 27 Sep 2005 14:36:58 -0000 1.182 +++ kern/syscalls.c 11 Oct 2005 06:34:13 -0000 @@ -2,7 +2,7 @@ * System call names. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/kern/syscalls.c,v 1.182 2005/09/27 14:36:58 csjp Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.199 2005/09/27 14:32:04 csjp Exp */ @@ -463,4 +463,5 @@ "auditctl", /* 453 = auditctl */ "_umtx_op", /* 454 = _umtx_op */ "thr_new", /* 455 = thr_new */ + "sigqueue", /* 456 = sigqueue */ }; Index: kern/syscalls.master =================================================================== RCS file: /home/ncvs/src/sys/kern/syscalls.master,v retrieving revision 1.199 diff -u -r1.199 syscalls.master --- kern/syscalls.master 27 Sep 2005 14:32:04 -0000 1.199 +++ kern/syscalls.master 11 Oct 2005 06:34:13 -0000 @@ -793,6 +793,6 @@ long id, void *uaddr, void *uaddr2); } 455 AUE_NULL MSTD { int thr_new(struct thr_param *param, \ int param_size); } - +456 AUE_NULL MSTD { int sigqueue(pid_t pid, int signum, void *value); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master Index: pc98/pc98/machdep.c =================================================================== RCS file: /home/ncvs/src/sys/pc98/pc98/machdep.c,v retrieving revision 1.365 diff -u -r1.365 machdep.c --- pc98/pc98/machdep.c 14 Sep 2005 12:42:39 -0000 1.365 +++ pc98/pc98/machdep.c 11 Oct 2005 06:34:19 -0000 @@ -177,11 +177,10 @@ int cold = 1; #ifdef COMPAT_43 -static void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code); +static void osendsig(sig_t catcher, ksiginfo_t *, sigset_t *mask); #endif #ifdef COMPAT_FREEBSD4 -static void freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, - u_long code); +static void freebsd4_sendsig(sig_t catcher, ksiginfo_t *, sigset_t *mask) #endif long Maxmem = 0; @@ -267,11 +266,7 @@ */ #ifdef COMPAT_43 static void -osendsig(catcher, sig, mask, code) - sig_t catcher; - int sig; - sigset_t *mask; - u_long code; +osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct osigframe sf, *fp; struct proc *p; @@ -279,10 +274,14 @@ struct sigacts *psp; struct trapframe *regs; int oonstack; + int sig; + int code; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + sig = ksi->ksi_signo; + code = ksi->ksi_code; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); regs = td->td_frame; @@ -311,6 +310,7 @@ sf.sf_arg2 = (register_t)&fp->sf_siginfo; sf.sf_siginfo.si_signo = sig; sf.sf_siginfo.si_code = code; + sf.sf_siginfo.sf_value = ksi->ksi_value; sf.sf_ahu.sf_action = (__osiginfohandler_t *)catcher; } else { /* Old FreeBSD-style arguments. */ @@ -721,8 +721,12 @@ return (EINVAL); /* Go back to user mode if both flags are set. */ - if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) - trapsignal(td, SIGBUS, 0); + if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) { + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); + } if (vm86->vm86_has_vme) { eflags = (tf->tf_eflags & ~VME_USERCHANGE) | @@ -763,7 +767,12 @@ * other selectors, invalid %eip's and invalid %esp's. */ if (!CS_SECURE(scp->sc_cs)) { - trapsignal(td, SIGBUS, T_PROTFLT); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_code = BUS_OBJERR; + ksi.ksi_trap = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); return (EINVAL); } regs->tf_ds = scp->sc_ds; @@ -839,8 +848,12 @@ return (EINVAL); /* Go back to user mode if both flags are set. */ - if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) - trapsignal(td, SIGBUS, 0); + if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) { + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); + } if (vm86->vm86_has_vme) { eflags = (tf->tf_eflags & ~VME_USERCHANGE) | @@ -886,7 +899,12 @@ cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { printf("freebsd4_sigreturn: cs = 0x%x\n", cs); - trapsignal(td, SIGBUS, T_PROTFLT); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_code = BUS_OBJERR; + ksi.ksi_trap = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); return (EINVAL); } @@ -946,8 +964,12 @@ return (EINVAL); /* Go back to user mode if both flags are set. */ - if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) - trapsignal(td, SIGBUS, 0); + if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) { + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); + } if (vm86->vm86_has_vme) { eflags = (tf->tf_eflags & ~VME_USERCHANGE) | @@ -993,7 +1015,12 @@ cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { printf("sigreturn: cs = 0x%x\n", cs); - trapsignal(td, SIGBUS, T_PROTFLT); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_code = BUS_OBJERR; + ksi.ksi_trap = T_PROTFLT; + ksi.ksi_addr = (void *)regs->tf_eip; + trapsignal(td, &ksi); return (EINVAL); } Index: powerpc/powerpc/machdep.c =================================================================== RCS file: /home/ncvs/src/sys/powerpc/powerpc/machdep.c,v retrieving revision 1.90 diff -u -r1.90 machdep.c --- powerpc/powerpc/machdep.c 30 Jul 2005 11:14:31 -0000 1.90 +++ powerpc/powerpc/machdep.c 11 Oct 2005 06:34:19 -0000 @@ -432,7 +432,7 @@ } void -sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct trapframe *tf; struct sigframe *sfp; @@ -441,10 +441,14 @@ struct thread *td; struct proc *p; int oonstack, rndfsize; + int sig; + int code; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + sig = ksi->ksi_signo; + code = ksi->ksi_code; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); tf = td->td_frame; @@ -512,9 +516,9 @@ /* * Fill siginfo structure. */ + sf.sf_si = ksi->ksi_info; sf.sf_si.si_signo = sig; - sf.sf_si.si_code = code; - sf.sf_si.si_addr = (void *)tf->srr0; + sf.sf_si.si_addr = (void *)tf->srr0; /* XXX */ } else { /* Old FreeBSD-style arguments. */ tf->fixreg[FIRSTARG+1] = code; @@ -543,25 +547,6 @@ mtx_lock(&psp->ps_mtx); } -/* - * Build siginfo_t for SA thread - */ -void -cpu_thread_siginfo(int sig, u_long code, siginfo_t *si) -{ - struct proc *p; - struct thread *td; - - td = curthread; - p = td->td_proc; - PROC_LOCK_ASSERT(p, MA_OWNED); - - bzero(si, sizeof(*si)); - si->si_signo = sig; - si->si_code = code; - /* XXXKSE fill other fields */ -} - int sigreturn(struct thread *td, struct sigreturn_args *uap) { Index: powerpc/powerpc/trap.c =================================================================== RCS file: /home/ncvs/src/sys/powerpc/powerpc/trap.c,v retrieving revision 1.55 diff -u -r1.55 trap.c --- powerpc/powerpc/trap.c 30 Jul 2005 11:14:31 -0000 1.55 +++ powerpc/powerpc/trap.c 11 Oct 2005 06:34:20 -0000 @@ -144,6 +144,7 @@ struct proc *p; int sig, type, user; u_int sticks, ucode; + ksiginfo_t ksi; PCPU_LAZY_INC(cnt.v_trap); @@ -254,7 +255,12 @@ if (sig != 0) { if (p->p_sysent->sv_transtrap != NULL) sig = (p->p_sysent->sv_transtrap)(sig, type); - trapsignal(td, sig, ucode); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = sig; + ksi.ksi_code = (int) ucode; /* XXX, not POSIX */ + /* ksi.ksi_addr = ? */ + ksi.ksi_trap = type; + trapsignal(td, &ksi); } userret(td, frame, sticks); Index: sparc64/sparc64/machdep.c =================================================================== RCS file: /home/ncvs/src/sys/sparc64/sparc64/machdep.c,v retrieving revision 1.125 diff -u -r1.125 machdep.c --- sparc64/sparc64/machdep.c 16 Apr 2005 15:00:09 -0000 1.125 +++ sparc64/sparc64/machdep.c 11 Oct 2005 06:34:21 -0000 @@ -447,7 +447,7 @@ } void -sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) { struct trapframe *tf; struct sigframe *sfp; @@ -458,11 +458,15 @@ struct proc *p; int oonstack; u_long sp; + int sig; + int code; oonstack = 0; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); + sig = ksi->ksi_signo; + code = ksi->ksi_code; psp = p->p_sigacts; mtx_assert(&psp->ps_mtx, MA_OWNED); tf = td->td_frame; @@ -513,9 +517,8 @@ tf->tf_out[2] = (register_t)&sfp->sf_uc; tf->tf_out[4] = (register_t)catcher; /* Fill siginfo structure. */ - sf.sf_si.si_signo = sig; - sf.sf_si.si_code = code; - sf.sf_si.si_addr = (void *)tf->tf_sfar; + sf.sf_si = ksi->ksi_info; + sf.sf_si.si_addr = (void *)tf->tf_sfar; /* XXX */ /* Copy the sigframe out to the user's stack. */ if (rwindow_save(td) != 0 || copyout(&sf, sfp, sizeof(*sfp)) != 0 || @@ -541,25 +544,6 @@ mtx_lock(&psp->ps_mtx); } -/* - * Build siginfo_t for SA thread - */ -void -cpu_thread_siginfo(int sig, u_long code, siginfo_t *si) -{ - struct proc *p; - struct thread *td; - - td = curthread; - p = td->td_proc; - PROC_LOCK_ASSERT(p, MA_OWNED); - - bzero(si, sizeof(*si)); - si->si_signo = sig; - si->si_code = code; - /* XXXKSE fill other fields */ -} - #ifndef _SYS_SYSPROTO_H_ struct sigreturn_args { ucontext_t *ucp; Index: sparc64/sparc64/trap.c =================================================================== RCS file: /home/ncvs/src/sys/sparc64/sparc64/trap.c,v retrieving revision 1.74 diff -u -r1.74 trap.c --- sparc64/sparc64/trap.c 12 Apr 2005 23:18:54 -0000 1.74 +++ sparc64/sparc64/trap.c 11 Oct 2005 06:34:21 -0000 @@ -233,6 +233,7 @@ u_int sticks; int error; int sig; + ksiginfo_t ksi; td = PCPU_GET(curthread); @@ -284,7 +285,12 @@ if (debugger_on_signal && (sig == 4 || sig == 10 || sig == 11)) kdb_enter("trapsig"); - trapsignal(td, sig, tf->tf_type); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = sig; + ksi.ksi_code = (int)tf->tf_type; /* XXX not POSIX */ + /* ksi.ksi_addr = ? */ + ksi.ksi_trap = (int)tf->tf_type; + trapsignal(td, &ksi); } userret(td, tf, sticks); Index: sys/proc.h =================================================================== RCS file: /home/ncvs/src/sys/sys/proc.h,v retrieving revision 1.436 diff -u -r1.436 proc.h --- sys/proc.h 30 Sep 2005 01:30:01 -0000 1.436 +++ sys/proc.h 11 Oct 2005 06:34:23 -0000 @@ -51,6 +51,7 @@ #include #include #include +#include #ifndef _KERNEL #include /* For structs itimerval, timeval. */ #else @@ -253,6 +254,8 @@ struct turnstile *td_turnstile; /* (k) Associated turnstile. */ struct umtx_q *td_umtxq; /* (c?) Link for when we're blocked. */ lwpid_t td_tid; /* (b) Thread ID. */ + sigqueue_t td_sigqueue; /* (c) Sigs arrived, not delivered. */ +#define td_siglist td_sigqueue.sq_signals /* Cleared during fork1() or thread_schedule_upcall(). */ #define td_startzero td_flags @@ -283,7 +286,6 @@ int td_intrval; /* (j) Return value of TDF_INTERRUPT. */ sigset_t td_oldsigmask; /* (k) Saved mask from pre sigpause. */ sigset_t td_sigmask; /* (c) Current signal mask. */ - sigset_t td_siglist; /* (c) Sigs arrived, not delivered. */ volatile u_int td_generation; /* (k) For detection of preemption */ stack_t td_sigstk; /* (k) Stack ptr and on-stack flag. */ int td_kflags; /* (c) Flags for KSE threading. */ @@ -544,6 +546,8 @@ LIST_ENTRY(proc) p_sibling; /* (e) List of sibling processes. */ LIST_HEAD(, proc) p_children; /* (e) Pointer to list of children. */ struct mtx p_mtx; /* (n) Lock for this struct. */ + sigqueue_t p_sigqueue; /* (c) Sigs not delivered to a td. */ +#define p_siglist p_sigqueue.sq_signals /* The following fields are all zeroed upon creation in fork. */ #define p_startzero p_oppid @@ -559,7 +563,6 @@ struct vnode *p_tracevp; /* (c + o) Trace to vnode. */ struct ucred *p_tracecred; /* (o) Credentials to trace with. */ struct vnode *p_textvp; /* (b) Vnode of executable. */ - sigset_t p_siglist; /* (c) Sigs not delivered to a td. */ char p_lock; /* (c) Proclock (prevent swap) count. */ struct sigiolst p_sigiolst; /* (c) List of sigio sources. */ int p_sigparent; /* (c) Signal to parent on exit. */ @@ -576,6 +579,7 @@ struct thread *p_xthread; /* (c) Trap thread */ int p_boundary_count;/* (c) Num threads at user boundary */ struct ksegrp *p_procscopegrp; + int p_pendingcnt; /* how many signals are pending */ /* End area that is zeroed on creation. */ #define p_endzero p_magic @@ -908,7 +912,6 @@ void cpu_thread_clean(struct thread *); void cpu_thread_exit(struct thread *); void cpu_thread_setup(struct thread *td); -void cpu_thread_siginfo(int sig, u_long code, siginfo_t *si); void cpu_thread_swapin(struct thread *); void cpu_thread_swapout(struct thread *); void ksegrp_link(struct ksegrp *kg, struct proc *p); @@ -921,7 +924,7 @@ void thread_link(struct thread *td, struct ksegrp *kg); void thread_reap(void); struct thread *thread_schedule_upcall(struct thread *td, struct kse_upcall *ku); -void thread_signal_add(struct thread *td, int sig); +void thread_signal_add(struct thread *td, ksiginfo_t *); int thread_single(int how); void thread_single_end(void); int thread_sleep_check(struct thread *td); Index: sys/signal.h =================================================================== RCS file: /home/ncvs/src/sys/sys/signal.h,v retrieving revision 1.46 diff -u -r1.46 signal.h --- sys/signal.h 20 Aug 2005 16:44:41 -0000 1.46 +++ sys/signal.h 11 Oct 2005 06:34:23 -0000 @@ -111,9 +111,9 @@ #if __BSD_VISIBLE #define SIGTHR 32 /* Thread interrupt. */ #endif -/* - * XXX missing SIGRTMIN, SIGRTMAX. - */ + +#define SIGRTMIN 65 +#define SIGRTMAX 128 #define SIG_DFL ((__sighandler_t *)0) #define SIG_IGN ((__sighandler_t *)1) @@ -199,8 +199,63 @@ void *si_addr; /* faulting instruction */ union sigval si_value; /* signal value */ long si_band; /* band event for SIGPOLL */ - int __spare__[7]; /* gimme some slack */ + int si_trap; /* machine specific trap code */ + int __spare__[6]; /* gimme some slack */ } siginfo_t; + +/** si_code **/ +/* codes for SIGILL */ +#define ILL_ILLOPC 1 +#define ILL_ILLOPN 2 +#define ILL_ILLADR 3 +#define ILL_ILLTRP 4 +#define ILL_PRVOPC 5 +#define ILL_PRVREG 6 +#define ILL_COPROC 7 +#define ILL_BADSTK 8 + +/* codes for SIGBUS */ +#define BUS_ADRALN 1 +#define BUS_ADRERR 2 +#define BUS_OBJERR 3 +#define BUS_RESERVED 4 + +/* codes for SIGSEGV */ +#define SEGV_MAPERR 1 +#define SEGV_ACCERR 2 + +/* codes for SIGFPE */ +#define FPE_INTOVF 1 /* integer overflow */ +#define FPE_INTDIV 2 /* integer divide by zero */ +#define FPE_FLTDIV 3 /* floating point divide by zero */ +#define FPE_FLTOVF 4 /* floating point overflow */ +#define FPE_FLTUND 5 /* floating point underflow */ +#define FPE_FLTRES 6 /* floating point inexact result */ +#define FPE_FLTINV 7 /* invalid floating point operation */ +#define FPE_FLTSUB 8 /* subscript out of range */ + +/* codes for SIGTRAP */ +#define TRAP_BRKPT 1 +#define TRAP_TRACE 2 + +/* SIGCHLD */ +#define CLD_EXITED 1 /* Child has exited */ +#define CLD_KILLED 2 /* Child has terminated abnormally but */ + /* did not create a core file */ +#define CLD_DUMPED 3 /* Child has terminated abnormally and */ + /* created a core file */ +#define CLD_TRAPPED 4 /* Traced child has trapped */ +#define CLD_STOPPED 5 /* Child has stopped */ +#define CLD_CONTINUED 6 /* Stopped child has continued */ + +/* SIGPOLL */ +#define POLL_IN 1 /* Data input available */ +#define POLL_OUT 2 /* Output buffers available */ +#define POLL_MSG 3 /* Input message available */ +#define POLL_ERR 4 /* I/O Error */ +#define POLL_PRI 5 /* High priority input available */ +#define POLL_HUP 4 /* Device disconnected */ + #endif #if __POSIX_VISIBLE || __XSI_VISIBLE Index: sys/signalvar.h =================================================================== RCS file: /home/ncvs/src/sys/sys/signalvar.h,v retrieving revision 1.68 diff -u -r1.68 signalvar.h --- sys/signalvar.h 7 Jan 2005 02:29:24 -0000 1.68 +++ sys/signalvar.h 11 Oct 2005 06:34:23 -0000 @@ -199,6 +199,39 @@ return (1); } +typedef struct ksiginfo { + TAILQ_ENTRY(ksiginfo) ksi_link; + siginfo_t ksi_info; + int ksi_flags; +} ksiginfo_t; + +#define ksi_signo ksi_info.si_signo +#define ksi_errno ksi_info.si_errno +#define ksi_code ksi_info.si_code +#define ksi_pid ksi_info.si_pid +#define ksi_uid ksi_info.si_uid +#define ksi_status ksi_info.si_status +#define ksi_addr ksi_info.si_addr +#define ksi_value ksi_info.si_value +#define ksi_band ksi_info.si_band +#define ksi_trap ksi_info.si_trap +#define ksi__spare__ ksi_info.__spare__ + +/* bits for ksi_flags */ +#define KSI_TRAP 0x01 /* generated by trap */ +#define KSI_KILL 0x02 /* generated by kill() syscall */ +#define KSI_SIGQUEUE 0x04 /* generated by sigqueue() syscall */ + +typedef struct sigqueue { + sigset_t sq_signals; + TAILQ_HEAD(, ksiginfo) sq_list; + struct proc *sq_proc; + int sq_flags; +} sigqueue_t; + +/* Flags for sig_flags */ +#define SQ_INIT 0x01 + #ifdef _KERNEL /* @@ -230,6 +263,25 @@ return (1); } +#define ksiginfo_init(ksi) \ +do { \ + bzero(ksi, sizeof(ksiginfo_t)); \ +} while(0) + +#define ksiginfo_init_trap(ksi) \ +do { \ + ksiginfo_t *kp = ksi; \ + bzero(kp, sizeof(ksiginfo_t)); \ + kp->ksi_flags |= KSI_TRAP; \ +} while(0) + +static __inline void +ksiginfo_copy(ksiginfo_t *src, ksiginfo_t *dst) +{ + (dst)->ksi_info = src->ksi_info; + (dst)->ksi_flags = src->ksi_flags; +} + struct pgrp; struct thread; struct proc; @@ -269,14 +321,27 @@ int sig_ffs(sigset_t *set); void siginit(struct proc *p); void signotify(struct thread *td); -void tdsignal(struct thread *td, int sig, sigtarget_t target); -void trapsignal(struct thread *td, int sig, u_long code); +int tdsignal(struct thread *td, int sig, ksiginfo_t *ksi, + sigtarget_t target); +void trapsignal(struct thread *td, ksiginfo_t *); int ptracestop(struct thread *td, int sig); +void sigqueue_init(struct sigqueue *queue, struct proc *p); +void sigqueue_flush(struct sigqueue *queue); +void sigqueue_delete_proc(struct proc *p, int sig); +void sigqueue_delete_set(struct sigqueue *queue, sigset_t *set); +void sigqueue_delete(struct sigqueue *queue, int sig); +void sigqueue_move_set(struct sigqueue *src, sigqueue_t *dst, sigset_t *); +int sigqueue_get(struct sigqueue *queue, int sig, ksiginfo_t *info); +int sigqueue_add(struct sigqueue *queue, int sig, ksiginfo_t *info); +void sigqueue_collect_set(struct sigqueue *queue, sigset_t *set); +void sigqueue_move(struct sigqueue *, struct sigqueue *, int sig); +void sigqueue_delete_set_proc(struct proc *, sigset_t *); +void sigqueue_delete_stopmask_proc(struct proc *); /* * Machine-dependent functions: */ -void sendsig(sig_t action, int sig, sigset_t *retmask, u_long code); +void sendsig(sig_t, ksiginfo_t *, sigset_t *retmask); #endif /* _KERNEL */ Index: sys/syscall.h =================================================================== RCS file: /home/ncvs/src/sys/sys/syscall.h,v retrieving revision 1.179 diff -u -r1.179 syscall.h --- sys/syscall.h 27 Sep 2005 14:36:59 -0000 1.179 +++ sys/syscall.h 11 Oct 2005 06:34:24 -0000 @@ -2,7 +2,7 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/sys/syscall.h,v 1.179 2005/09/27 14:36:59 csjp Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.199 2005/09/27 14:32:04 csjp Exp */ @@ -371,4 +371,5 @@ #define SYS_auditctl 453 #define SYS__umtx_op 454 #define SYS_thr_new 455 -#define SYS_MAXSYSCALL 456 +#define SYS_sigqueue 456 +#define SYS_MAXSYSCALL 457 Index: sys/syscall.mk =================================================================== RCS file: /home/ncvs/src/sys/sys/syscall.mk,v retrieving revision 1.134 diff -u -r1.134 syscall.mk --- sys/syscall.mk 27 Sep 2005 14:36:59 -0000 1.134 +++ sys/syscall.mk 11 Oct 2005 06:34:24 -0000 @@ -1,6 +1,6 @@ # FreeBSD system call names. # DO NOT EDIT-- this file is automatically generated. -# $FreeBSD: src/sys/sys/syscall.mk,v 1.134 2005/09/27 14:36:59 csjp Exp $ +# $FreeBSD$ # created from FreeBSD: src/sys/kern/syscalls.master,v 1.199 2005/09/27 14:32:04 csjp Exp MIASM = \ syscall.o \ @@ -312,4 +312,5 @@ setaudit_addr.o \ auditctl.o \ _umtx_op.o \ - thr_new.o + thr_new.o \ + sigqueue.o Index: sys/sysent.h =================================================================== RCS file: /home/ncvs/src/sys/sys/sysent.h,v retrieving revision 1.45 diff -u -r1.45 sysent.h --- sys/sysent.h 29 May 2005 20:08:39 -0000 1.45 +++ sys/sysent.h 11 Oct 2005 06:34:24 -0000 @@ -35,6 +35,7 @@ #include struct thread; +struct ksiginfo; typedef int sy_call_t(struct thread *, void *); @@ -64,8 +65,8 @@ /* translate trap-to-signal mapping */ int (*sv_fixup)(register_t **, struct image_params *); /* stack fixup function */ - void (*sv_sendsig)(void (*)(int), int, struct __sigset *, - u_long); /* send signal */ + void (*sv_sendsig)(void (*)(int), struct ksiginfo *, struct __sigset *); + /* send signal */ char *sv_sigcode; /* start of sigtramp code */ int *sv_szsigcode; /* size of sigtramp code */ void (*sv_prepsyscall)(struct trapframe *, int *, u_int *, Index: sys/sysproto.h =================================================================== RCS file: /home/ncvs/src/sys/sys/sysproto.h,v retrieving revision 1.178 diff -u -r1.178 sysproto.h --- sys/sysproto.h 27 Sep 2005 14:36:59 -0000 1.178 +++ sys/sysproto.h 11 Oct 2005 06:34:28 -0000 @@ -2,7 +2,7 @@ * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/sys/sysproto.h,v 1.178 2005/09/27 14:36:59 csjp Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.199 2005/09/27 14:32:04 csjp Exp */ @@ -1365,6 +1365,11 @@ char param_l_[PADL_(struct thr_param *)]; struct thr_param * param; char param_r_[PADR_(struct thr_param *)]; char param_size_l_[PADL_(int)]; int param_size; char param_size_r_[PADR_(int)]; }; +struct sigqueue_args { + char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)]; + char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)]; + char value_l_[PADL_(void *)]; void * value; char value_r_[PADR_(void *)]; +}; int nosys(struct thread *, struct nosys_args *); void sys_exit(struct thread *, struct sys_exit_args *); int fork(struct thread *, struct fork_args *); @@ -1674,6 +1679,7 @@ int auditctl(struct thread *, struct auditctl_args *); int _umtx_op(struct thread *, struct _umtx_op_args *); int thr_new(struct thread *, struct thr_new_args *); +int sigqueue(struct thread *, struct sigqueue_args *); #ifdef COMPAT_43