Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/hwpmc/hwpmc_logging.c
Show First 20 Lines • Show All 205 Lines • ▼ Show 20 Lines | pmclog_get_buffer(struct pmc_owner *po) | ||||
KASSERT(po->po_curbuf == NULL, | KASSERT(po->po_curbuf == NULL, | ||||
("[pmclog,%d] po=%p current buffer still valid", __LINE__, po)); | ("[pmclog,%d] po=%p current buffer still valid", __LINE__, po)); | ||||
mtx_lock_spin(&pmc_bufferlist_mtx); | mtx_lock_spin(&pmc_bufferlist_mtx); | ||||
if ((plb = TAILQ_FIRST(&pmc_bufferlist)) != NULL) | if ((plb = TAILQ_FIRST(&pmc_bufferlist)) != NULL) | ||||
TAILQ_REMOVE(&pmc_bufferlist, plb, plb_next); | TAILQ_REMOVE(&pmc_bufferlist, plb, plb_next); | ||||
mtx_unlock_spin(&pmc_bufferlist_mtx); | mtx_unlock_spin(&pmc_bufferlist_mtx); | ||||
PMCDBG(LOG,GTB,1, "po=%p plb=%p", po, plb); | PMCDBG2(LOG,GTB,1, "po=%p plb=%p", po, plb); | ||||
#ifdef HWPMC_DEBUG | #ifdef HWPMC_DEBUG | ||||
if (plb) | if (plb) | ||||
KASSERT(plb->plb_ptr == plb->plb_base && | KASSERT(plb->plb_ptr == plb->plb_base && | ||||
plb->plb_base < plb->plb_fence, | plb->plb_base < plb->plb_fence, | ||||
("[pmclog,%d] po=%p buffer invariants: ptr=%p " | ("[pmclog,%d] po=%p buffer invariants: ptr=%p " | ||||
"base=%p fence=%p", __LINE__, po, plb->plb_ptr, | "base=%p fence=%p", __LINE__, po, plb->plb_ptr, | ||||
plb->plb_base, plb->plb_fence)); | plb->plb_base, plb->plb_fence)); | ||||
Show All 33 Lines | pmclog_loop(void *arg) | ||||
p = po->po_owner; | p = po->po_owner; | ||||
td = curthread; | td = curthread; | ||||
mycred = td->td_ucred; | mycred = td->td_ucred; | ||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
ownercred = crhold(p->p_ucred); | ownercred = crhold(p->p_ucred); | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
PMCDBG(LOG,INI,1, "po=%p kt=%p", po, po->po_kthread); | PMCDBG2(LOG,INI,1, "po=%p kt=%p", po, po->po_kthread); | ||||
KASSERT(po->po_kthread == curthread->td_proc, | KASSERT(po->po_kthread == curthread->td_proc, | ||||
("[pmclog,%d] proc mismatch po=%p po/kt=%p curproc=%p", __LINE__, | ("[pmclog,%d] proc mismatch po=%p po/kt=%p curproc=%p", __LINE__, | ||||
po, po->po_kthread, curthread->td_proc)); | po, po->po_kthread, curthread->td_proc)); | ||||
lb = NULL; | lb = NULL; | ||||
/* | /* | ||||
Show All 34 Lines | if (lb == NULL) { /* look for a fresh buffer to write */ | ||||
TAILQ_REMOVE(&po->po_logbuffers, lb, plb_next); | TAILQ_REMOVE(&po->po_logbuffers, lb, plb_next); | ||||
mtx_unlock_spin(&po->po_mtx); | mtx_unlock_spin(&po->po_mtx); | ||||
} | } | ||||
mtx_unlock(&pmc_kthread_mtx); | mtx_unlock(&pmc_kthread_mtx); | ||||
/* process the request */ | /* process the request */ | ||||
PMCDBG(LOG,WRI,2, "po=%p base=%p ptr=%p", po, | PMCDBG3(LOG,WRI,2, "po=%p base=%p ptr=%p", po, | ||||
lb->plb_base, lb->plb_ptr); | lb->plb_base, lb->plb_ptr); | ||||
/* change our thread's credentials before issuing the I/O */ | /* change our thread's credentials before issuing the I/O */ | ||||
aiov.iov_base = lb->plb_base; | aiov.iov_base = lb->plb_base; | ||||
aiov.iov_len = nbytes = lb->plb_ptr - lb->plb_base; | aiov.iov_len = nbytes = lb->plb_ptr - lb->plb_base; | ||||
auio.uio_iov = &aiov; | auio.uio_iov = &aiov; | ||||
auio.uio_iovcnt = 1; | auio.uio_iovcnt = 1; | ||||
Show All 14 Lines | if (error) { | ||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
kern_psignal(p, SIGIO); | kern_psignal(p, SIGIO); | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
mtx_lock(&pmc_kthread_mtx); | mtx_lock(&pmc_kthread_mtx); | ||||
po->po_error = error; /* save for flush log */ | po->po_error = error; /* save for flush log */ | ||||
PMCDBG(LOG,WRI,2, "po=%p error=%d", po, error); | PMCDBG2(LOG,WRI,2, "po=%p error=%d", po, error); | ||||
break; | break; | ||||
} | } | ||||
mtx_lock(&pmc_kthread_mtx); | mtx_lock(&pmc_kthread_mtx); | ||||
/* put the used buffer back into the global pool */ | /* put the used buffer back into the global pool */ | ||||
PMCLOG_INIT_BUFFER_DESCRIPTOR(lb); | PMCLOG_INIT_BUFFER_DESCRIPTOR(lb); | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | KASSERT(po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence, | ||||
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_fence)); | po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_fence)); | ||||
/* schedule an I/O if we've filled a buffer */ | /* schedule an I/O if we've filled a buffer */ | ||||
if (po->po_curbuf->plb_ptr >= po->po_curbuf->plb_fence) | if (po->po_curbuf->plb_ptr >= po->po_curbuf->plb_fence) | ||||
pmclog_schedule_io(po); | pmclog_schedule_io(po); | ||||
mtx_unlock_spin(&po->po_mtx); | mtx_unlock_spin(&po->po_mtx); | ||||
PMCDBG(LOG,REL,1, "po=%p", po); | PMCDBG1(LOG,REL,1, "po=%p", po); | ||||
} | } | ||||
/* | /* | ||||
* Attempt to reserve 'length' bytes of space in an owner's log | * Attempt to reserve 'length' bytes of space in an owner's log | ||||
* buffer. The function returns a pointer to 'length' bytes of space | * buffer. The function returns a pointer to 'length' bytes of space | ||||
* if there was enough space or returns NULL if no space was | * if there was enough space or returns NULL if no space was | ||||
* available. Non-null returns do so with the po mutex locked. The | * available. Non-null returns do so with the po mutex locked. The | ||||
* caller must invoke pmclog_release() on the pmc owner structure | * caller must invoke pmclog_release() on the pmc owner structure | ||||
* when done. | * when done. | ||||
*/ | */ | ||||
static uint32_t * | static uint32_t * | ||||
pmclog_reserve(struct pmc_owner *po, int length) | pmclog_reserve(struct pmc_owner *po, int length) | ||||
{ | { | ||||
uintptr_t newptr, oldptr; | uintptr_t newptr, oldptr; | ||||
uint32_t *lh; | uint32_t *lh; | ||||
struct timespec ts; | struct timespec ts; | ||||
PMCDBG(LOG,ALL,1, "po=%p len=%d", po, length); | PMCDBG2(LOG,ALL,1, "po=%p len=%d", po, length); | ||||
KASSERT(length % sizeof(uint32_t) == 0, | KASSERT(length % sizeof(uint32_t) == 0, | ||||
("[pmclog,%d] length not a multiple of word size", __LINE__)); | ("[pmclog,%d] length not a multiple of word size", __LINE__)); | ||||
mtx_lock_spin(&po->po_mtx); | mtx_lock_spin(&po->po_mtx); | ||||
/* No more data when shutdown in progress. */ | /* No more data when shutdown in progress. */ | ||||
if (po->po_flags & PMC_PO_SHUTDOWN) { | if (po->po_flags & PMC_PO_SHUTDOWN) { | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | pmclog_schedule_io(struct pmc_owner *po) | ||||
KASSERT(po->po_curbuf->plb_ptr >= po->po_curbuf->plb_base, | KASSERT(po->po_curbuf->plb_ptr >= po->po_curbuf->plb_base, | ||||
("[pmclog,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__, | ("[pmclog,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__, | ||||
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base)); | po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base)); | ||||
KASSERT(po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence, | KASSERT(po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence, | ||||
("[pmclog,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__, | ("[pmclog,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__, | ||||
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_fence)); | po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_fence)); | ||||
PMCDBG(LOG,SIO, 1, "po=%p", po); | PMCDBG1(LOG,SIO, 1, "po=%p", po); | ||||
mtx_assert(&po->po_mtx, MA_OWNED); | mtx_assert(&po->po_mtx, MA_OWNED); | ||||
/* | /* | ||||
* Add the current buffer to the tail of the buffer list and | * Add the current buffer to the tail of the buffer list and | ||||
* wakeup the helper. | * wakeup the helper. | ||||
*/ | */ | ||||
TAILQ_INSERT_TAIL(&po->po_logbuffers, po->po_curbuf, plb_next); | TAILQ_INSERT_TAIL(&po->po_logbuffers, po->po_curbuf, plb_next); | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd) | ||||
struct proc *p; | struct proc *p; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
/* | /* | ||||
* As long as it is possible to get a LOR between pmc_sx lock and | * As long as it is possible to get a LOR between pmc_sx lock and | ||||
* proctree/allproc sx locks used for adding a new process, assure | * proctree/allproc sx locks used for adding a new process, assure | ||||
* the former is not held here. | * the former is not held here. | ||||
*/ | */ | ||||
sx_assert(&pmc_sx, SA_UNLOCKED); | sx_assert(&pmc_sx, SA_UNLOCKED); | ||||
PMCDBG(LOG,CFG,1, "config po=%p logfd=%d", po, logfd); | PMCDBG2(LOG,CFG,1, "config po=%p logfd=%d", po, logfd); | ||||
p = po->po_owner; | p = po->po_owner; | ||||
/* return EBUSY if a log file was already present */ | /* return EBUSY if a log file was already present */ | ||||
if (po->po_flags & PMC_PO_OWNS_LOGFILE) | if (po->po_flags & PMC_PO_OWNS_LOGFILE) | ||||
return (EBUSY); | return (EBUSY); | ||||
KASSERT(po->po_kthread == NULL, | KASSERT(po->po_kthread == NULL, | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
int | int | ||||
pmclog_deconfigure_log(struct pmc_owner *po) | pmclog_deconfigure_log(struct pmc_owner *po) | ||||
{ | { | ||||
int error; | int error; | ||||
struct pmclog_buffer *lb; | struct pmclog_buffer *lb; | ||||
PMCDBG(LOG,CFG,1, "de-config po=%p", po); | PMCDBG1(LOG,CFG,1, "de-config po=%p", po); | ||||
if ((po->po_flags & PMC_PO_OWNS_LOGFILE) == 0) | if ((po->po_flags & PMC_PO_OWNS_LOGFILE) == 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
KASSERT(po->po_sscount == 0, | KASSERT(po->po_sscount == 0, | ||||
("[pmclog,%d] po=%p still owning SS PMCs", __LINE__, po)); | ("[pmclog,%d] po=%p still owning SS PMCs", __LINE__, po)); | ||||
KASSERT(po->po_file != NULL, | KASSERT(po->po_file != NULL, | ||||
("[pmclog,%d] po=%p no log file", __LINE__, po)); | ("[pmclog,%d] po=%p no log file", __LINE__, po)); | ||||
Show All 34 Lines | |||||
*/ | */ | ||||
int | int | ||||
pmclog_flush(struct pmc_owner *po) | pmclog_flush(struct pmc_owner *po) | ||||
{ | { | ||||
int error; | int error; | ||||
struct pmclog_buffer *lb; | struct pmclog_buffer *lb; | ||||
PMCDBG(LOG,FLS,1, "po=%p", po); | PMCDBG1(LOG,FLS,1, "po=%p", po); | ||||
/* | /* | ||||
* If there is a pending error recorded by the logger thread, | * If there is a pending error recorded by the logger thread, | ||||
* return that. | * return that. | ||||
*/ | */ | ||||
if (po->po_error) | if (po->po_error) | ||||
return (po->po_error); | return (po->po_error); | ||||
Show All 24 Lines | error: | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
pmclog_close(struct pmc_owner *po) | pmclog_close(struct pmc_owner *po) | ||||
{ | { | ||||
PMCDBG(LOG,CLO,1, "po=%p", po); | PMCDBG1(LOG,CLO,1, "po=%p", po); | ||||
mtx_lock(&pmc_kthread_mtx); | mtx_lock(&pmc_kthread_mtx); | ||||
/* | /* | ||||
* Schedule the current buffer. | * Schedule the current buffer. | ||||
*/ | */ | ||||
mtx_lock_spin(&po->po_mtx); | mtx_lock_spin(&po->po_mtx); | ||||
if (po->po_curbuf) | if (po->po_curbuf) | ||||
Show All 15 Lines | |||||
void | void | ||||
pmclog_process_callchain(struct pmc *pm, struct pmc_sample *ps) | pmclog_process_callchain(struct pmc *pm, struct pmc_sample *ps) | ||||
{ | { | ||||
int n, recordlen; | int n, recordlen; | ||||
uint32_t flags; | uint32_t flags; | ||||
struct pmc_owner *po; | struct pmc_owner *po; | ||||
PMCDBG(LOG,SAM,1,"pm=%p pid=%d n=%d", pm, ps->ps_pid, | PMCDBG3(LOG,SAM,1,"pm=%p pid=%d n=%d", pm, ps->ps_pid, | ||||
ps->ps_nsamples); | ps->ps_nsamples); | ||||
recordlen = offsetof(struct pmclog_callchain, pl_pc) + | recordlen = offsetof(struct pmclog_callchain, pl_pc) + | ||||
ps->ps_nsamples * sizeof(uintfptr_t); | ps->ps_nsamples * sizeof(uintfptr_t); | ||||
po = pm->pm_owner; | po = pm->pm_owner; | ||||
flags = PMC_CALLCHAIN_TO_CPUFLAGS(ps->ps_cpu,ps->ps_flags); | flags = PMC_CALLCHAIN_TO_CPUFLAGS(ps->ps_cpu,ps->ps_flags); | ||||
PMCLOG_RESERVE(po, CALLCHAIN, recordlen); | PMCLOG_RESERVE(po, CALLCHAIN, recordlen); | ||||
PMCLOG_EMIT32(ps->ps_pid); | PMCLOG_EMIT32(ps->ps_pid); | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
void | void | ||||
pmclog_process_pmcallocate(struct pmc *pm) | pmclog_process_pmcallocate(struct pmc *pm) | ||||
{ | { | ||||
struct pmc_owner *po; | struct pmc_owner *po; | ||||
struct pmc_soft *ps; | struct pmc_soft *ps; | ||||
po = pm->pm_owner; | po = pm->pm_owner; | ||||
PMCDBG(LOG,ALL,1, "pm=%p", pm); | PMCDBG1(LOG,ALL,1, "pm=%p", pm); | ||||
if (PMC_TO_CLASS(pm) == PMC_CLASS_SOFT) { | if (PMC_TO_CLASS(pm) == PMC_CLASS_SOFT) { | ||||
PMCLOG_RESERVE(po, PMCALLOCATEDYN, | PMCLOG_RESERVE(po, PMCALLOCATEDYN, | ||||
sizeof(struct pmclog_pmcallocatedyn)); | sizeof(struct pmclog_pmcallocatedyn)); | ||||
PMCLOG_EMIT32(pm->pm_id); | PMCLOG_EMIT32(pm->pm_id); | ||||
PMCLOG_EMIT32(pm->pm_event); | PMCLOG_EMIT32(pm->pm_event); | ||||
PMCLOG_EMIT32(pm->pm_flags); | PMCLOG_EMIT32(pm->pm_flags); | ||||
ps = pmc_soft_ev_acquire(pm->pm_event); | ps = pmc_soft_ev_acquire(pm->pm_event); | ||||
Show All 14 Lines | |||||
} | } | ||||
void | void | ||||
pmclog_process_pmcattach(struct pmc *pm, pid_t pid, char *path) | pmclog_process_pmcattach(struct pmc *pm, pid_t pid, char *path) | ||||
{ | { | ||||
int pathlen, recordlen; | int pathlen, recordlen; | ||||
struct pmc_owner *po; | struct pmc_owner *po; | ||||
PMCDBG(LOG,ATT,1,"pm=%p pid=%d", pm, pid); | PMCDBG2(LOG,ATT,1,"pm=%p pid=%d", pm, pid); | ||||
po = pm->pm_owner; | po = pm->pm_owner; | ||||
pathlen = strlen(path) + 1; /* #bytes for the string */ | pathlen = strlen(path) + 1; /* #bytes for the string */ | ||||
recordlen = offsetof(struct pmclog_pmcattach, pl_pathname) + pathlen; | recordlen = offsetof(struct pmclog_pmcattach, pl_pathname) + pathlen; | ||||
PMCLOG_RESERVE(po, PMCATTACH, recordlen); | PMCLOG_RESERVE(po, PMCATTACH, recordlen); | ||||
PMCLOG_EMIT32(pm->pm_id); | PMCLOG_EMIT32(pm->pm_id); | ||||
PMCLOG_EMIT32(pid); | PMCLOG_EMIT32(pid); | ||||
PMCLOG_EMITSTRING(path, pathlen); | PMCLOG_EMITSTRING(path, pathlen); | ||||
PMCLOG_DESPATCH(po); | PMCLOG_DESPATCH(po); | ||||
} | } | ||||
void | void | ||||
pmclog_process_pmcdetach(struct pmc *pm, pid_t pid) | pmclog_process_pmcdetach(struct pmc *pm, pid_t pid) | ||||
{ | { | ||||
struct pmc_owner *po; | struct pmc_owner *po; | ||||
PMCDBG(LOG,ATT,1,"!pm=%p pid=%d", pm, pid); | PMCDBG2(LOG,ATT,1,"!pm=%p pid=%d", pm, pid); | ||||
po = pm->pm_owner; | po = pm->pm_owner; | ||||
PMCLOG_RESERVE(po, PMCDETACH, sizeof(struct pmclog_pmcdetach)); | PMCLOG_RESERVE(po, PMCDETACH, sizeof(struct pmclog_pmcdetach)); | ||||
PMCLOG_EMIT32(pm->pm_id); | PMCLOG_EMIT32(pm->pm_id); | ||||
PMCLOG_EMIT32(pid); | PMCLOG_EMIT32(pid); | ||||
PMCLOG_DESPATCH(po); | PMCLOG_DESPATCH(po); | ||||
} | } | ||||
/* | /* | ||||
* Log a context switch event to the log file. | * Log a context switch event to the log file. | ||||
*/ | */ | ||||
void | void | ||||
pmclog_process_proccsw(struct pmc *pm, struct pmc_process *pp, pmc_value_t v) | pmclog_process_proccsw(struct pmc *pm, struct pmc_process *pp, pmc_value_t v) | ||||
{ | { | ||||
struct pmc_owner *po; | struct pmc_owner *po; | ||||
KASSERT(pm->pm_flags & PMC_F_LOG_PROCCSW, | KASSERT(pm->pm_flags & PMC_F_LOG_PROCCSW, | ||||
("[pmclog,%d] log-process-csw called gratuitously", __LINE__)); | ("[pmclog,%d] log-process-csw called gratuitously", __LINE__)); | ||||
PMCDBG(LOG,SWO,1,"pm=%p pid=%d v=%jx", pm, pp->pp_proc->p_pid, | PMCDBG3(LOG,SWO,1,"pm=%p pid=%d v=%jx", pm, pp->pp_proc->p_pid, | ||||
v); | v); | ||||
po = pm->pm_owner; | po = pm->pm_owner; | ||||
PMCLOG_RESERVE(po, PROCCSW, sizeof(struct pmclog_proccsw)); | PMCLOG_RESERVE(po, PROCCSW, sizeof(struct pmclog_proccsw)); | ||||
PMCLOG_EMIT32(pm->pm_id); | PMCLOG_EMIT32(pm->pm_id); | ||||
PMCLOG_EMIT64(v); | PMCLOG_EMIT64(v); | ||||
PMCLOG_EMIT32(pp->pp_proc->p_pid); | PMCLOG_EMIT32(pp->pp_proc->p_pid); | ||||
PMCLOG_DESPATCH(po); | PMCLOG_DESPATCH(po); | ||||
} | } | ||||
void | void | ||||
pmclog_process_procexec(struct pmc_owner *po, pmc_id_t pmid, pid_t pid, | pmclog_process_procexec(struct pmc_owner *po, pmc_id_t pmid, pid_t pid, | ||||
uintfptr_t startaddr, char *path) | uintfptr_t startaddr, char *path) | ||||
{ | { | ||||
int pathlen, recordlen; | int pathlen, recordlen; | ||||
PMCDBG(LOG,EXC,1,"po=%p pid=%d path=\"%s\"", po, pid, path); | PMCDBG3(LOG,EXC,1,"po=%p pid=%d path=\"%s\"", po, pid, path); | ||||
pathlen = strlen(path) + 1; /* #bytes for the path */ | pathlen = strlen(path) + 1; /* #bytes for the path */ | ||||
recordlen = offsetof(struct pmclog_procexec, pl_pathname) + pathlen; | recordlen = offsetof(struct pmclog_procexec, pl_pathname) + pathlen; | ||||
PMCLOG_RESERVE(po, PROCEXEC, recordlen); | PMCLOG_RESERVE(po, PROCEXEC, recordlen); | ||||
PMCLOG_EMIT32(pid); | PMCLOG_EMIT32(pid); | ||||
PMCLOG_EMITADDR(startaddr); | PMCLOG_EMITADDR(startaddr); | ||||
PMCLOG_EMIT32(pmid); | PMCLOG_EMIT32(pmid); | ||||
PMCLOG_EMITSTRING(path,pathlen); | PMCLOG_EMITSTRING(path,pathlen); | ||||
PMCLOG_DESPATCH(po); | PMCLOG_DESPATCH(po); | ||||
} | } | ||||
/* | /* | ||||
* Log a process exit event (and accumulated pmc value) to the log file. | * Log a process exit event (and accumulated pmc value) to the log file. | ||||
*/ | */ | ||||
void | void | ||||
pmclog_process_procexit(struct pmc *pm, struct pmc_process *pp) | pmclog_process_procexit(struct pmc *pm, struct pmc_process *pp) | ||||
{ | { | ||||
int ri; | int ri; | ||||
struct pmc_owner *po; | struct pmc_owner *po; | ||||
ri = PMC_TO_ROWINDEX(pm); | ri = PMC_TO_ROWINDEX(pm); | ||||
PMCDBG(LOG,EXT,1,"pm=%p pid=%d v=%jx", pm, pp->pp_proc->p_pid, | PMCDBG3(LOG,EXT,1,"pm=%p pid=%d v=%jx", pm, pp->pp_proc->p_pid, | ||||
pp->pp_pmcs[ri].pp_pmcval); | pp->pp_pmcs[ri].pp_pmcval); | ||||
po = pm->pm_owner; | po = pm->pm_owner; | ||||
PMCLOG_RESERVE(po, PROCEXIT, sizeof(struct pmclog_procexit)); | PMCLOG_RESERVE(po, PROCEXIT, sizeof(struct pmclog_procexit)); | ||||
PMCLOG_EMIT32(pm->pm_id); | PMCLOG_EMIT32(pm->pm_id); | ||||
PMCLOG_EMIT64(pp->pp_pmcs[ri].pp_pmcval); | PMCLOG_EMIT64(pp->pp_pmcs[ri].pp_pmcval); | ||||
PMCLOG_EMIT32(pp->pp_proc->p_pid); | PMCLOG_EMIT32(pp->pp_proc->p_pid); | ||||
Show All 29 Lines | |||||
* Write a user log entry. | * Write a user log entry. | ||||
*/ | */ | ||||
int | int | ||||
pmclog_process_userlog(struct pmc_owner *po, struct pmc_op_writelog *wl) | pmclog_process_userlog(struct pmc_owner *po, struct pmc_op_writelog *wl) | ||||
{ | { | ||||
int error; | int error; | ||||
PMCDBG(LOG,WRI,1, "writelog po=%p ud=0x%x", po, wl->pm_userdata); | PMCDBG2(LOG,WRI,1, "writelog po=%p ud=0x%x", po, wl->pm_userdata); | ||||
error = 0; | error = 0; | ||||
PMCLOG_RESERVE_WITH_ERROR(po, USERDATA, | PMCLOG_RESERVE_WITH_ERROR(po, USERDATA, | ||||
sizeof(struct pmclog_userdata)); | sizeof(struct pmclog_userdata)); | ||||
PMCLOG_EMIT32(wl->pm_userdata); | PMCLOG_EMIT32(wl->pm_userdata); | ||||
PMCLOG_DESPATCH(po); | PMCLOG_DESPATCH(po); | ||||
▲ Show 20 Lines • Show All 59 Lines • Show Last 20 Lines |