diff options
| author | Roger A. Faulkner <Roger.Faulkner@Sun.COM> | 2009-06-15 13:26:03 -0700 |
|---|---|---|
| committer | Roger A. Faulkner <Roger.Faulkner@Sun.COM> | 2009-06-15 13:26:03 -0700 |
| commit | e0cf54a5673ecf2b9054101898211427b97772f7 (patch) | |
| tree | fd0f69130bffb55710c42fc60b29dc9f9c3d306d /usr/src/uts/common | |
| parent | 62224350e5355e6834f7deb9d8a7d062a50cb7c2 (diff) | |
| download | illumos-joyent-e0cf54a5673ecf2b9054101898211427b97772f7.tar.gz | |
6719215 profile timer survives exec; handler does not; process crashes with Profile Timer Expired
Diffstat (limited to 'usr/src/uts/common')
| -rw-r--r-- | usr/src/uts/common/os/exec.c | 7 | ||||
| -rw-r--r-- | usr/src/uts/common/os/lwp.c | 3 | ||||
| -rw-r--r-- | usr/src/uts/common/os/sig.c | 46 | ||||
| -rw-r--r-- | usr/src/uts/common/os/timers.c | 61 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/proc.h | 1 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/timer.h | 5 |
6 files changed, 117 insertions, 6 deletions
diff --git a/usr/src/uts/common/os/exec.c b/usr/src/uts/common/os/exec.c index 2ca011f17b..7bd4273c1d 100644 --- a/usr/src/uts/common/os/exec.c +++ b/usr/src/uts/common/os/exec.c @@ -1801,6 +1801,13 @@ exec_args(execa_t *uap, uarg_t *args, intpdata_t *intp, void **auxvpp) if (p->p_itimer != NULL) timer_exit(); + /* + * Delete the ITIMER_REALPROF interval timer. + * The other ITIMER_* interval timers are specified + * to be inherited across exec(). + */ + delete_itimer_realprof(); + if (audit_active) audit_exec(args->stk_base, args->stk_base + args->arglen, args->na - args->ne, args->ne); diff --git a/usr/src/uts/common/os/lwp.c b/usr/src/uts/common/os/lwp.c index a4bc1bffd2..bf827dd106 100644 --- a/usr/src/uts/common/os/lwp.c +++ b/usr/src/uts/common/os/lwp.c @@ -57,6 +57,7 @@ #include <sys/sdt.h> #include <sys/cmn_err.h> #include <sys/brand.h> +#include <sys/cyclic.h> /* hash function for the lwpid hash table, p->p_tidhash[] */ #define TIDHASH(tid, hash_sz) ((tid) & ((hash_sz) - 1)) @@ -205,7 +206,7 @@ lwp_create(void (*proc)(), caddr_t arg, size_t len, proc_t *p, /* * Allocate the SIGPROF buffer if ITIMER_REALPROF is in effect. */ - if (timerisset(&p->p_rprof_timer.it_value)) + if (p->p_rprof_cyclic != CYCLIC_NONE) t->t_rprof = kmem_zalloc(sizeof (struct rprof), KM_SLEEP); if (cid != NOCLASS) diff --git a/usr/src/uts/common/os/sig.c b/usr/src/uts/common/os/sig.c index 454b9e600f..481d6575af 100644 --- a/usr/src/uts/common/os/sig.c +++ b/usr/src/uts/common/os/sig.c @@ -56,6 +56,7 @@ #include <sys/core.h> #include <sys/schedctl.h> #include <sys/contract/process_impl.h> +#include <sys/cyclic.h> #include <sys/dtrace.h> #include <sys/sdt.h> @@ -2550,6 +2551,51 @@ trapsig(k_siginfo_t *ip, int restartable) mutex_exit(&p->p_lock); } +/* + * Arrange for the real time profiling signal to be dispatched. + */ +void +realsigprof(int sysnum, int nsysarg, int error) +{ + proc_t *p; + klwp_t *lwp; + + if (curthread->t_rprof->rp_anystate == 0) + return; + p = ttoproc(curthread); + lwp = ttolwp(curthread); + mutex_enter(&p->p_lock); + if (p->p_rprof_cyclic == CYCLIC_NONE) { + bzero(curthread->t_rprof, sizeof (*curthread->t_rprof)); + mutex_exit(&p->p_lock); + return; + } + if (sigismember(&p->p_ignore, SIGPROF) || + signal_is_blocked(curthread, SIGPROF)) { + mutex_exit(&p->p_lock); + return; + } + lwp->lwp_siginfo.si_signo = SIGPROF; + lwp->lwp_siginfo.si_code = PROF_SIG; + lwp->lwp_siginfo.si_errno = error; + hrt2ts(gethrtime(), &lwp->lwp_siginfo.si_tstamp); + lwp->lwp_siginfo.si_syscall = sysnum; + lwp->lwp_siginfo.si_nsysarg = nsysarg; + lwp->lwp_siginfo.si_fault = lwp->lwp_lastfault; + lwp->lwp_siginfo.si_faddr = lwp->lwp_lastfaddr; + lwp->lwp_lastfault = 0; + lwp->lwp_lastfaddr = NULL; + sigtoproc(p, curthread, SIGPROF); + mutex_exit(&p->p_lock); + ASSERT(lwp->lwp_cursig == 0); + if (issig(FORREAL)) + psig(); + mutex_enter(&p->p_lock); + lwp->lwp_siginfo.si_signo = 0; + bzero(curthread->t_rprof, sizeof (*curthread->t_rprof)); + mutex_exit(&p->p_lock); +} + #ifdef _SYSCALL32_IMPL /* diff --git a/usr/src/uts/common/os/timers.c b/usr/src/uts/common/os/timers.c index fbc204e526..2fc7b7bff2 100644 --- a/usr/src/uts/common/os/timers.c +++ b/usr/src/uts/common/os/timers.c @@ -18,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -519,6 +520,61 @@ xsetitimer(uint_t which, struct itimerval *itv, int iskaddr) } /* + * Delete the ITIMER_REALPROF interval timer. + * Called only from exec_args() when exec occurs. + * The other ITIMER_* interval timers are specified + * to be inherited across exec(), so leave them alone. + */ +void +delete_itimer_realprof(void) +{ + kthread_t *t = curthread; + struct proc *p = ttoproc(t); + klwp_t *lwp = ttolwp(t); + cyclic_id_t cyclic; + + mutex_enter(&p->p_lock); + + /* we are performing execve(); assert we are single-threaded */ + ASSERT(t == p->p_tlist && t == t->t_forw); + + if ((cyclic = p->p_rprof_cyclic) == CYCLIC_NONE) { + mutex_exit(&p->p_lock); + } else { + p->p_rprof_cyclic = CYCLIC_NONE; + /* + * Delete any current instance of SIGPROF. + */ + if (lwp->lwp_cursig == SIGPROF) { + lwp->lwp_cursig = 0; + lwp->lwp_extsig = 0; + if (lwp->lwp_curinfo) { + siginfofree(lwp->lwp_curinfo); + lwp->lwp_curinfo = NULL; + } + } + /* + * Delete any pending instances of SIGPROF. + */ + sigdelset(&p->p_sig, SIGPROF); + sigdelset(&p->p_extsig, SIGPROF); + sigdelq(p, NULL, SIGPROF); + sigdelset(&t->t_sig, SIGPROF); + sigdelset(&t->t_extsig, SIGPROF); + sigdelq(p, t, SIGPROF); + + mutex_exit(&p->p_lock); + + /* + * Remove the ITIMER_REALPROF cyclic. + */ + mutex_enter(&cpu_lock); + cyclic_remove(cyclic); + mutex_exit(&cpu_lock); + } +} + +/* * Real interval timer expired: * send process whose timer expired an alarm signal. * If time is not set up to reload, then just return. @@ -578,7 +634,8 @@ realprofexpire(void *arg) kthread_t *t; mutex_enter(&p->p_lock); - if ((t = p->p_tlist) == NULL) { + if (p->p_rprof_cyclic == CYCLIC_NONE || + (t = p->p_tlist) == NULL) { mutex_exit(&p->p_lock); return; } diff --git a/usr/src/uts/common/sys/proc.h b/usr/src/uts/common/sys/proc.h index 43407bab38..daacb058f7 100644 --- a/usr/src/uts/common/sys/proc.h +++ b/usr/src/uts/common/sys/proc.h @@ -613,6 +613,7 @@ extern void psignal(proc_t *, int); extern void tsignal(kthread_t *, int); extern void sigtoproc(proc_t *, kthread_t *, int); extern void trapsig(k_siginfo_t *, int); +extern void realsigprof(int, int, int); extern int eat_signal(kthread_t *, int); extern int signal_is_blocked(kthread_t *, int); extern int sigcheck(proc_t *, kthread_t *); diff --git a/usr/src/uts/common/sys/timer.h b/usr/src/uts/common/sys/timer.h index 05d08bb489..604ddf5d83 100644 --- a/usr/src/uts/common/sys/timer.h +++ b/usr/src/uts/common/sys/timer.h @@ -20,15 +20,13 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_TIMER_H #define _SYS_TIMER_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <sys/proc.h> #include <sys/thread.h> @@ -106,6 +104,7 @@ extern void timespecsub(timespec_t *, timespec_t *); extern void timespecfix(timespec_t *); extern int xgetitimer(uint_t, struct itimerval *, int); extern int xsetitimer(uint_t, struct itimerval *, int); +extern void delete_itimer_realprof(void); #define timerspecisset(tvp) ((tvp)->tv_sec || (tvp)->tv_nsec) #define timerspeccmp(tvp, uvp) (((tvp)->tv_sec - (uvp)->tv_sec) ? \ |
