@@ -742,11 +742,8 @@ void w_display_cpu_pstates(void)
struct power_entry {
-#ifndef __i386__
- int dummy;
-#endif
- int64_t type;
- int64_t value;
+ uint64_t type;
+ uint64_t value;
} __attribute__((packed));
@@ -27,6 +27,7 @@
#include <algorithm>
#include <string.h>
#include <stdint.h>
+#include <dirent.h>
#include "perf_bundle.h"
#include "perf_event.h"
@@ -110,11 +111,30 @@ void perf_bundle::add_event(const char *event_name)
}
}
}
-
+static int lock_depth = 0;
void perf_bundle::start(void)
{
unsigned int i;
class perf_event *ev;
+ char line[1023];
+ FILE *file;
+ char filename[PATH_MAX];
+
+ /*check the format of power_frequency event*/
+ strcpy(filename,
+ "/sys/kernel/debug/tracing/events/power/power_frequency/format");
+ if (!lock_depth) {
+ file = fopen(filename, "r");
+ if (file) {
+ while (fgets(line, 1023,file) != NULL) {
+ if (strstr(line, "lock_depth")) {
+ lock_depth = 1;
+ break;
+ }
+ }
+ fclose(file);
+ }
+ }
for (i = 0; i < events.size(); i++) {
ev = events[i];
@@ -154,34 +174,57 @@ void perf_bundle::clear(void)
records.resize(0);
}
-
-struct trace_entry {
+/*Trace entry for the common fields of perf events*/
+struct trace_entry_common {
uint64_t time;
uint32_t cpu;
uint32_t res;
__u32 size;
+} __attribute__((packed));
+
+/*Trace entry for the fields specific to each perf events.
+* lock_depth field to support old kernels*/
+struct trace_data_lockdepth {
unsigned short type;
unsigned char flags;
unsigned char preempt_count;
int pid;
int lock_depth;
+#ifndef __i386__
+ int filler;
+#endif
} __attribute__((packed));;
+/*Trace entry for the fields specific to each perf events*/
+struct trace_data_normal {
+ unsigned short type;
+ unsigned char flags;
+ unsigned char preempt_count;
+ int pid;
+} __attribute__((packed));;
-struct perf_sample {
+struct perf_sample_normal {
struct perf_event_header header;
- struct trace_entry trace;
+ struct trace_entry_common trace_common;
+ struct trace_data_normal trace_data;
unsigned char data[0];
} __attribute__((packed));
+struct perf_sample_lockdepth {
+ struct perf_event_header header;
+ struct trace_entry_common trace_common;
+ struct trace_data_lockdepth trace_data;
+ unsigned char data[0];
+} __attribute__((packed));;
+
static uint64_t timestamp(perf_event_header *event)
{
- struct perf_sample *sample;
+ struct perf_sample_lockdepth *sample;
if (event->type != PERF_RECORD_SAMPLE)
return 0;
- sample = (struct perf_sample *)event;
+ sample = (struct perf_sample_lockdepth *)event;
#if 0
int i;
@@ -207,7 +250,7 @@ static uint64_t timestamp(perf_event_header *event)
printf("%02x ", *(x+i));
printf("\n");
#endif
- return sample->trace.time;
+ return sample->trace_common.time;
}
@@ -235,16 +278,35 @@ void perf_bundle::process(void)
sort(records.begin(), records.end(), event_sort_function);
for (i = 0; i < records.size(); i++) {
- struct perf_sample *sample;
-
- sample = (struct perf_sample *)records[i];
- if (!sample)
- continue;
-
- if (sample->header.type != PERF_RECORD_SAMPLE)
- continue;
-
- handle_trace_point(sample->trace.type, &sample->data, sample->trace.cpu, sample->trace.time, sample->trace.flags);
+ /*Check for lock_depth */
+ if (lock_depth) {
+ struct perf_sample_lockdepth *sample =
+ (struct perf_sample_lockdepth *)records[i];
+ if (!sample)
+ continue;
+
+ if (sample->header.type != PERF_RECORD_SAMPLE)
+ continue;
+
+ handle_trace_point(sample->trace_data.type,
+ &sample->data, sample->trace_common.cpu,
+ sample->trace_common.time,
+ sample->trace_data.flags);
+ }
+ else {
+ struct perf_sample_normal *sample =
+ (struct perf_sample_normal *)records[i];
+ if (!sample)
+ continue;
+
+ if (sample->header.type != PERF_RECORD_SAMPLE)
+ continue;
+
+ handle_trace_point(sample->trace_data.type,
+ &sample->data, sample->trace_common.cpu,
+ sample->trace_common.time,
+ sample->trace_data.flags);
+ }
}
}
lock_depth field is removed from the power frequency events in the new linux kernel(2.6.38 onwards). So this creates issue to retrieve the lower members of the trace data. To fix this problem 2 separate structures are created and their use depends upon the format of the power_frequency events. These changes have been tested to work fine with both old and new kernels as well as on x86 and ARM platform. Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> --- This patch is for powertop2.0 and fixes the issue of frequency reported as always 0 in kernel from 2.6.38 onwards. cpu/cpu.cpp | 7 +--- perf/perf_bundle.cpp | 98 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 82 insertions(+), 23 deletions(-)