[PATCH 1/1] perf: Have NOP txn interface ignore non ADD txns

From: Sukadev Bhattiprolu
Date: Thu Apr 09 2015 - 13:47:50 EST


The NOP txn interface should ignore non TXN_ADD transactions and
avoid disabling/enabling the PMU.

Use a per-cpu, per-PMU flag to store/check the type of transaction
in progress.

Thanks to Peter Zijlstra for the input.

Signed-off-by: Sukadev Bhattiprolu <sukadev@xxxxxxxxxxxxxxxxxx>
---

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 9e869b2..9466864 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -160,7 +160,10 @@ struct perf_event;
/*
* Common implementation detail of pmu::{start,commit,cancel}_txn
*/
-#define PERF_EVENT_TXN 0x1
+#define PERF_EVENT_TXN_ADD 0x1 /* txn to add/schedule event on PMU */
+#define PERF_EVENT_TXN_READ 0x2 /* txn to add/schedule event on PMU */
+
+#define PERF_EVENT_TXN_MASK (PERF_EVENT_TXN_ADD|PERF_EVENT_TXN_READ)

/**
* pmu::capabilities flags
@@ -240,8 +243,10 @@ struct pmu {
*
* Start the transaction, after this ->add() doesn't need to
* do schedulability tests.
+ *
+ * Optional.
*/
- void (*start_txn) (struct pmu *pmu); /* optional */
+ void (*start_txn) (struct pmu *pmu, int flags);
/*
* If ->start_txn() disabled the ->add() schedulability test
* then ->commit_txn() is required to perform one. On success
@@ -534,6 +534,7 @@ struct perf_cpu_context {
ktime_t hrtimer_interval;
struct pmu *unique_pmu;
struct perf_cgroup *cgrp;
+ int group_flag;
};

struct perf_output_handle {
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 0ebc468..08d0c3e 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6746,18 +6746,35 @@ static int perf_pmu_nop_int(struct pmu *pmu)

static void perf_pmu_start_txn(struct pmu *pmu, int flags)
{
- perf_pmu_disable(pmu);
+ struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
+
+ BUG_ON(cpuctx->group_flag);
+
+ cpuctx->group_flag = flags;
+
+ if (flags & PERF_EVENT_TXN_ADD)
+ perf_pmu_disable(pmu);
}

static int perf_pmu_commit_txn(struct pmu *pmu)
{
- perf_pmu_enable(pmu);
+ struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
+
+ if (cpuctx->group_flag & PERF_EVENT_TXN_ADD)
+ perf_pmu_enable(pmu);
+
+ cpuctx->group_flag &= ~PERF_EVENT_TXN_MASK;
return 0;
}

static void perf_pmu_cancel_txn(struct pmu *pmu)
{
- perf_pmu_enable(pmu);
+ struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
+
+ if (cpuctx->group_flag & PERF_EVENT_TXN_ADD)
+ perf_pmu_enable(pmu);
+
+ cpuctx->group_flag &= ~PERF_EVENT_TXN_MASK;
}

static int perf_event_idx_default(struct perf_event *event)

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/