Thread (6 messages) flat view 6 messages, 2 authors, 2017-09-04

Re: [PATCH v2 net-next 1/4] bpf: add helper bpf_perf_read_counter_time for perf event array map

From: Peter Zijlstra <peterz@infradead.org>
Date: 2017-09-04 07:46:44

On Fri, Sep 01, 2017 at 10:48:21PM -0700, Yonghong Song wrote:
quoted hunk ↗ jump to hunk
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index b14095b..5a50808 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -898,7 +898,8 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr,
 				void *context);
 extern void perf_pmu_migrate_context(struct pmu *pmu,
 				int src_cpu, int dst_cpu);
-int perf_event_read_local(struct perf_event *event, u64 *value);
+int perf_event_read_local(struct perf_event *event, u64 *value,
+			  u64 *enabled, u64 *running);
 extern u64 perf_event_read_value(struct perf_event *event,
 				 u64 *enabled, u64 *running);
 
quoted hunk ↗ jump to hunk
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 8c01572..20c4039 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3670,7 +3670,8 @@ static inline u64 perf_event_count(struct perf_event *event)
  *     will not be local and we cannot read them atomically
  *   - must not have a pmu::count method
  */
-int perf_event_read_local(struct perf_event *event, u64 *value)
+int perf_event_read_local(struct perf_event *event, u64 *value,
+			  u64 *enabled, u64 *running)
 {
 	unsigned long flags;
 	int ret = 0;
@@ -3694,7 +3695,7 @@ int perf_event_read_local(struct perf_event *event, u64 *value)
 	 * It must not have a pmu::count method, those are not
 	 * NMI safe.
 	 */
-	if (event->pmu->count) {
+	if (value && event->pmu->count) {
 		ret = -EOPNOTSUPP;
 		goto out;
 	}
No, value _must_ be !NULL. Otherwise you allow getting timestamps
independently from the count value and that is broken.

The {value, enabled, running} tuple is temporally related.
quoted hunk ↗ jump to hunk
@@ -3718,10 +3719,16 @@ int perf_event_read_local(struct perf_event *event, u64 *value)
 	 * or local to this CPU. Furthermore it means its ACTIVE (otherwise
 	 * oncpu == -1).
 	 */
-	if (event->oncpu == smp_processor_id())
-		event->pmu->read(event);
-
-	*value = local64_read(&event->count);
+	if (value) {
+		if (event->oncpu == smp_processor_id())
+			event->pmu->read(event);
+		*value = local64_read(&event->count);
+	}
+	if (enabled && running) {
+		u64 ctx_time = event->shadow_ctx_time + perf_clock();
+		*enabled = ctx_time - event->tstamp_enabled;
+		*running = ctx_time - event->tstamp_running;
+	}
 out:
 	local_irq_restore(flags);
Please make that something like:


	u64 now = event->shadow_ctx_time + perf_clock();

	if (enabled)
		*enabled = now - event->tstamp_enabled;

	if (event->oncpu == smp_processor_id()) {
		event->pmu->read(event);
		if (running)
			*running = now - event->tstamp_running;
	} else {
		*running = event->total_time_running;
	}

And I'll fix it up when I make:

  https://lkml.kernel.org/r/20170831171837.njnc6r6elsvkl7lt@hirez.programming.kicks-ass.net

happen.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help