summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjkoshy <jkoshy@FreeBSD.org>2005-06-30 19:01:26 +0000
committerjkoshy <jkoshy@FreeBSD.org>2005-06-30 19:01:26 +0000
commit3cade8d074f10ed4002c26e30494d70bb274b767 (patch)
tree65d154e0d10e4dfd78924cb57c52e53ed80a41dd /sys
parentca20bf4b48c565fd16ea813e7cce4e94862c31aa (diff)
downloadFreeBSD-src-3cade8d074f10ed4002c26e30494d70bb274b767.zip
FreeBSD-src-3cade8d074f10ed4002c26e30494d70bb274b767.tar.gz
MFP4:
- pmcstat(8) gprof output mode fixes: lib/libpmc/pmclog.{c,h}, sys/sys/pmclog.h: + Add a 'is_usermode' field to the PMCLOG_PCSAMPLE event + Add an 'entryaddr' field to the PMCLOG_PROCEXEC event, so that pmcstat(8) can determine where the runtime loader /libexec/ld-elf.so.1 is getting loaded. sys/kern/kern_exec.c: + Use a local struct to group the entry address of the image being exec()'ed and the process credential changed flag to the exec handling hook inside hwpmc(4). usr.sbin/pmcstat/*: + Support "-k kernelpath", "-D sampledir". + Implement the ELF bits of 'gmon.out' profile generation in a new file "pmcstat_log.c". Move all log related functions to this file. + Move local definitions and prototypes to "pmcstat.h" - Other bug fixes: + lib/libpmc/pmclog.c: correctly handle EOF in pmclog_read(). + sys/dev/hwpmc_mod.c: unconditionally log a PROCEXIT event to all attached PMCs when a process exits. + sys/sys/pmc.h: correct a function prototype. + Improve usage checks in pmcstat(8). Approved by: re (blanket hwpmc)
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/hwpmc/hwpmc_logging.c17
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c37
-rw-r--r--sys/kern/kern_exec.c9
-rw-r--r--sys/sys/pmc.h2
-rw-r--r--sys/sys/pmckern.h5
-rw-r--r--sys/sys/pmclog.h6
6 files changed, 48 insertions, 28 deletions
diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c
index 5ae7bc6..bca14bd 100644
--- a/sys/dev/hwpmc/hwpmc_logging.c
+++ b/sys/dev/hwpmc/hwpmc_logging.c
@@ -138,14 +138,16 @@ CTASSERT(sizeof(struct pmclog_mappingchange) == PATH_MAX +
5*4 + 2*sizeof(uintfptr_t));
CTASSERT(offsetof(struct pmclog_mappingchange,pl_pathname) ==
5*4 + 2*sizeof(uintfptr_t));
-CTASSERT(sizeof(struct pmclog_pcsample) == 5*4 + sizeof(uintfptr_t));
+CTASSERT(sizeof(struct pmclog_pcsample) == 6*4 + sizeof(uintfptr_t));
CTASSERT(sizeof(struct pmclog_pmcallocate) == 6*4);
CTASSERT(sizeof(struct pmclog_pmcattach) == 5*4 + PATH_MAX);
CTASSERT(offsetof(struct pmclog_pmcattach,pl_pathname) == 5*4);
CTASSERT(sizeof(struct pmclog_pmcdetach) == 5*4);
CTASSERT(sizeof(struct pmclog_proccsw) == 5*4 + 8);
-CTASSERT(sizeof(struct pmclog_procexec) == 4*4 + PATH_MAX);
-CTASSERT(offsetof(struct pmclog_procexec,pl_pathname) == 4*4);
+CTASSERT(sizeof(struct pmclog_procexec) == 5*4 + PATH_MAX +
+ sizeof(uintfptr_t));
+CTASSERT(offsetof(struct pmclog_procexec,pl_pathname) == 5*4 +
+ sizeof(uintfptr_t));
CTASSERT(sizeof(struct pmclog_procexit) == 5*4 + 8);
CTASSERT(sizeof(struct pmclog_procfork) == 5*4);
CTASSERT(sizeof(struct pmclog_sysexit) == 4*4);
@@ -755,6 +757,7 @@ pmclog_process_pcsample(struct pmc *pm, struct pmc_sample *ps)
PMCLOG_EMIT32(ps->ps_pid);
PMCLOG_EMITADDR(ps->ps_pc);
PMCLOG_EMIT32(pm->pm_id);
+ PMCLOG_EMIT32(ps->ps_usermode);
PMCLOG_DESPATCH(po);
}
@@ -834,7 +837,8 @@ pmclog_process_proccsw(struct pmc *pm, struct pmc_process *pp, pmc_value_t v)
}
void
-pmclog_process_procexec(struct pmc_owner *po, pid_t pid, char *path)
+pmclog_process_procexec(struct pmc_owner *po, pmc_id_t pmid, pid_t pid,
+ uintfptr_t startaddr, char *path)
{
int pathlen, recordlen;
@@ -845,6 +849,8 @@ pmclog_process_procexec(struct pmc_owner *po, pid_t pid, char *path)
PMCLOG_RESERVE(po, PROCEXEC, recordlen);
PMCLOG_EMIT32(pid);
+ PMCLOG_EMITADDR(startaddr);
+ PMCLOG_EMIT32(pmid);
PMCLOG_EMITSTRING(path,pathlen);
PMCLOG_DESPATCH(po);
}
@@ -859,9 +865,6 @@ pmclog_process_procexit(struct pmc *pm, struct pmc_process *pp)
int ri;
struct pmc_owner *po;
- KASSERT(pm->pm_flags & PMC_F_LOG_PROCEXIT,
- ("[pmc,%d] log-process-exit called gratuitously", __LINE__));
-
ri = PMC_TO_ROWINDEX(pm);
PMCDBG(LOG,EXT,1,"pm=%p pid=%d v=%jx", pm, pp->pp_proc->p_pid,
pp->pp_pmcs[ri].pp_pmcval);
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index 962c15b..867722c 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -661,16 +661,16 @@ pmc_force_context_switch(void)
*/
static void
-pmc_getprocname(struct proc *p, char **fullpath, char **freepath)
+pmc_getfilename(struct vnode *v, char **fullpath, char **freepath)
{
struct thread *td;
td = curthread;
*fullpath = "unknown";
*freepath = NULL;
- vn_lock(p->p_textvp, LK_EXCLUSIVE | LK_RETRY, td);
- vn_fullpath(td, p->p_textvp, fullpath, freepath);
- VOP_UNLOCK(p->p_textvp, 0, td);
+ vn_lock(v, LK_EXCLUSIVE | LK_RETRY, td);
+ vn_fullpath(td, v, fullpath, freepath);
+ VOP_UNLOCK(v, 0, td);
}
/*
@@ -951,7 +951,7 @@ pmc_attach_one_process(struct proc *p, struct pmc *pm)
/* issue an attach event to a configured log file */
if (pm->pm_owner->po_flags & PMC_PO_OWNS_LOGFILE) {
- pmc_getprocname(p, &fullpath, &freepath);
+ pmc_getfilename(p->p_textvp, &fullpath, &freepath);
pmclog_process_pmcattach(pm, p->p_pid, fullpath);
if (freepath)
FREE(freepath, M_TEMP);
@@ -1442,7 +1442,6 @@ pmc_hook_handler(struct thread *td, int function, void *arg)
case PMC_FN_PROCESS_EXEC:
{
- int *credentials_changed;
char *fullpath, *freepath;
unsigned int ri;
int is_using_hwpmcs;
@@ -1450,16 +1449,20 @@ pmc_hook_handler(struct thread *td, int function, void *arg)
struct proc *p;
struct pmc_owner *po;
struct pmc_process *pp;
+ struct pmckern_procexec *pk;
sx_assert(&pmc_sx, SX_XLOCKED);
p = td->td_proc;
- pmc_getprocname(p, &fullpath, &freepath);
+ pmc_getfilename(p->p_textvp, &fullpath, &freepath);
+
+ pk = (struct pmckern_procexec *) arg;
/* Inform owners of SS mode PMCs of the exec event. */
LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
if (po->po_flags & PMC_PO_OWNS_LOGFILE)
- pmclog_process_procexec(po, p->p_pid, fullpath);
+ pmclog_process_procexec(po, PMC_ID_INVALID,
+ p->p_pid, pk->pm_entryaddr, fullpath);
PROC_LOCK(p);
is_using_hwpmcs = p->p_flag & P_HWPMC;
@@ -1499,19 +1502,19 @@ pmc_hook_handler(struct thread *td, int function, void *arg)
po = pm->pm_owner;
if (po->po_sscount == 0 &&
po->po_flags & PMC_PO_OWNS_LOGFILE)
- pmclog_process_procexec(po, p->p_pid,
+ pmclog_process_procexec(po, pm->pm_id,
+ p->p_pid, pk->pm_entryaddr,
fullpath);
}
if (freepath)
FREE(freepath, M_TEMP);
- credentials_changed = arg;
PMCDBG(PRC,EXC,1, "exec proc=%p (%d, %s) cred-changed=%d",
- p, p->p_pid, p->p_comm, *credentials_changed);
+ p, p->p_pid, p->p_comm, pk->pm_credentialschanged);
- if (*credentials_changed == 0) /* credentials didn't change */
+ if (pk->pm_credentialschanged == 0) /* no change */
break;
/*
@@ -3457,7 +3460,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
*/
int
-pmc_process_interrupt(int cpu, struct pmc *pm, intfptr_t pc, int usermode)
+pmc_process_interrupt(int cpu, struct pmc *pm, uintfptr_t pc, int usermode)
{
int error, ri;
struct thread *td;
@@ -3474,7 +3477,7 @@ pmc_process_interrupt(int cpu, struct pmc *pm, intfptr_t pc, int usermode)
atomic_add_int(&pmc_stats.pm_intr_bufferfull, 1);
atomic_set_int(&pm->pm_flags, PMC_F_IS_STALLED);
PMCDBG(SAM,INT,1,"(spc) cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d",
- cpu, pm, (int64_t) pc, usermode,
+ cpu, pm, (uint64_t) pc, usermode,
(int) (psb->ps_write - psb->ps_samples),
(int) (psb->ps_read - psb->ps_samples));
error = ENOMEM;
@@ -3483,7 +3486,7 @@ pmc_process_interrupt(int cpu, struct pmc *pm, intfptr_t pc, int usermode)
/* fill in entry */
PMCDBG(SAM,INT,1,"cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d", cpu, pm,
- (int64_t) pc, usermode,
+ (uint64_t) pc, usermode,
(int) (psb->ps_write - psb->ps_samples),
(int) (psb->ps_read - psb->ps_samples));
@@ -3549,7 +3552,7 @@ pmc_process_samples(int cpu)
goto entrydone;
PMCDBG(SAM,OPS,1,"cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d", cpu,
- pm, (int64_t) ps->ps_pc, ps->ps_usermode,
+ pm, (uint64_t) ps->ps_pc, ps->ps_usermode,
(int) (psb->ps_write - psb->ps_samples),
(int) (psb->ps_read - psb->ps_samples));
@@ -3768,7 +3771,7 @@ pmc_process_exit(void *arg __unused, struct proc *p)
*/
for (ri = 0; ri < md->pmd_npmc; ri++)
if ((pm = pp->pp_pmcs[ri].pp_pmc) != NULL) {
- if (pm->pm_flags & PMC_F_LOG_PROCEXIT)
+ if (pm->pm_flags & PMC_F_NEEDS_LOGFILE)
pmclog_process_procexit(pm, pp);
pmc_unlink_target_process(pm, pp);
}
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 3640180..719f5bb 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -301,6 +301,9 @@ do_execve(td, args, mac_p)
struct label *interplabel = NULL;
int will_transition;
#endif
+#ifdef HWPMC_HOOKS
+ struct pmckern_procexec pe;
+#endif
vfslocked = 0;
imgp = &image_params;
@@ -681,8 +684,10 @@ interpret:
*/
if (PMC_SYSTEM_SAMPLING_ACTIVE() || PMC_PROC_IS_USING_PMCS(p)) {
PROC_UNLOCK(p);
- PMC_CALL_HOOK_X(td, PMC_FN_PROCESS_EXEC,
- (void *) &credential_changing);
+ pe.pm_credentialschanged = credential_changing;
+ pe.pm_entryaddr = imgp->entry_addr;
+
+ PMC_CALL_HOOK_X(td, PMC_FN_PROCESS_EXEC, (void *) &pe);
} else
PROC_UNLOCK(p);
#else /* !HWPMC_HOOKS */
diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h
index 5126f32..e872ffb 100644
--- a/sys/sys/pmc.h
+++ b/sys/sys/pmc.h
@@ -995,7 +995,7 @@ MALLOC_DECLARE(M_PMC);
struct pmc_mdep *pmc_md_initialize(void); /* MD init function */
int pmc_getrowdisp(int _ri);
-int pmc_process_interrupt(int _cpu, struct pmc *_pm, intfptr_t _pc,
+int pmc_process_interrupt(int _cpu, struct pmc *_pm, uintfptr_t _pc,
int _usermode);
#endif /* _KERNEL */
diff --git a/sys/sys/pmckern.h b/sys/sys/pmckern.h
index 5f2e158..0d689b2 100644
--- a/sys/sys/pmckern.h
+++ b/sys/sys/pmckern.h
@@ -44,6 +44,11 @@
#define PMC_FN_CSW_OUT 3
#define PMC_FN_DO_SAMPLES 4
+struct pmckern_procexec {
+ int pm_credentialschanged;
+ uintptr_t pm_entryaddr;
+};
+
/* hook */
extern int (*pmc_hook)(struct thread *_td, int _function, void *_arg);
extern int (*pmc_intr)(int _cpu, uintptr_t _pc, int _usermode);
diff --git a/sys/sys/pmclog.h b/sys/sys/pmclog.h
index 97aa2f6..026c667 100644
--- a/sys/sys/pmclog.h
+++ b/sys/sys/pmclog.h
@@ -113,6 +113,7 @@ struct pmclog_pcsample {
uint32_t pl_pid;
uintfptr_t pl_pc; /* 8 byte aligned */
uint32_t pl_pmcid;
+ uint32_t pl_usermode;
} __packed;
struct pmclog_pmcallocate {
@@ -145,6 +146,8 @@ struct pmclog_proccsw {
struct pmclog_procexec {
PMCLOG_ENTRY_HEADER
uint32_t pl_pid;
+ uintfptr_t pl_start; /* keep 8 byte aligned */
+ uint32_t pl_pmcid;
char pl_pathname[PATH_MAX];
} __packed;
@@ -217,7 +220,8 @@ void pmclog_process_pmcattach(struct pmc *_pm, pid_t _pid, char *_path);
void pmclog_process_pmcdetach(struct pmc *_pm, pid_t _pid);
void pmclog_process_proccsw(struct pmc *_pm, struct pmc_process *_pp,
pmc_value_t _v);
-void pmclog_process_procexec(struct pmc_owner *_po, pid_t _pid, char *_path);
+void pmclog_process_procexec(struct pmc_owner *_po, pmc_id_t _pmid, pid_t _pid,
+ uintfptr_t _startaddr, char *_path);
void pmclog_process_procexit(struct pmc *_pm, struct pmc_process *_pp);
void pmclog_process_procfork(struct pmc_owner *_po, pid_t _oldpid, pid_t _newpid);
void pmclog_process_sysexit(struct pmc_owner *_po, pid_t _pid);
OpenPOWER on IntegriCloud