perf intel-pt: Improve sync_switch by processing PERF_RECORD_SWITCH* in events
authorAdrian Hunter <adrian.hunter@intel.com>
Fri, 12 Apr 2019 11:38:29 +0000 (14:38 +0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 28 May 2019 21:37:45 +0000 (18:37 -0300)
sync_switch is a facility to synchronize decoding more closely with the
point in the kernel when the context actually switched.

Improve it by processing "context switch in" events.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190412113830.4126-8-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/intel-pt.c

index 03b1da6d1da482981d9ac9e201c5cf1fbc9c2350..6aaba1146fc81b6c874f7e6b11c874c40c75c7f9 100644 (file)
@@ -1914,6 +1914,44 @@ static int intel_pt_process_switch(struct intel_pt *pt,
        return machine__set_current_tid(pt->machine, cpu, -1, tid);
 }
 
+static int intel_pt_context_switch_in(struct intel_pt *pt,
+                                     struct perf_sample *sample)
+{
+       pid_t pid = sample->pid;
+       pid_t tid = sample->tid;
+       int cpu = sample->cpu;
+
+       if (pt->sync_switch) {
+               struct intel_pt_queue *ptq;
+
+               ptq = intel_pt_cpu_to_ptq(pt, cpu);
+               if (ptq && ptq->sync_switch) {
+                       ptq->next_tid = -1;
+                       switch (ptq->switch_state) {
+                       case INTEL_PT_SS_NOT_TRACING:
+                       case INTEL_PT_SS_UNKNOWN:
+                       case INTEL_PT_SS_TRACING:
+                               break;
+                       case INTEL_PT_SS_EXPECTING_SWITCH_EVENT:
+                       case INTEL_PT_SS_EXPECTING_SWITCH_IP:
+                               ptq->switch_state = INTEL_PT_SS_TRACING;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       /*
+        * If the current tid has not been updated yet, ensure it is now that
+        * a "switch in" event has occurred.
+        */
+       if (machine__get_current_tid(pt->machine, cpu) == tid)
+               return 0;
+
+       return machine__set_current_tid(pt->machine, cpu, pid, tid);
+}
+
 static int intel_pt_context_switch(struct intel_pt *pt, union perf_event *event,
                                   struct perf_sample *sample)
 {
@@ -1925,7 +1963,7 @@ static int intel_pt_context_switch(struct intel_pt *pt, union perf_event *event,
 
        if (pt->have_sched_switch == 3) {
                if (!out)
-                       return 0;
+                       return intel_pt_context_switch_in(pt, sample);
                if (event->header.type != PERF_RECORD_SWITCH_CPU_WIDE) {
                        pr_err("Expecting CPU-wide context switch event\n");
                        return -EINVAL;