summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/hwpmc/hwpmc_soft.c21
-rw-r--r--sys/kern/kern_clock.c3
-rw-r--r--sys/sys/pmckern.h9
3 files changed, 24 insertions, 9 deletions
diff --git a/sys/dev/hwpmc/hwpmc_soft.c b/sys/dev/hwpmc/hwpmc_soft.c
index 48e297e..56af775 100644
--- a/sys/dev/hwpmc/hwpmc_soft.c
+++ b/sys/dev/hwpmc/hwpmc_soft.c
@@ -45,8 +45,6 @@ __FBSDID("$FreeBSD$");
#define SOFT_CAPS (PMC_CAP_READ | PMC_CAP_WRITE | PMC_CAP_INTERRUPT | \
PMC_CAP_USER | PMC_CAP_SYSTEM)
-PMC_SOFT_DECLARE( , , clock, prof);
-
struct soft_descr {
struct pmc_descr pm_descr; /* "base class" */
};
@@ -126,9 +124,10 @@ soft_allocate_pmc(int cpu, int ri, struct pmc *pm,
if (ps == NULL)
return (EINVAL);
pmc_soft_ev_release(ps);
+ /* Module unload is protected by pmc SX lock. */
+ if (ps->ps_alloc != NULL)
+ ps->ps_alloc();
- if (ev == pmc___clock_prof.ps_ev.pm_ev_code)
- cpu_startprofclock();
return (0);
}
@@ -315,6 +314,8 @@ static int
soft_release_pmc(int cpu, int ri, struct pmc *pmc)
{
struct pmc_hw *phw;
+ enum pmc_event ev;
+ struct pmc_soft *ps;
(void) pmc;
@@ -328,8 +329,16 @@ soft_release_pmc(int cpu, int ri, struct pmc *pmc)
KASSERT(phw->phw_pmc == NULL,
("[soft,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc));
- if (pmc->pm_event == pmc___clock_prof.ps_ev.pm_ev_code)
- cpu_stopprofclock();
+ ev = pmc->pm_event;
+
+ /* Check if event is registered. */
+ ps = pmc_soft_ev_acquire(ev);
+ KASSERT(ps != NULL,
+ ("[soft,%d] unregistered event %d", __LINE__, ev));
+ pmc_soft_ev_release(ps);
+ /* Module unload is protected by pmc SX lock. */
+ if (ps->ps_release != NULL)
+ ps->ps_release();
return (0);
}
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
index 4439ccb..2841f8c 100644
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -78,7 +78,8 @@ __FBSDID("$FreeBSD$");
#include <sys/pmckern.h>
PMC_SOFT_DEFINE( , , clock, hard);
PMC_SOFT_DEFINE( , , clock, stat);
-PMC_SOFT_DEFINE( , , clock, prof);
+PMC_SOFT_DEFINE_EX( , , clock, prof, \
+ cpu_startprofclock, cpu_stopprofclock);
#endif
#ifdef DEVICE_POLLING
diff --git a/sys/sys/pmckern.h b/sys/sys/pmckern.h
index c623648..e3e18a6 100644
--- a/sys/sys/pmckern.h
+++ b/sys/sys/pmckern.h
@@ -87,9 +87,9 @@ struct pmckern_soft {
* Soft PMC.
*/
-#define PMC_SOFT_DEFINE(prov, mod, func, name) \
+#define PMC_SOFT_DEFINE_EX(prov, mod, func, name, alloc, release) \
struct pmc_soft pmc_##prov##_##mod##_##func##_##name = \
- { 0, { #prov "_" #mod "_" #func "." #name, 0 } }; \
+ { 0, alloc, release, { #prov "_" #mod "_" #func "." #name, 0 } }; \
SYSINIT(pmc_##prov##_##mod##_##func##_##name##_init, SI_SUB_KDTRACE, \
SI_ORDER_SECOND + 1, pmc_soft_ev_register, \
&pmc_##prov##_##mod##_##func##_##name ); \
@@ -97,6 +97,9 @@ struct pmckern_soft {
SI_SUB_KDTRACE, SI_ORDER_SECOND + 1, pmc_soft_ev_deregister, \
&pmc_##prov##_##mod##_##func##_##name )
+#define PMC_SOFT_DEFINE(prov, mod, func, name) \
+ PMC_SOFT_DEFINE_EX(prov, mod, func, name, NULL, NULL)
+
#define PMC_SOFT_DECLARE(prov, mod, func, name) \
extern struct pmc_soft pmc_##prov##_##mod##_##func##_##name
@@ -147,6 +150,8 @@ do { \
struct pmc_soft {
int ps_running;
+ void (*ps_alloc)(void);
+ void (*ps_release)(void);
struct pmc_dyn_event_descr ps_ev;
};
OpenPOWER on IntegriCloud