version 1.254, 2007/07/09 21:10:53 |
version 1.254.6.7, 2007/12/09 19:38:19 |
|
|
#include <sys/cdefs.h> |
#include <sys/cdefs.h> |
__KERNEL_RCSID(0, "$NetBSD$"); |
__KERNEL_RCSID(0, "$NetBSD$"); |
|
|
#include "opt_ktrace.h" |
|
#include "opt_ptrace.h" |
#include "opt_ptrace.h" |
#include "opt_multiprocessor.h" |
#include "opt_multiprocessor.h" |
#include "opt_compat_sunos.h" |
#include "opt_compat_sunos.h" |
Line 100 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 99 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/kauth.h> |
#include <sys/kauth.h> |
#include <sys/acct.h> |
#include <sys/acct.h> |
#include <sys/callout.h> |
#include <sys/callout.h> |
|
#include <sys/atomic.h> |
#include <machine/cpu.h> |
#include <sys/cpu.h> |
|
|
#ifdef PAX_SEGVGUARD |
#ifdef PAX_SEGVGUARD |
#include <sys/pax.h> |
#include <sys/pax.h> |
Line 145 static const char lognocoredump[] = |
|
Line 144 static const char lognocoredump[] = |
|
POOL_INIT(siginfo_pool, sizeof(siginfo_t), 0, 0, 0, "siginfo", |
POOL_INIT(siginfo_pool, sizeof(siginfo_t), 0, 0, 0, "siginfo", |
&pool_allocator_nointr, IPL_NONE); |
&pool_allocator_nointr, IPL_NONE); |
POOL_INIT(ksiginfo_pool, sizeof(ksiginfo_t), 0, 0, 0, "ksiginfo", |
POOL_INIT(ksiginfo_pool, sizeof(ksiginfo_t), 0, 0, 0, "ksiginfo", |
NULL, IPL_SOFTCLOCK); |
NULL, IPL_VM); |
|
|
/* |
/* |
* signal_init: |
* signal_init: |
Line 205 sigacts_poolpage_free(struct pool *pp, v |
|
Line 204 sigacts_poolpage_free(struct pool *pp, v |
|
struct sigacts * |
struct sigacts * |
sigactsinit(struct proc *pp, int share) |
sigactsinit(struct proc *pp, int share) |
{ |
{ |
struct sigacts *ps; |
struct sigacts *ps, *ps2; |
|
|
if (pp != NULL) { |
ps = pp->p_sigacts; |
KASSERT(mutex_owned(&pp->p_smutex)); |
|
} |
|
|
|
if (share) { |
if (share) { |
ps = pp->p_sigacts; |
|
mutex_enter(&ps->sa_mutex); |
mutex_enter(&ps->sa_mutex); |
ps->sa_refcnt++; |
ps->sa_refcnt++; |
mutex_exit(&ps->sa_mutex); |
mutex_exit(&ps->sa_mutex); |
|
ps2 = ps; |
} else { |
} else { |
if (pp) |
ps2 = pool_get(&sigacts_pool, PR_WAITOK); |
mutex_exit(&pp->p_smutex); |
/* XXX IPL_SCHED to match p_smutex */ |
ps = pool_get(&sigacts_pool, PR_WAITOK); |
mutex_init(&ps2->sa_mutex, MUTEX_DEFAULT, IPL_SCHED); |
mutex_init(&ps->sa_mutex, MUTEX_SPIN, IPL_NONE); |
mutex_enter(&ps->sa_mutex); |
if (pp) { |
memcpy(&ps2->sa_sigdesc, ps->sa_sigdesc, |
mutex_enter(&pp->p_smutex); |
sizeof(ps2->sa_sigdesc)); |
memcpy(&ps->sa_sigdesc, pp->p_sigacts->sa_sigdesc, |
mutex_exit(&ps->sa_mutex); |
sizeof(ps->sa_sigdesc)); |
ps2->sa_refcnt = 1; |
} else |
|
memset(&ps->sa_sigdesc, 0, sizeof(ps->sa_sigdesc)); |
|
ps->sa_refcnt = 1; |
|
} |
} |
|
|
return ps; |
return ps2; |
} |
} |
|
|
/* |
/* |
|
|
sigactsunshare(struct proc *p) |
sigactsunshare(struct proc *p) |
{ |
{ |
struct sigacts *ps, *oldps; |
struct sigacts *ps, *oldps; |
int refcnt; |
|
|
|
KASSERT(mutex_owned(&p->p_smutex)); |
|
|
|
oldps = p->p_sigacts; |
oldps = p->p_sigacts; |
|
if (oldps->sa_refcnt == 1) |
mutex_enter(&oldps->sa_mutex); |
|
refcnt = oldps->sa_refcnt; |
|
mutex_exit(&oldps->sa_mutex); |
|
if (refcnt == 1) |
|
return; |
return; |
|
ps = pool_get(&sigacts_pool, PR_WAITOK); |
mutex_exit(&p->p_smutex); |
/* XXX IPL_SCHED to match p_smutex */ |
ps = sigactsinit(NULL, 0); |
mutex_init(&ps->sa_mutex, MUTEX_DEFAULT, IPL_SCHED); |
mutex_enter(&p->p_smutex); |
memset(&ps->sa_sigdesc, 0, sizeof(ps->sa_sigdesc)); |
p->p_sigacts = ps; |
p->p_sigacts = ps; |
|
|
sigactsfree(oldps); |
sigactsfree(oldps); |
} |
} |
|
|
Line 351 execsigs(struct proc *p) |
|
Line 337 execsigs(struct proc *p) |
|
|
|
KASSERT(p->p_nlwps == 1); |
KASSERT(p->p_nlwps == 1); |
|
|
mutex_enter(&p->p_smutex); |
|
|
|
sigactsunshare(p); |
sigactsunshare(p); |
|
|
ps = p->p_sigacts; |
ps = p->p_sigacts; |
|
|
/* |
/* |
* Reset caught signals. Held signals remain held through |
* Reset caught signals. Held signals remain held through |
* l->l_sigmask (unless they were caught, and are now ignored |
* l->l_sigmask (unless they were caught, and are now ignored |
* by default). |
* by default). |
|
* |
|
* No need to lock yet, the process has only one LWP and |
|
* at this point the sigacts are private to the process. |
*/ |
*/ |
sigemptyset(&tset); |
sigemptyset(&tset); |
for (signo = 1; signo < NSIG; signo++) { |
for (signo = 1; signo < NSIG; signo++) { |
Line 378 execsigs(struct proc *p) |
|
Line 364 execsigs(struct proc *p) |
|
SIGACTION_PS(ps, signo).sa_flags = SA_RESTART; |
SIGACTION_PS(ps, signo).sa_flags = SA_RESTART; |
} |
} |
ksiginfo_queue_init(&kq); |
ksiginfo_queue_init(&kq); |
|
|
|
mutex_enter(&p->p_smutex); |
sigclearall(p, &tset, &kq); |
sigclearall(p, &tset, &kq); |
sigemptyset(&p->p_sigctx.ps_sigcatch); |
sigemptyset(&p->p_sigctx.ps_sigcatch); |
|
|
Line 398 execsigs(struct proc *p) |
|
Line 386 execsigs(struct proc *p) |
|
l->l_sigstk.ss_sp = 0; |
l->l_sigstk.ss_sp = 0; |
ksiginfo_queue_init(&l->l_sigpend.sp_info); |
ksiginfo_queue_init(&l->l_sigpend.sp_info); |
sigemptyset(&l->l_sigpend.sp_set); |
sigemptyset(&l->l_sigpend.sp_set); |
|
|
mutex_exit(&p->p_smutex); |
mutex_exit(&p->p_smutex); |
|
|
ksiginfo_queue_drain(&kq); |
ksiginfo_queue_drain(&kq); |
} |
} |
|
|
Line 449 ksiginfo_alloc(struct proc *p, ksiginfo_ |
|
Line 437 ksiginfo_alloc(struct proc *p, ksiginfo_ |
|
return ok; |
return ok; |
} |
} |
|
|
s = splsoftclock(); |
s = splvm(); |
kp = pool_get(&ksiginfo_pool, flags); |
kp = pool_get(&ksiginfo_pool, flags); |
splx(s); |
splx(s); |
if (kp == NULL) { |
if (kp == NULL) { |
Line 484 ksiginfo_free(ksiginfo_t *kp) |
|
Line 472 ksiginfo_free(ksiginfo_t *kp) |
|
|
|
if ((kp->ksi_flags & (KSI_QUEUED | KSI_FROMPOOL)) != KSI_FROMPOOL) |
if ((kp->ksi_flags & (KSI_QUEUED | KSI_FROMPOOL)) != KSI_FROMPOOL) |
return; |
return; |
s = splsoftclock(); |
s = splvm(); |
pool_put(&ksiginfo_pool, kp); |
pool_put(&ksiginfo_pool, kp); |
splx(s); |
splx(s); |
} |
} |
Line 506 ksiginfo_queue_drain0(ksiginfoq_t *kq) |
|
Line 494 ksiginfo_queue_drain0(ksiginfoq_t *kq) |
|
while (!CIRCLEQ_EMPTY(kq)) { |
while (!CIRCLEQ_EMPTY(kq)) { |
ksi = CIRCLEQ_FIRST(kq); |
ksi = CIRCLEQ_FIRST(kq); |
CIRCLEQ_REMOVE(kq, ksi, ksi_list); |
CIRCLEQ_REMOVE(kq, ksi, ksi_list); |
s = splsoftclock(); |
s = splvm(); |
pool_put(&ksiginfo_pool, ksi); |
pool_put(&ksiginfo_pool, ksi); |
splx(s); |
splx(s); |
} |
} |
Line 683 sigispending(struct lwp *l, int signo) |
|
Line 671 sigispending(struct lwp *l, int signo) |
|
struct proc *p = l->l_proc; |
struct proc *p = l->l_proc; |
sigset_t tset; |
sigset_t tset; |
|
|
mb_read(); |
membar_consumer(); |
|
|
tset = l->l_sigpend.sp_set; |
tset = l->l_sigpend.sp_set; |
sigplusset(&p->p_sigpend.sp_set, &tset); |
sigplusset(&p->p_sigpend.sp_set, &tset); |
Line 740 getucontext(struct lwp *l, ucontext_t *u |
|
Line 728 getucontext(struct lwp *l, ucontext_t *u |
|
* The (unsupplied) definition of the `current execution stack' |
* The (unsupplied) definition of the `current execution stack' |
* in the System V Interface Definition appears to allow returning |
* in the System V Interface Definition appears to allow returning |
* the main context stack. |
* the main context stack. |
* |
|
* XXXLWP this is borken for multiple LWPs. |
|
*/ |
*/ |
if ((l->l_sigstk.ss_flags & SS_ONSTACK) == 0) { |
if ((l->l_sigstk.ss_flags & SS_ONSTACK) == 0) { |
ucp->uc_stack.ss_sp = (void *)USRSTACK; |
ucp->uc_stack.ss_sp = (void *)USRSTACK; |
Line 923 trapsignal(struct lwp *l, ksiginfo_t *ks |
|
Line 909 trapsignal(struct lwp *l, ksiginfo_t *ks |
|
p->p_stats->p_ru.ru_nsignals++; |
p->p_stats->p_ru.ru_nsignals++; |
kpsendsig(l, ksi, &l->l_sigmask); |
kpsendsig(l, ksi, &l->l_sigmask); |
mutex_exit(&p->p_smutex); |
mutex_exit(&p->p_smutex); |
#ifdef KTRACE |
ktrpsig(signo, SIGACTION_PS(ps, signo).sa_handler, |
if (KTRPOINT(p, KTR_PSIG)) |
&l->l_sigmask, ksi); |
ktrpsig(l, signo, SIGACTION_PS(ps, signo).sa_handler, |
|
&l->l_sigmask, ksi); |
|
#endif |
|
} else { |
} else { |
/* XXX for core dump/debugger */ |
/* XXX for core dump/debugger */ |
p->p_sigctx.ps_lwp = l->l_lid; |
p->p_sigctx.ps_lwp = l->l_lid; |
|
|
kpsignal2(struct proc *p, ksiginfo_t *ksi) |
kpsignal2(struct proc *p, ksiginfo_t *ksi) |
{ |
{ |
int prop, lid, toall, signo = ksi->ksi_signo; |
int prop, lid, toall, signo = ksi->ksi_signo; |
|
struct sigacts *sa; |
struct lwp *l; |
struct lwp *l; |
ksiginfo_t *kp; |
ksiginfo_t *kp; |
ksiginfoq_t kq; |
ksiginfoq_t kq; |
Line 1270 kpsignal2(struct proc *p, ksiginfo_t *ks |
|
Line 1254 kpsignal2(struct proc *p, ksiginfo_t *ks |
|
* process dumps core immediately. |
* process dumps core immediately. |
*/ |
*/ |
if (KSI_TRAP_P(ksi)) { |
if (KSI_TRAP_P(ksi)) { |
|
sa = p->p_sigacts; |
|
mutex_enter(&sa->sa_mutex); |
if (!sigismember(&p->p_sigctx.ps_sigcatch, signo)) { |
if (!sigismember(&p->p_sigctx.ps_sigcatch, signo)) { |
sigdelset(&p->p_sigctx.ps_sigignore, signo); |
sigdelset(&p->p_sigctx.ps_sigignore, signo); |
SIGACTION(p, signo).sa_handler = SIG_DFL; |
SIGACTION(p, signo).sa_handler = SIG_DFL; |
} |
} |
|
mutex_exit(&sa->sa_mutex); |
} |
} |
|
|
/* |
/* |
Line 1342 kpsignal2(struct proc *p, ksiginfo_t *ks |
|
Line 1329 kpsignal2(struct proc *p, ksiginfo_t *ks |
|
l = lwp_find(p, lid); |
l = lwp_find(p, lid); |
if (l != NULL) { |
if (l != NULL) { |
sigput(&l->l_sigpend, p, kp); |
sigput(&l->l_sigpend, p, kp); |
mb_write(); |
membar_producer(); |
(void)sigpost(l, action, prop, kp->ksi_signo); |
(void)sigpost(l, action, prop, kp->ksi_signo); |
} |
} |
goto out; |
goto out; |
Line 1427 kpsignal2(struct proc *p, ksiginfo_t *ks |
|
Line 1414 kpsignal2(struct proc *p, ksiginfo_t *ks |
|
* visible on the per process list (for sigispending()). This |
* visible on the per process list (for sigispending()). This |
* is unlikely to be needed in practice, but... |
* is unlikely to be needed in practice, but... |
*/ |
*/ |
mb_write(); |
membar_producer(); |
|
|
/* |
/* |
* Try to find an LWP that can take the signal. |
* Try to find an LWP that can take the signal. |
Line 1481 sigswitch(bool ppsig, int ppmask, int si |
|
Line 1468 sigswitch(bool ppsig, int ppmask, int si |
|
* to a halt so they are included in p->p_nrlwps |
* to a halt so they are included in p->p_nrlwps |
*/ |
*/ |
p->p_sflag |= (PS_STOPPING | PS_NOTIFYSTOP); |
p->p_sflag |= (PS_STOPPING | PS_NOTIFYSTOP); |
mb_write(); |
membar_producer(); |
|
|
LIST_FOREACH(l2, &p->p_lwps, l_sibling) { |
LIST_FOREACH(l2, &p->p_lwps, l_sibling) { |
lwp_lock(l2); |
lwp_lock(l2); |
Line 1819 postsig(int signo) |
|
Line 1806 postsig(int signo) |
|
p->p_stats->p_ru.ru_nsignals++; |
p->p_stats->p_ru.ru_nsignals++; |
sigget(l->l_sigpendset, &ksi, signo, NULL); |
sigget(l->l_sigpendset, &ksi, signo, NULL); |
|
|
#ifdef KTRACE |
if (ktrpoint(KTR_PSIG)) { |
if (KTRPOINT(p, KTR_PSIG)) { |
|
mutex_exit(&p->p_smutex); |
mutex_exit(&p->p_smutex); |
ktrpsig(l, signo, action, returnmask, NULL); |
ktrpsig(signo, action, returnmask, NULL); |
mutex_enter(&p->p_smutex); |
mutex_enter(&p->p_smutex); |
} |
} |
#endif |
|
|
|
if (action == SIG_DFL) { |
if (action == SIG_DFL) { |
/* |
/* |
Line 1865 sendsig_reset(struct lwp *l, int signo) |
|
Line 1850 sendsig_reset(struct lwp *l, int signo) |
|
p->p_sigctx.ps_code = 0; |
p->p_sigctx.ps_code = 0; |
p->p_sigctx.ps_signo = 0; |
p->p_sigctx.ps_signo = 0; |
|
|
|
mutex_enter(&ps->sa_mutex); |
sigplusset(&SIGACTION_PS(ps, signo).sa_mask, &l->l_sigmask); |
sigplusset(&SIGACTION_PS(ps, signo).sa_mask, &l->l_sigmask); |
if (SIGACTION_PS(ps, signo).sa_flags & SA_RESETHAND) { |
if (SIGACTION_PS(ps, signo).sa_flags & SA_RESETHAND) { |
sigdelset(&p->p_sigctx.ps_sigcatch, signo); |
sigdelset(&p->p_sigctx.ps_sigcatch, signo); |
Line 1872 sendsig_reset(struct lwp *l, int signo) |
|
Line 1858 sendsig_reset(struct lwp *l, int signo) |
|
sigaddset(&p->p_sigctx.ps_sigignore, signo); |
sigaddset(&p->p_sigctx.ps_sigignore, signo); |
SIGACTION_PS(ps, signo).sa_handler = SIG_DFL; |
SIGACTION_PS(ps, signo).sa_handler = SIG_DFL; |
} |
} |
|
mutex_exit(&ps->sa_mutex); |
} |
} |
|
|
/* |
/* |
Line 2012 proc_stop(struct proc *p, int notify, in |
|
Line 1999 proc_stop(struct proc *p, int notify, in |
|
* unlock between here and the p->p_nrlwps check below. |
* unlock between here and the p->p_nrlwps check below. |
*/ |
*/ |
p->p_sflag |= PS_STOPPING; |
p->p_sflag |= PS_STOPPING; |
mb_write(); |
membar_producer(); |
|
|
LIST_FOREACH(l, &p->p_lwps, l_sibling) { |
LIST_FOREACH(l, &p->p_lwps, l_sibling) { |
lwp_lock(l); |
lwp_lock(l); |
Line 2066 proc_stop(struct proc *p, int notify, in |
|
Line 2053 proc_stop(struct proc *p, int notify, in |
|
* information to the parent could be delayed indefinitely. |
* information to the parent could be delayed indefinitely. |
* |
* |
* To handle this race, proc_stop_callout() runs once per tick while there |
* To handle this race, proc_stop_callout() runs once per tick while there |
* are stopping processes it the system. It sets LWPs that are sleeping |
* are stopping processes in the system. It sets LWPs that are sleeping |
* interruptably into the LSSTOP state. |
* interruptably into the LSSTOP state. |
* |
* |
* Note that we are not concerned about keeping all LWPs stopped while the |
* Note that we are not concerned about keeping all LWPs stopped while the |
Line 2088 proc_stop_callout(void *cookie) |
|
Line 2075 proc_stop_callout(void *cookie) |
|
restart = false; |
restart = false; |
more = false; |
more = false; |
|
|
|
mutex_enter(&proclist_lock); |
mutex_enter(&proclist_mutex); |
mutex_enter(&proclist_mutex); |
PROCLIST_FOREACH(p, &allproc) { |
PROCLIST_FOREACH(p, &allproc) { |
mutex_enter(&p->p_smutex); |
mutex_enter(&p->p_smutex); |
Line 2137 proc_stop_callout(void *cookie) |
|
Line 2125 proc_stop_callout(void *cookie) |
|
break; |
break; |
} |
} |
mutex_exit(&proclist_mutex); |
mutex_exit(&proclist_mutex); |
|
mutex_exit(&proclist_lock); |
} while (restart); |
} while (restart); |
|
|
/* |
/* |