diff options
-rw-r--r-- | sys/dev/hwpmc/hwpmc_soft.c | 21 | ||||
-rw-r--r-- | sys/kern/kern_clock.c | 3 | ||||
-rw-r--r-- | sys/sys/pmckern.h | 9 |
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; }; |