|
@@ -1089,6 +1089,14 @@ static const char * const event_type_descriptors[] = {
|
|
"Hardware breakpoint",
|
|
"Hardware breakpoint",
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static int cmp_string(const void *a, const void *b)
|
|
|
|
+{
|
|
|
|
+ const char * const *as = a;
|
|
|
|
+ const char * const *bs = b;
|
|
|
|
+
|
|
|
|
+ return strcmp(*as, *bs);
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Print the events from <debugfs_mount_point>/tracing/events
|
|
* Print the events from <debugfs_mount_point>/tracing/events
|
|
*/
|
|
*/
|
|
@@ -1100,11 +1108,21 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
|
|
struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
|
|
struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
|
|
char evt_path[MAXPATHLEN];
|
|
char evt_path[MAXPATHLEN];
|
|
char dir_path[MAXPATHLEN];
|
|
char dir_path[MAXPATHLEN];
|
|
|
|
+ char **evt_list = NULL;
|
|
|
|
+ unsigned int evt_i = 0, evt_num = 0;
|
|
|
|
+ bool evt_num_known = false;
|
|
|
|
|
|
|
|
+restart:
|
|
sys_dir = opendir(tracing_events_path);
|
|
sys_dir = opendir(tracing_events_path);
|
|
if (!sys_dir)
|
|
if (!sys_dir)
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+ if (evt_num_known) {
|
|
|
|
+ evt_list = zalloc(sizeof(char *) * evt_num);
|
|
|
|
+ if (!evt_list)
|
|
|
|
+ goto out_close_sys_dir;
|
|
|
|
+ }
|
|
|
|
+
|
|
for_each_subsystem(sys_dir, sys_dirent, sys_next) {
|
|
for_each_subsystem(sys_dir, sys_dirent, sys_next) {
|
|
if (subsys_glob != NULL &&
|
|
if (subsys_glob != NULL &&
|
|
!strglobmatch(sys_dirent.d_name, subsys_glob))
|
|
!strglobmatch(sys_dirent.d_name, subsys_glob))
|
|
@@ -1121,19 +1139,56 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
|
|
!strglobmatch(evt_dirent.d_name, event_glob))
|
|
!strglobmatch(evt_dirent.d_name, event_glob))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- if (name_only) {
|
|
|
|
- printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name);
|
|
|
|
|
|
+ if (!evt_num_known) {
|
|
|
|
+ evt_num++;
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
snprintf(evt_path, MAXPATHLEN, "%s:%s",
|
|
snprintf(evt_path, MAXPATHLEN, "%s:%s",
|
|
sys_dirent.d_name, evt_dirent.d_name);
|
|
sys_dirent.d_name, evt_dirent.d_name);
|
|
- printf(" %-50s [%s]\n", evt_path,
|
|
|
|
- event_type_descriptors[PERF_TYPE_TRACEPOINT]);
|
|
|
|
|
|
+
|
|
|
|
+ evt_list[evt_i] = strdup(evt_path);
|
|
|
|
+ if (evt_list[evt_i] == NULL)
|
|
|
|
+ goto out_close_evt_dir;
|
|
|
|
+ evt_i++;
|
|
}
|
|
}
|
|
closedir(evt_dir);
|
|
closedir(evt_dir);
|
|
}
|
|
}
|
|
closedir(sys_dir);
|
|
closedir(sys_dir);
|
|
|
|
+
|
|
|
|
+ if (!evt_num_known) {
|
|
|
|
+ evt_num_known = true;
|
|
|
|
+ goto restart;
|
|
|
|
+ }
|
|
|
|
+ qsort(evt_list, evt_num, sizeof(char *), cmp_string);
|
|
|
|
+ evt_i = 0;
|
|
|
|
+ while (evt_i < evt_num) {
|
|
|
|
+ if (name_only) {
|
|
|
|
+ printf("%s ", evt_list[evt_i++]);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ printf(" %-50s [%s]\n", evt_list[evt_i++],
|
|
|
|
+ event_type_descriptors[PERF_TYPE_TRACEPOINT]);
|
|
|
|
+ }
|
|
|
|
+ if (evt_num)
|
|
|
|
+ printf("\n");
|
|
|
|
+
|
|
|
|
+out_free:
|
|
|
|
+ evt_num = evt_i;
|
|
|
|
+ for (evt_i = 0; evt_i < evt_num; evt_i++)
|
|
|
|
+ zfree(&evt_list[evt_i]);
|
|
|
|
+ zfree(&evt_list);
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+out_close_evt_dir:
|
|
|
|
+ closedir(evt_dir);
|
|
|
|
+out_close_sys_dir:
|
|
|
|
+ closedir(sys_dir);
|
|
|
|
+
|
|
|
|
+ printf("FATAL: not enough memory to print %s\n",
|
|
|
|
+ event_type_descriptors[PERF_TYPE_TRACEPOINT]);
|
|
|
|
+ if (evt_list)
|
|
|
|
+ goto out_free;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1218,20 +1273,61 @@ static void __print_events_type(u8 type, struct event_symbol *syms,
|
|
unsigned max)
|
|
unsigned max)
|
|
{
|
|
{
|
|
char name[64];
|
|
char name[64];
|
|
- unsigned i;
|
|
|
|
|
|
+ unsigned int i, evt_i = 0, evt_num = 0;
|
|
|
|
+ char **evt_list = NULL;
|
|
|
|
+ bool evt_num_known = false;
|
|
|
|
+
|
|
|
|
+restart:
|
|
|
|
+ if (evt_num_known) {
|
|
|
|
+ evt_list = zalloc(sizeof(char *) * evt_num);
|
|
|
|
+ if (!evt_list)
|
|
|
|
+ goto out_enomem;
|
|
|
|
+ syms -= max;
|
|
|
|
+ }
|
|
|
|
|
|
for (i = 0; i < max ; i++, syms++) {
|
|
for (i = 0; i < max ; i++, syms++) {
|
|
if (!is_event_supported(type, i))
|
|
if (!is_event_supported(type, i))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
+ if (!evt_num_known) {
|
|
|
|
+ evt_num++;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (strlen(syms->alias))
|
|
if (strlen(syms->alias))
|
|
snprintf(name, sizeof(name), "%s OR %s",
|
|
snprintf(name, sizeof(name), "%s OR %s",
|
|
syms->symbol, syms->alias);
|
|
syms->symbol, syms->alias);
|
|
else
|
|
else
|
|
snprintf(name, sizeof(name), "%s", syms->symbol);
|
|
snprintf(name, sizeof(name), "%s", syms->symbol);
|
|
|
|
|
|
- printf(" %-50s [%s]\n", name, event_type_descriptors[type]);
|
|
|
|
|
|
+ evt_list[evt_i] = strdup(name);
|
|
|
|
+ if (evt_list[evt_i] == NULL)
|
|
|
|
+ goto out_enomem;
|
|
|
|
+ evt_i++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!evt_num_known) {
|
|
|
|
+ evt_num_known = true;
|
|
|
|
+ goto restart;
|
|
}
|
|
}
|
|
|
|
+ qsort(evt_list, evt_num, sizeof(char *), cmp_string);
|
|
|
|
+ evt_i = 0;
|
|
|
|
+ while (evt_i < evt_num)
|
|
|
|
+ printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
|
|
|
|
+ if (evt_num)
|
|
|
|
+ printf("\n");
|
|
|
|
+
|
|
|
|
+out_free:
|
|
|
|
+ evt_num = evt_i;
|
|
|
|
+ for (evt_i = 0; evt_i < evt_num; evt_i++)
|
|
|
|
+ zfree(&evt_list[evt_i]);
|
|
|
|
+ zfree(&evt_list);
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+out_enomem:
|
|
|
|
+ printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
|
|
|
|
+ if (evt_list)
|
|
|
|
+ goto out_free;
|
|
}
|
|
}
|
|
|
|
|
|
void print_events_type(u8 type)
|
|
void print_events_type(u8 type)
|
|
@@ -1244,8 +1340,17 @@ void print_events_type(u8 type)
|
|
|
|
|
|
int print_hwcache_events(const char *event_glob, bool name_only)
|
|
int print_hwcache_events(const char *event_glob, bool name_only)
|
|
{
|
|
{
|
|
- unsigned int type, op, i, printed = 0;
|
|
|
|
|
|
+ unsigned int type, op, i, evt_i = 0, evt_num = 0;
|
|
char name[64];
|
|
char name[64];
|
|
|
|
+ char **evt_list = NULL;
|
|
|
|
+ bool evt_num_known = false;
|
|
|
|
+
|
|
|
|
+restart:
|
|
|
|
+ if (evt_num_known) {
|
|
|
|
+ evt_list = zalloc(sizeof(char *) * evt_num);
|
|
|
|
+ if (!evt_list)
|
|
|
|
+ goto out_enomem;
|
|
|
|
+ }
|
|
|
|
|
|
for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
|
|
for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
|
|
for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
|
|
for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
|
|
@@ -1263,27 +1368,66 @@ int print_hwcache_events(const char *event_glob, bool name_only)
|
|
type | (op << 8) | (i << 16)))
|
|
type | (op << 8) | (i << 16)))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- if (name_only)
|
|
|
|
- printf("%s ", name);
|
|
|
|
- else
|
|
|
|
- printf(" %-50s [%s]\n", name,
|
|
|
|
- event_type_descriptors[PERF_TYPE_HW_CACHE]);
|
|
|
|
- ++printed;
|
|
|
|
|
|
+ if (!evt_num_known) {
|
|
|
|
+ evt_num++;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ evt_list[evt_i] = strdup(name);
|
|
|
|
+ if (evt_list[evt_i] == NULL)
|
|
|
|
+ goto out_enomem;
|
|
|
|
+ evt_i++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (printed)
|
|
|
|
|
|
+ if (!evt_num_known) {
|
|
|
|
+ evt_num_known = true;
|
|
|
|
+ goto restart;
|
|
|
|
+ }
|
|
|
|
+ qsort(evt_list, evt_num, sizeof(char *), cmp_string);
|
|
|
|
+ evt_i = 0;
|
|
|
|
+ while (evt_i < evt_num) {
|
|
|
|
+ if (name_only) {
|
|
|
|
+ printf("%s ", evt_list[evt_i++]);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ printf(" %-50s [%s]\n", evt_list[evt_i++],
|
|
|
|
+ event_type_descriptors[PERF_TYPE_HW_CACHE]);
|
|
|
|
+ }
|
|
|
|
+ if (evt_num)
|
|
printf("\n");
|
|
printf("\n");
|
|
- return printed;
|
|
|
|
|
|
+
|
|
|
|
+out_free:
|
|
|
|
+ evt_num = evt_i;
|
|
|
|
+ for (evt_i = 0; evt_i < evt_num; evt_i++)
|
|
|
|
+ zfree(&evt_list[evt_i]);
|
|
|
|
+ zfree(&evt_list);
|
|
|
|
+ return evt_num;
|
|
|
|
+
|
|
|
|
+out_enomem:
|
|
|
|
+ printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]);
|
|
|
|
+ if (evt_list)
|
|
|
|
+ goto out_free;
|
|
|
|
+ return evt_num;
|
|
}
|
|
}
|
|
|
|
|
|
static void print_symbol_events(const char *event_glob, unsigned type,
|
|
static void print_symbol_events(const char *event_glob, unsigned type,
|
|
struct event_symbol *syms, unsigned max,
|
|
struct event_symbol *syms, unsigned max,
|
|
bool name_only)
|
|
bool name_only)
|
|
{
|
|
{
|
|
- unsigned i, printed = 0;
|
|
|
|
|
|
+ unsigned int i, evt_i = 0, evt_num = 0;
|
|
char name[MAX_NAME_LEN];
|
|
char name[MAX_NAME_LEN];
|
|
|
|
+ char **evt_list = NULL;
|
|
|
|
+ bool evt_num_known = false;
|
|
|
|
+
|
|
|
|
+restart:
|
|
|
|
+ if (evt_num_known) {
|
|
|
|
+ evt_list = zalloc(sizeof(char *) * evt_num);
|
|
|
|
+ if (!evt_list)
|
|
|
|
+ goto out_enomem;
|
|
|
|
+ syms -= max;
|
|
|
|
+ }
|
|
|
|
|
|
for (i = 0; i < max; i++, syms++) {
|
|
for (i = 0; i < max; i++, syms++) {
|
|
|
|
|
|
@@ -1295,23 +1439,49 @@ static void print_symbol_events(const char *event_glob, unsigned type,
|
|
if (!is_event_supported(type, i))
|
|
if (!is_event_supported(type, i))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- if (name_only) {
|
|
|
|
- printf("%s ", syms->symbol);
|
|
|
|
|
|
+ if (!evt_num_known) {
|
|
|
|
+ evt_num++;
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
- if (strlen(syms->alias))
|
|
|
|
|
|
+ if (!name_only && strlen(syms->alias))
|
|
snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
|
|
snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
|
|
else
|
|
else
|
|
strncpy(name, syms->symbol, MAX_NAME_LEN);
|
|
strncpy(name, syms->symbol, MAX_NAME_LEN);
|
|
|
|
|
|
- printf(" %-50s [%s]\n", name, event_type_descriptors[type]);
|
|
|
|
-
|
|
|
|
- printed++;
|
|
|
|
|
|
+ evt_list[evt_i] = strdup(name);
|
|
|
|
+ if (evt_list[evt_i] == NULL)
|
|
|
|
+ goto out_enomem;
|
|
|
|
+ evt_i++;
|
|
}
|
|
}
|
|
|
|
|
|
- if (printed)
|
|
|
|
|
|
+ if (!evt_num_known) {
|
|
|
|
+ evt_num_known = true;
|
|
|
|
+ goto restart;
|
|
|
|
+ }
|
|
|
|
+ qsort(evt_list, evt_num, sizeof(char *), cmp_string);
|
|
|
|
+ evt_i = 0;
|
|
|
|
+ while (evt_i < evt_num) {
|
|
|
|
+ if (name_only) {
|
|
|
|
+ printf("%s ", evt_list[evt_i++]);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
|
|
|
|
+ }
|
|
|
|
+ if (evt_num)
|
|
printf("\n");
|
|
printf("\n");
|
|
|
|
+
|
|
|
|
+out_free:
|
|
|
|
+ evt_num = evt_i;
|
|
|
|
+ for (evt_i = 0; evt_i < evt_num; evt_i++)
|
|
|
|
+ zfree(&evt_list[evt_i]);
|
|
|
|
+ zfree(&evt_list);
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+out_enomem:
|
|
|
|
+ printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
|
|
|
|
+ if (evt_list)
|
|
|
|
+ goto out_free;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|