s390/perf,oprofile: Share sampling facility

Introduce reserve/release functions to share the sampling facility
between perf and oprofile.
Also improve error handling for the sampling facility support in perf.

Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Hendrik Brueckner
2013-12-12 16:52:48 +01:00
committed by Martin Schwidefsky
parent 55baa2f831
commit e28bb79d99
5 changed files with 73 additions and 8 deletions

View File

@@ -260,16 +260,12 @@ static int sf_disable(void)
#define PMC_INIT 0
#define PMC_RELEASE 1
#define PMC_FAILURE 2
static void setup_pmc_cpu(void *flags)
{
int err;
struct cpu_hw_sf *cpusf = &__get_cpu_var(cpu_hw_sf);
/* XXX Improve error handling and pass a flag in the *flags
* variable to indicate failures. Alternatively, ignore
* (print) errors here and let the PMU functions fail if
* the per-cpu PMU_F_RESERVED flag is not.
*/
err = 0;
switch (*((int *) flags)) {
case PMC_INIT:
@@ -299,6 +295,8 @@ static void setup_pmc_cpu(void *flags)
"setup_pmc_cpu: released: cpuhw=%p\n", cpusf);
break;
}
if (err)
*((int *) flags) |= PMC_FAILURE;
}
static void release_pmc_hardware(void)
@@ -307,13 +305,22 @@ static void release_pmc_hardware(void)
irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT);
on_each_cpu(setup_pmc_cpu, &flags, 1);
perf_release_sampling();
}
static int reserve_pmc_hardware(void)
{
int flags = PMC_INIT;
int err;
err = perf_reserve_sampling();
if (err)
return err;
on_each_cpu(setup_pmc_cpu, &flags, 1);
if (flags & PMC_FAILURE) {
release_pmc_hardware();
return -ENODEV;
}
irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT);
return 0;

View File

@@ -208,3 +208,33 @@ ssize_t cpumf_events_sysfs_show(struct device *dev,
return sprintf(page, "event=0x%04llx,name=%s\n",
pmu_attr->id, attr->attr.name);
}
/* Reserve/release functions for sharing perf hardware */
static DEFINE_SPINLOCK(perf_hw_owner_lock);
static void *perf_sampling_owner;
int perf_reserve_sampling(void)
{
int err;
err = 0;
spin_lock(&perf_hw_owner_lock);
if (perf_sampling_owner) {
pr_warn("The sampling facility is already reserved by %p\n",
perf_sampling_owner);
err = -EBUSY;
} else
perf_sampling_owner = __builtin_return_address(0);
spin_unlock(&perf_hw_owner_lock);
return err;
}
EXPORT_SYMBOL(perf_reserve_sampling);
void perf_release_sampling(void)
{
spin_lock(&perf_hw_owner_lock);
WARN_ON(!perf_sampling_owner);
perf_sampling_owner = NULL;
spin_unlock(&perf_hw_owner_lock);
}
EXPORT_SYMBOL(perf_release_sampling);