aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/hwpmc/hwpmc_mod.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/hwpmc/hwpmc_mod.c')
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c92
1 files changed, 87 insertions, 5 deletions
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index e9c47881894e..191f2554ee60 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -269,6 +269,11 @@ static int generic_switch_out(struct pmc_cpu *pc, struct pmc_process *pp);
static struct pmc_mdep *pmc_generic_cpu_initialize(void);
static void pmc_generic_cpu_finalize(struct pmc_mdep *md);
static void pmc_post_callchain_callback(void);
+static void pmc_process_threadcreate(struct thread *td);
+static void pmc_process_threadexit(struct thread *td);
+static void pmc_process_proccreate(struct proc *p);
+static void pmc_process_allproc(struct pmc *pm);
+
/*
* Kernel tunables and sysctl(8) interface.
*/
@@ -2049,6 +2054,9 @@ const char *pmc_hooknames[] = {
"THR-CREATE",
"THR-EXIT",
"THR-USERRET",
+ "THR-CREATE-LOG",
+ "THR-EXIT-LOG",
+ "PROC-CREATE-LOG"
};
#endif
@@ -2225,6 +2233,10 @@ pmc_hook_handler(struct thread *td, int function, void *arg)
pmc_process_munmap(td, (struct pmckern_map_out *) arg);
break;
+ case PMC_FN_PROC_CREATE_LOG:
+ pmc_process_proccreate((struct proc *)arg);
+ break;
+
case PMC_FN_USER_CALLCHAIN:
/*
* Record a call chain.
@@ -2270,14 +2282,22 @@ pmc_hook_handler(struct thread *td, int function, void *arg)
case PMC_FN_THR_CREATE:
pmc_process_thread_add(td);
+ pmc_process_threadcreate(td);
+ break;
+
+ case PMC_FN_THR_CREATE_LOG:
+ pmc_process_threadcreate(td);
break;
case PMC_FN_THR_EXIT:
KASSERT(td == curthread, ("[pmc,%d] td != curthread",
__LINE__));
pmc_process_thread_delete(td);
+ pmc_process_threadexit(td);
+ break;
+ case PMC_FN_THR_EXIT_LOG:
+ pmc_process_threadexit(td);
break;
-
case PMC_FN_THR_USERRET:
KASSERT(td == curthread, ("[pmc,%d] td != curthread",
__LINE__));
@@ -2697,9 +2717,9 @@ pmc_wait_for_pmc_idle(struct pmc *pm)
* Loop (with a forced context switch) till the PMC's runcount
* comes down to zero.
*/
- pmclog_flush(pm->pm_owner);
+ pmclog_flush(pm->pm_owner, 1);
while (counter_u64_fetch(pm->pm_runcount) > 0) {
- pmclog_flush(pm->pm_owner);
+ pmclog_flush(pm->pm_owner, 1);
#ifdef HWPMC_DEBUG
maxloop--;
KASSERT(maxloop > 0,
@@ -3439,7 +3459,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
break;
}
- error = pmclog_flush(po);
+ error = pmclog_flush(po, 0);
}
break;
@@ -4015,6 +4035,8 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
pmc = NULL;
break;
}
+ if (mode == PMC_MODE_SS)
+ pmc_process_allproc(pmc);
/*
* Return the allocated index.
@@ -5216,8 +5238,10 @@ pmc_process_fork(void *arg __unused, struct proc *p1, struct proc *newproc,
*/
epoch_enter_preempt(global_epoch_preempt);
CK_LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
- if (po->po_flags & PMC_PO_OWNS_LOGFILE)
+ if (po->po_flags & PMC_PO_OWNS_LOGFILE) {
pmclog_process_procfork(po, p1->p_pid, newproc->p_pid);
+ pmclog_process_proccreate(po, newproc, 1);
+ }
epoch_exit_preempt(global_epoch_preempt);
if (!is_using_hwpmcs)
@@ -5280,6 +5304,64 @@ pmc_process_fork(void *arg __unused, struct proc *p1, struct proc *newproc,
}
static void
+pmc_process_threadcreate(struct thread *td)
+{
+ struct pmc_owner *po;
+
+ epoch_enter_preempt(global_epoch_preempt);
+ CK_LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
+ if (po->po_flags & PMC_PO_OWNS_LOGFILE)
+ pmclog_process_threadcreate(po, td, 1);
+ epoch_exit_preempt(global_epoch_preempt);
+}
+
+static void
+pmc_process_threadexit(struct thread *td)
+{
+ struct pmc_owner *po;
+
+ epoch_enter_preempt(global_epoch_preempt);
+ CK_LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
+ if (po->po_flags & PMC_PO_OWNS_LOGFILE)
+ pmclog_process_threadexit(po, td);
+ epoch_exit_preempt(global_epoch_preempt);
+}
+
+static void
+pmc_process_proccreate(struct proc *p)
+{
+ struct pmc_owner *po;
+
+ epoch_enter_preempt(global_epoch_preempt);
+ CK_LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
+ if (po->po_flags & PMC_PO_OWNS_LOGFILE)
+ pmclog_process_proccreate(po, p, 1 /* sync */);
+ epoch_exit_preempt(global_epoch_preempt);
+}
+
+static void
+pmc_process_allproc(struct pmc *pm)
+{
+ struct pmc_owner *po;
+ struct thread *td;
+ struct proc *p;
+
+ po = pm->pm_owner;
+ if ((po->po_flags & PMC_PO_OWNS_LOGFILE) == 0)
+ return;
+ sx_slock(&allproc_lock);
+ FOREACH_PROC_IN_SYSTEM(p) {
+ pmclog_process_proccreate(po, p, 0 /* sync */);
+ PROC_LOCK(p);
+ FOREACH_THREAD_IN_PROC(p, td)
+ pmclog_process_threadcreate(po, td, 0 /* sync */);
+ PROC_UNLOCK(p);
+ }
+ sx_sunlock(&allproc_lock);
+ pmclog_flush(po, 0);
+}
+
+static void
pmc_kld_load(void *arg __unused, linker_file_t lf)
{
struct pmc_owner *po;