aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index 131eb3575e24..a5df748073a0 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -2538,13 +2538,35 @@ static int
pmc_find_pmc(pmc_id_t pmcid, struct pmc **pmc)
{
- struct pmc *pm;
+ struct pmc *pm, *opm;
struct pmc_owner *po;
+ struct pmc_process *pp;
+ KASSERT(PMC_ID_TO_ROWINDEX(pmcid) < md->pmd_npmc,
+ ("[pmc,%d] Illegal pmc index %d (max %d)", __LINE__,
+ PMC_ID_TO_ROWINDEX(pmcid), md->pmd_npmc));
PMCDBG1(PMC,FND,1, "find-pmc id=%d", pmcid);
- if ((po = pmc_find_owner_descriptor(curthread->td_proc)) == NULL)
- return ESRCH;
+ if ((po = pmc_find_owner_descriptor(curthread->td_proc)) == NULL) {
+ /*
+ * In case of PMC_F_DESCENDANTS child processes we will not find
+ * the current process in the owners hash list. Find the owner
+ * process first and from there lookup the po.
+ */
+ if ((pp = pmc_find_process_descriptor(curthread->td_proc,
+ PMC_FLAG_NONE)) == NULL) {
+ return ESRCH;
+ } else {
+ opm = pp->pp_pmcs[PMC_ID_TO_ROWINDEX(pmcid)].pp_pmc;
+ if (opm == NULL)
+ return ESRCH;
+ if ((opm->pm_flags & (PMC_F_ATTACHED_TO_OWNER|
+ PMC_F_DESCENDANTS)) != (PMC_F_ATTACHED_TO_OWNER|
+ PMC_F_DESCENDANTS))
+ return ESRCH;
+ po = opm->pm_owner;
+ }
+ }
if ((pm = pmc_find_pmc_descriptor_in_process(po, pmcid)) == NULL)
return EINVAL;