Commit 64999e44 authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

perf lock: Extend struct lock_key to have print function

And use it to print output for each key field.  No functional change
intended and the output should be identical.
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220323230259.288494-2-namhyung@kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 67b61f59
...@@ -237,9 +237,43 @@ struct lock_key { ...@@ -237,9 +237,43 @@ struct lock_key {
* e.g. nr_acquired -> acquired, wait_time_total -> wait_total * e.g. nr_acquired -> acquired, wait_time_total -> wait_total
*/ */
const char *name; const char *name;
/* header: the string printed on the header line */
const char *header;
/* len: the printing width of the field */
int len;
/* key: a pointer to function to compare two lock stats for sorting */
int (*key)(struct lock_stat*, struct lock_stat*); int (*key)(struct lock_stat*, struct lock_stat*);
/* print: a pointer to function to print a given lock stats */
void (*print)(struct lock_key*, struct lock_stat*);
/* list: list entry to link this */
struct list_head list;
}; };
#define PRINT_KEY(member) \
static void lock_stat_key_print_ ## member(struct lock_key *key, \
struct lock_stat *ls) \
{ \
pr_info("%*llu", key->len, (unsigned long long)ls->member); \
}
PRINT_KEY(nr_acquired)
PRINT_KEY(nr_contended)
PRINT_KEY(avg_wait_time)
PRINT_KEY(wait_time_total)
PRINT_KEY(wait_time_max)
static void lock_stat_key_print_wait_time_min(struct lock_key *key,
struct lock_stat *ls)
{
u64 wait_time = ls->wait_time_min;
if (wait_time == ULLONG_MAX)
wait_time = 0;
pr_info("%*"PRIu64, key->len, wait_time);
}
static const char *sort_key = "acquired"; static const char *sort_key = "acquired";
static int (*compare)(struct lock_stat *, struct lock_stat *); static int (*compare)(struct lock_stat *, struct lock_stat *);
...@@ -247,19 +281,20 @@ static int (*compare)(struct lock_stat *, struct lock_stat *); ...@@ -247,19 +281,20 @@ static int (*compare)(struct lock_stat *, struct lock_stat *);
static struct rb_root sorted; /* place to store intermediate data */ static struct rb_root sorted; /* place to store intermediate data */
static struct rb_root result; /* place to store sorted data */ static struct rb_root result; /* place to store sorted data */
#define DEF_KEY_LOCK(name, fn_suffix) \ static LIST_HEAD(lock_keys);
{ #name, lock_stat_key_ ## fn_suffix }
#define DEF_KEY_LOCK(name, header, fn_suffix, len) \
{ #name, header, len, lock_stat_key_ ## fn_suffix, lock_stat_key_print_ ## fn_suffix, {} }
struct lock_key keys[] = { struct lock_key keys[] = {
DEF_KEY_LOCK(acquired, nr_acquired), DEF_KEY_LOCK(acquired, "acquired", nr_acquired, 10),
DEF_KEY_LOCK(contended, nr_contended), DEF_KEY_LOCK(contended, "contended", nr_contended, 10),
DEF_KEY_LOCK(avg_wait, avg_wait_time), DEF_KEY_LOCK(avg_wait, "avg wait (ns)", avg_wait_time, 15),
DEF_KEY_LOCK(wait_total, wait_time_total), DEF_KEY_LOCK(wait_total, "total wait (ns)", wait_time_total, 15),
DEF_KEY_LOCK(wait_min, wait_time_min), DEF_KEY_LOCK(wait_max, "max wait (ns)", wait_time_max, 15),
DEF_KEY_LOCK(wait_max, wait_time_max), DEF_KEY_LOCK(wait_min, "min wait (ns)", wait_time_min, 15),
/* extra comparisons much complicated should be here */ /* extra comparisons much complicated should be here */
{ }
{ NULL, NULL }
}; };
static int select_key(void) static int select_key(void)
...@@ -278,6 +313,16 @@ static int select_key(void) ...@@ -278,6 +313,16 @@ static int select_key(void)
return -1; return -1;
} }
static int setup_output_field(void)
{
int i;
for (i = 0; keys[i].name; i++)
list_add_tail(&keys[i].list, &lock_keys);
return 0;
}
static void combine_lock_stats(struct lock_stat *st) static void combine_lock_stats(struct lock_stat *st)
{ {
struct rb_node **rb = &sorted.rb_node; struct rb_node **rb = &sorted.rb_node;
...@@ -753,18 +798,13 @@ static void print_bad_events(int bad, int total) ...@@ -753,18 +798,13 @@ static void print_bad_events(int bad, int total)
static void print_result(void) static void print_result(void)
{ {
struct lock_stat *st; struct lock_stat *st;
struct lock_key *key;
char cut_name[20]; char cut_name[20];
int bad, total; int bad, total;
pr_info("%20s ", "Name"); pr_info("%20s ", "Name");
pr_info("%10s ", "acquired"); list_for_each_entry(key, &lock_keys, list)
pr_info("%10s ", "contended"); pr_info("%*s ", key->len, key->header);
pr_info("%15s ", "avg wait (ns)");
pr_info("%15s ", "total wait (ns)");
pr_info("%15s ", "max wait (ns)");
pr_info("%15s ", "min wait (ns)");
pr_info("\n\n"); pr_info("\n\n");
bad = total = 0; bad = total = 0;
...@@ -789,14 +829,10 @@ static void print_result(void) ...@@ -789,14 +829,10 @@ static void print_result(void)
pr_info("%20s ", cut_name); pr_info("%20s ", cut_name);
} }
pr_info("%10u ", st->nr_acquired); list_for_each_entry(key, &lock_keys, list) {
pr_info("%10u ", st->nr_contended); key->print(key, st);
pr_info(" ");
pr_info("%15" PRIu64 " ", st->avg_wait_time); }
pr_info("%15" PRIu64 " ", st->wait_time_total);
pr_info("%15" PRIu64 " ", st->wait_time_max);
pr_info("%15" PRIu64 " ", st->wait_time_min == ULLONG_MAX ?
0 : st->wait_time_min);
pr_info("\n"); pr_info("\n");
} }
...@@ -966,6 +1002,9 @@ static int __cmd_report(bool display_info) ...@@ -966,6 +1002,9 @@ static int __cmd_report(bool display_info)
goto out_delete; goto out_delete;
} }
if (setup_output_field())
goto out_delete;
if (select_key()) if (select_key())
goto out_delete; goto out_delete;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment