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: Namhyung 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.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
67b61f59a6
commit
64999e4402
@ -237,9 +237,43 @@ struct lock_key {
|
||||
* e.g. nr_acquired -> acquired, wait_time_total -> wait_total
|
||||
*/
|
||||
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*);
|
||||
/* 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 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 result; /* place to store sorted data */
|
||||
|
||||
#define DEF_KEY_LOCK(name, fn_suffix) \
|
||||
{ #name, lock_stat_key_ ## fn_suffix }
|
||||
static LIST_HEAD(lock_keys);
|
||||
|
||||
#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[] = {
|
||||
DEF_KEY_LOCK(acquired, nr_acquired),
|
||||
DEF_KEY_LOCK(contended, nr_contended),
|
||||
DEF_KEY_LOCK(avg_wait, avg_wait_time),
|
||||
DEF_KEY_LOCK(wait_total, wait_time_total),
|
||||
DEF_KEY_LOCK(wait_min, wait_time_min),
|
||||
DEF_KEY_LOCK(wait_max, wait_time_max),
|
||||
DEF_KEY_LOCK(acquired, "acquired", nr_acquired, 10),
|
||||
DEF_KEY_LOCK(contended, "contended", nr_contended, 10),
|
||||
DEF_KEY_LOCK(avg_wait, "avg wait (ns)", avg_wait_time, 15),
|
||||
DEF_KEY_LOCK(wait_total, "total wait (ns)", wait_time_total, 15),
|
||||
DEF_KEY_LOCK(wait_max, "max wait (ns)", wait_time_max, 15),
|
||||
DEF_KEY_LOCK(wait_min, "min wait (ns)", wait_time_min, 15),
|
||||
|
||||
/* extra comparisons much complicated should be here */
|
||||
|
||||
{ NULL, NULL }
|
||||
{ }
|
||||
};
|
||||
|
||||
static int select_key(void)
|
||||
@ -278,6 +313,16 @@ static int select_key(void)
|
||||
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)
|
||||
{
|
||||
struct rb_node **rb = &sorted.rb_node;
|
||||
@ -753,18 +798,13 @@ static void print_bad_events(int bad, int total)
|
||||
static void print_result(void)
|
||||
{
|
||||
struct lock_stat *st;
|
||||
struct lock_key *key;
|
||||
char cut_name[20];
|
||||
int bad, total;
|
||||
|
||||
pr_info("%20s ", "Name");
|
||||
pr_info("%10s ", "acquired");
|
||||
pr_info("%10s ", "contended");
|
||||
|
||||
pr_info("%15s ", "avg wait (ns)");
|
||||
pr_info("%15s ", "total wait (ns)");
|
||||
pr_info("%15s ", "max wait (ns)");
|
||||
pr_info("%15s ", "min wait (ns)");
|
||||
|
||||
list_for_each_entry(key, &lock_keys, list)
|
||||
pr_info("%*s ", key->len, key->header);
|
||||
pr_info("\n\n");
|
||||
|
||||
bad = total = 0;
|
||||
@ -789,14 +829,10 @@ static void print_result(void)
|
||||
pr_info("%20s ", cut_name);
|
||||
}
|
||||
|
||||
pr_info("%10u ", st->nr_acquired);
|
||||
pr_info("%10u ", st->nr_contended);
|
||||
|
||||
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);
|
||||
list_for_each_entry(key, &lock_keys, list) {
|
||||
key->print(key, st);
|
||||
pr_info(" ");
|
||||
}
|
||||
pr_info("\n");
|
||||
}
|
||||
|
||||
@ -966,6 +1002,9 @@ static int __cmd_report(bool display_info)
|
||||
goto out_delete;
|
||||
}
|
||||
|
||||
if (setup_output_field())
|
||||
goto out_delete;
|
||||
|
||||
if (select_key())
|
||||
goto out_delete;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user