Skip to content

Commit b30d7a7

Browse files
committed
Merge tag 'perf-tools-for-v6.5-1-2023-06-28' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next
Pull perf tools updates from Namhyung Kim: "Internal cleanup: - Refactor PMU data management to handle hybrid systems in a generic way. Do more work in the lexer so that legacy event types parse more easily. A side-effect of this is that if a PMU is specified, scanning sysfs is avoided improving start-up time. - Fix hybrid metrics, for example, the TopdownL1 works for both performance and efficiency cores on Intel machines. To support this, sort and regroup events after parsing. - Add reference count checking for the 'thread' data structure. - Lots of fixes for memory leaks in various places thanks to the ASAN and Ian's refcount checker. - Reduce the binary size by replacing static variables with local or dynamically allocated memory. - Introduce shared_mutex for annotate data to reduce memory footprint. - Make filesystem access library functions more thread safe. Test: - Organize cpu_map tests into a single suite. - Add metric value validation test to check if the values are within correct value ranges. - Add perf stat stdio output test to check if event and metric names match. - Add perf data converter JSON output test. - Fix a lot of issues reported by shellcheck(1). This is a preparation to enable shellcheck by default. - Make the large x86 new instructions test optional at build time using EXTRA_TESTS=1. - Add a test for libpfm4 events. perf script: - Add 'dsoff' outpuf field to display offset from the DSO. $ perf script -F comm,pid,event,ip,dsoff ls 2695501 cycles: 152cc73ef4b5 (/usr/lib/x86_64-linux-gnu/ld-2.31.so+0x1c4b5) ls 2695501 cycles: ffffffff99045b3e ([kernel.kallsyms]) ls 2695501 cycles: ffffffff9968e107 ([kernel.kallsyms]) ls 2695501 cycles: ffffffffc1f54afb ([kernel.kallsyms]) ls 2695501 cycles: ffffffff9968382f ([kernel.kallsyms]) ls 2695501 cycles: ffffffff99e00094 ([kernel.kallsyms]) ls 2695501 cycles: 152cc718a8d0 (/usr/lib/x86_64-linux-gnu/libselinux.so.1+0x68d0) ls 2695501 cycles: ffffffff992a6db0 ([kernel.kallsyms]) - Adjust width for large PID/TID values. perf report: - Robustify reading addr2line output for srcline by checking sentinel output before the actual data and by using timeout of 1 second. - Allow config terms (like 'name=ABC') with breakpoint events. $ perf record -e mem:0x55feb98dd169:x/name=breakpoint/ -p 19646 -- sleep 1 perf annotate: - Handle x86 instruction suffix like 'l' in 'movl' generally. - Parse instruction operands properly even with a whitespace. This is needed for llvm-objdump output. - Support RISC-V binutils lookup using the triplet prefixes. - Add '<' and '>' key to navigate to prev/next symbols in TUI. - Fix instruction association and parsing for LoongArch. perf stat: - Add --per-cache aggregation option, optionally specify a cache level like `--per-cache=L2`. $ sudo perf stat --per-cache -a -e ls_dmnd_fills_from_sys.ext_cache_remote --\ taskset -c 0-15,64-79,128-143,192-207\ perf bench sched messaging -p -t -l 100000 -g 8 # Running 'sched/messaging' benchmark: # 20 sender and receiver threads per group # 8 groups == 320 threads run Total time: 7.648 [sec] Performance counter stats for 'system wide': S0-D0-L3-ID0 16 17,145,912 ls_dmnd_fills_from_sys.ext_cache_remote S0-D0-L3-ID8 16 14,977,628 ls_dmnd_fills_from_sys.ext_cache_remote S0-D0-L3-ID16 16 262,539 ls_dmnd_fills_from_sys.ext_cache_remote S0-D0-L3-ID24 16 3,140 ls_dmnd_fills_from_sys.ext_cache_remote S0-D0-L3-ID32 16 27,403 ls_dmnd_fills_from_sys.ext_cache_remote S0-D0-L3-ID40 16 17,026 ls_dmnd_fills_from_sys.ext_cache_remote S0-D0-L3-ID48 16 7,292 ls_dmnd_fills_from_sys.ext_cache_remote S0-D0-L3-ID56 16 2,464 ls_dmnd_fills_from_sys.ext_cache_remote S1-D1-L3-ID64 16 22,489,306 ls_dmnd_fills_from_sys.ext_cache_remote S1-D1-L3-ID72 16 21,455,257 ls_dmnd_fills_from_sys.ext_cache_remote S1-D1-L3-ID80 16 11,619 ls_dmnd_fills_from_sys.ext_cache_remote S1-D1-L3-ID88 16 30,978 ls_dmnd_fills_from_sys.ext_cache_remote S1-D1-L3-ID96 16 37,628 ls_dmnd_fills_from_sys.ext_cache_remote S1-D1-L3-ID104 16 13,594 ls_dmnd_fills_from_sys.ext_cache_remote S1-D1-L3-ID112 16 10,164 ls_dmnd_fills_from_sys.ext_cache_remote S1-D1-L3-ID120 16 11,259 ls_dmnd_fills_from_sys.ext_cache_remote 7.779171484 seconds time elapsed - Change default (no event/metric) formatting for default metrics so that events are hidden and the metric and group appear. Performance counter stats for 'ls /': 1.85 msec task-clock # 0.594 CPUs utilized 0 context-switches # 0.000 /sec 0 cpu-migrations # 0.000 /sec 97 page-faults # 52.517 K/sec 2,187,173 cycles # 1.184 GHz 2,474,459 instructions # 1.13 insn per cycle 531,584 branches # 287.805 M/sec 13,626 branch-misses # 2.56% of all branches TopdownL1 # 23.5 % tma_backend_bound # 11.5 % tma_bad_speculation # 39.1 % tma_frontend_bound # 25.9 % tma_retiring - Allow --cputype option to have any PMU name (not just hybrid). - Fix output value not to added when it runs multiple times with -r option. perf list: - Show metricgroup description from JSON file called metricgroups.json. - Allow 'pfm' argument to list only libpfm4 events and check each event is supported before showing it. JSON vendor events: - Avoid event grouping using "NO_GROUP_EVENTS" constraints. The topdown events are correctly grouped even if no group exists. - Add "Default" metric group to print it in the default output. And use "DefaultMetricgroupName" to indicate the real metric group name. - Add AmpereOne core PMU events. Misc: - Define man page date correctly. - Track exception level properly on ARM CoreSight ETM. - Allow anonymous struct, union or enum when retrieving type names from DWARF. - Fix incorrect filename when calling `perf inject --jit`. - Handle PLT size correctly on LoongArch" * tag 'perf-tools-for-v6.5-1-2023-06-28' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next: (269 commits) perf test: Skip metrics w/o event name in stat STD output linter perf test: Reorder event name checks in stat STD output linter perf pmu: Remove a hard coded cpu PMU assumption perf pmus: Add notion of default PMU for JSON events perf unwind: Fix map reference counts perf test: Set PERF_EXEC_PATH for script execution perf script: Initialize buffer for regs_map() perf tests: Fix test_arm_callgraph_fp variable expansion perf symbol: Add LoongArch case in get_plt_sizes() perf test: Remove x permission from lib/stat_output.sh perf test: Rerun failed metrics with longer workload perf test: Add skip list for metrics known would fail perf test: Add metric value validation test perf jit: Fix incorrect file name in DWARF line table perf annotate: Fix instruction association and parsing for LoongArch perf annotation: Switch lock from a mutex to a sharded_mutex perf sharded_mutex: Introduce sharded_mutex tools: Fix incorrect calculation of object size by sizeof perf subcmd: Fix missing check for return value of malloc() in add_cmdname() perf parse-events: Remove unneeded semicolon ...
2 parents d2a6fd4 + 4d60e83 commit b30d7a7

File tree

324 files changed

+20334
-11817
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

324 files changed

+20334
-11817
lines changed

tools/lib/api/fs/cgroup.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ struct cgroupfs_cache_entry {
1414
};
1515

1616
/* just cache last used one */
17-
static struct cgroupfs_cache_entry cached;
17+
static struct cgroupfs_cache_entry *cached;
1818

1919
int cgroupfs_find_mountpoint(char *buf, size_t maxlen, const char *subsys)
2020
{
@@ -24,9 +24,9 @@ int cgroupfs_find_mountpoint(char *buf, size_t maxlen, const char *subsys)
2424
char *p, *path;
2525
char mountpoint[PATH_MAX];
2626

27-
if (!strcmp(cached.subsys, subsys)) {
28-
if (strlen(cached.mountpoint) < maxlen) {
29-
strcpy(buf, cached.mountpoint);
27+
if (cached && !strcmp(cached->subsys, subsys)) {
28+
if (strlen(cached->mountpoint) < maxlen) {
29+
strcpy(buf, cached->mountpoint);
3030
return 0;
3131
}
3232
return -1;
@@ -91,8 +91,13 @@ int cgroupfs_find_mountpoint(char *buf, size_t maxlen, const char *subsys)
9191
free(line);
9292
fclose(fp);
9393

94-
strncpy(cached.subsys, subsys, sizeof(cached.subsys) - 1);
95-
strcpy(cached.mountpoint, mountpoint);
94+
if (!cached)
95+
cached = calloc(1, sizeof(*cached));
96+
97+
if (cached) {
98+
strncpy(cached->subsys, subsys, sizeof(cached->subsys) - 1);
99+
strcpy(cached->mountpoint, mountpoint);
100+
}
96101

97102
if (mountpoint[0] && strlen(mountpoint) < maxlen) {
98103
strcpy(buf, mountpoint);

tools/lib/api/fs/fs.c

Lines changed: 99 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// SPDX-License-Identifier: GPL-2.0
2+
#include <assert.h>
23
#include <ctype.h>
34
#include <errno.h>
45
#include <limits.h>
@@ -10,6 +11,7 @@
1011
#include <sys/types.h>
1112
#include <sys/stat.h>
1213
#include <fcntl.h>
14+
#include <pthread.h>
1315
#include <unistd.h>
1416
#include <sys/mount.h>
1517

@@ -43,7 +45,7 @@
4345
#define BPF_FS_MAGIC 0xcafe4a11
4446
#endif
4547

46-
static const char * const sysfs__fs_known_mountpoints[] = {
48+
static const char * const sysfs__known_mountpoints[] = {
4749
"/sys",
4850
0,
4951
};
@@ -86,87 +88,89 @@ static const char * const bpf_fs__known_mountpoints[] = {
8688
};
8789

8890
struct fs {
89-
const char *name;
90-
const char * const *mounts;
91-
char path[PATH_MAX];
92-
bool found;
93-
bool checked;
94-
long magic;
95-
};
96-
97-
enum {
98-
FS__SYSFS = 0,
99-
FS__PROCFS = 1,
100-
FS__DEBUGFS = 2,
101-
FS__TRACEFS = 3,
102-
FS__HUGETLBFS = 4,
103-
FS__BPF_FS = 5,
91+
const char * const name;
92+
const char * const * const mounts;
93+
char *path;
94+
pthread_mutex_t mount_mutex;
95+
const long magic;
10496
};
10597

10698
#ifndef TRACEFS_MAGIC
10799
#define TRACEFS_MAGIC 0x74726163
108100
#endif
109101

110-
static struct fs fs__entries[] = {
111-
[FS__SYSFS] = {
112-
.name = "sysfs",
113-
.mounts = sysfs__fs_known_mountpoints,
114-
.magic = SYSFS_MAGIC,
115-
.checked = false,
116-
},
117-
[FS__PROCFS] = {
118-
.name = "proc",
119-
.mounts = procfs__known_mountpoints,
120-
.magic = PROC_SUPER_MAGIC,
121-
.checked = false,
122-
},
123-
[FS__DEBUGFS] = {
124-
.name = "debugfs",
125-
.mounts = debugfs__known_mountpoints,
126-
.magic = DEBUGFS_MAGIC,
127-
.checked = false,
128-
},
129-
[FS__TRACEFS] = {
130-
.name = "tracefs",
131-
.mounts = tracefs__known_mountpoints,
132-
.magic = TRACEFS_MAGIC,
133-
.checked = false,
134-
},
135-
[FS__HUGETLBFS] = {
136-
.name = "hugetlbfs",
137-
.mounts = hugetlbfs__known_mountpoints,
138-
.magic = HUGETLBFS_MAGIC,
139-
.checked = false,
140-
},
141-
[FS__BPF_FS] = {
142-
.name = "bpf",
143-
.mounts = bpf_fs__known_mountpoints,
144-
.magic = BPF_FS_MAGIC,
145-
.checked = false,
146-
},
147-
};
102+
static void fs__init_once(struct fs *fs);
103+
static const char *fs__mountpoint(const struct fs *fs);
104+
static const char *fs__mount(struct fs *fs);
105+
106+
#define FS(lower_name, fs_name, upper_name) \
107+
static struct fs fs__##lower_name = { \
108+
.name = #fs_name, \
109+
.mounts = lower_name##__known_mountpoints, \
110+
.magic = upper_name##_MAGIC, \
111+
.mount_mutex = PTHREAD_MUTEX_INITIALIZER, \
112+
}; \
113+
\
114+
static void lower_name##_init_once(void) \
115+
{ \
116+
struct fs *fs = &fs__##lower_name; \
117+
\
118+
fs__init_once(fs); \
119+
} \
120+
\
121+
const char *lower_name##__mountpoint(void) \
122+
{ \
123+
static pthread_once_t init_once = PTHREAD_ONCE_INIT; \
124+
struct fs *fs = &fs__##lower_name; \
125+
\
126+
pthread_once(&init_once, lower_name##_init_once); \
127+
return fs__mountpoint(fs); \
128+
} \
129+
\
130+
const char *lower_name##__mount(void) \
131+
{ \
132+
const char *mountpoint = lower_name##__mountpoint(); \
133+
struct fs *fs = &fs__##lower_name; \
134+
\
135+
if (mountpoint) \
136+
return mountpoint; \
137+
\
138+
return fs__mount(fs); \
139+
} \
140+
\
141+
bool lower_name##__configured(void) \
142+
{ \
143+
return lower_name##__mountpoint() != NULL; \
144+
}
145+
146+
FS(sysfs, sysfs, SYSFS);
147+
FS(procfs, procfs, PROC_SUPER);
148+
FS(debugfs, debugfs, DEBUGFS);
149+
FS(tracefs, tracefs, TRACEFS);
150+
FS(hugetlbfs, hugetlbfs, HUGETLBFS);
151+
FS(bpf_fs, bpf, BPF_FS);
148152

149153
static bool fs__read_mounts(struct fs *fs)
150154
{
151-
bool found = false;
152155
char type[100];
153156
FILE *fp;
157+
char path[PATH_MAX + 1];
154158

155159
fp = fopen("/proc/mounts", "r");
156160
if (fp == NULL)
157-
return NULL;
161+
return false;
158162

159-
while (!found &&
160-
fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
161-
fs->path, type) == 2) {
163+
while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
164+
path, type) == 2) {
162165

163-
if (strcmp(type, fs->name) == 0)
164-
found = true;
166+
if (strcmp(type, fs->name) == 0) {
167+
fs->path = strdup(path);
168+
fclose(fp);
169+
return fs->path != NULL;
170+
}
165171
}
166-
167172
fclose(fp);
168-
fs->checked = true;
169-
return fs->found = found;
173+
return false;
170174
}
171175

172176
static int fs__valid_mount(const char *fs, long magic)
@@ -188,8 +192,9 @@ static bool fs__check_mounts(struct fs *fs)
188192
ptr = fs->mounts;
189193
while (*ptr) {
190194
if (fs__valid_mount(*ptr, fs->magic) == 0) {
191-
fs->found = true;
192-
strcpy(fs->path, *ptr);
195+
fs->path = strdup(*ptr);
196+
if (!fs->path)
197+
return false;
193198
return true;
194199
}
195200
ptr++;
@@ -227,43 +232,26 @@ static bool fs__env_override(struct fs *fs)
227232
if (!override_path)
228233
return false;
229234

230-
fs->found = true;
231-
fs->checked = true;
232-
strncpy(fs->path, override_path, sizeof(fs->path) - 1);
233-
fs->path[sizeof(fs->path) - 1] = '\0';
235+
fs->path = strdup(override_path);
236+
if (!fs->path)
237+
return false;
234238
return true;
235239
}
236240

237-
static const char *fs__get_mountpoint(struct fs *fs)
241+
static void fs__init_once(struct fs *fs)
238242
{
239-
if (fs__env_override(fs))
240-
return fs->path;
241-
242-
if (fs__check_mounts(fs))
243-
return fs->path;
244-
245-
if (fs__read_mounts(fs))
246-
return fs->path;
247-
248-
return NULL;
243+
if (!fs__env_override(fs) &&
244+
!fs__check_mounts(fs) &&
245+
!fs__read_mounts(fs)) {
246+
assert(!fs->path);
247+
} else {
248+
assert(fs->path);
249+
}
249250
}
250251

251-
static const char *fs__mountpoint(int idx)
252+
static const char *fs__mountpoint(const struct fs *fs)
252253
{
253-
struct fs *fs = &fs__entries[idx];
254-
255-
if (fs->found)
256-
return (const char *)fs->path;
257-
258-
/* the mount point was already checked for the mount point
259-
* but and did not exist, so return NULL to avoid scanning again.
260-
* This makes the found and not found paths cost equivalent
261-
* in case of multiple calls.
262-
*/
263-
if (fs->checked)
264-
return NULL;
265-
266-
return fs__get_mountpoint(fs);
254+
return fs->path;
267255
}
268256

269257
static const char *mount_overload(struct fs *fs)
@@ -278,45 +266,29 @@ static const char *mount_overload(struct fs *fs)
278266
return getenv(upper_name) ?: *fs->mounts;
279267
}
280268

281-
static const char *fs__mount(int idx)
269+
static const char *fs__mount(struct fs *fs)
282270
{
283-
struct fs *fs = &fs__entries[idx];
284271
const char *mountpoint;
285272

286-
if (fs__mountpoint(idx))
287-
return (const char *)fs->path;
273+
pthread_mutex_lock(&fs->mount_mutex);
288274

289-
mountpoint = mount_overload(fs);
275+
/* Check if path found inside the mutex to avoid races with other callers of mount. */
276+
mountpoint = fs__mountpoint(fs);
277+
if (mountpoint)
278+
goto out;
290279

291-
if (mount(NULL, mountpoint, fs->name, 0, NULL) < 0)
292-
return NULL;
293-
294-
return fs__check_mounts(fs) ? fs->path : NULL;
295-
}
280+
mountpoint = mount_overload(fs);
296281

297-
#define FS(name, idx) \
298-
const char *name##__mountpoint(void) \
299-
{ \
300-
return fs__mountpoint(idx); \
301-
} \
302-
\
303-
const char *name##__mount(void) \
304-
{ \
305-
return fs__mount(idx); \
306-
} \
307-
\
308-
bool name##__configured(void) \
309-
{ \
310-
return name##__mountpoint() != NULL; \
282+
if (mount(NULL, mountpoint, fs->name, 0, NULL) == 0 &&
283+
fs__valid_mount(mountpoint, fs->magic) == 0) {
284+
fs->path = strdup(mountpoint);
285+
mountpoint = fs->path;
286+
}
287+
out:
288+
pthread_mutex_unlock(&fs->mount_mutex);
289+
return mountpoint;
311290
}
312291

313-
FS(sysfs, FS__SYSFS);
314-
FS(procfs, FS__PROCFS);
315-
FS(debugfs, FS__DEBUGFS);
316-
FS(tracefs, FS__TRACEFS);
317-
FS(hugetlbfs, FS__HUGETLBFS);
318-
FS(bpf_fs, FS__BPF_FS);
319-
320292
int filename__read_int(const char *filename, int *value)
321293
{
322294
char line[64];

tools/lib/api/fs/tracing_path.c

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,12 @@
1313

1414
#include "tracing_path.h"
1515

16-
static char tracing_mnt[PATH_MAX] = "/sys/kernel/debug";
1716
static char tracing_path[PATH_MAX] = "/sys/kernel/tracing";
18-
static char tracing_events_path[PATH_MAX] = "/sys/kernel/tracing/events";
1917

2018
static void __tracing_path_set(const char *tracing, const char *mountpoint)
2119
{
22-
snprintf(tracing_mnt, sizeof(tracing_mnt), "%s", mountpoint);
2320
snprintf(tracing_path, sizeof(tracing_path), "%s/%s",
2421
mountpoint, tracing);
25-
snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
26-
mountpoint, tracing, "events");
2722
}
2823

2924
static const char *tracing_path_tracefs_mount(void)
@@ -149,15 +144,15 @@ int tracing_path__strerror_open_tp(int err, char *buf, size_t size,
149144
/* sdt markers */
150145
if (!strncmp(filename, "sdt_", 4)) {
151146
snprintf(buf, size,
152-
"Error:\tFile %s/%s not found.\n"
147+
"Error:\tFile %s/events/%s not found.\n"
153148
"Hint:\tSDT event cannot be directly recorded on.\n"
154149
"\tPlease first use 'perf probe %s:%s' before recording it.\n",
155-
tracing_events_path, filename, sys, name);
150+
tracing_path, filename, sys, name);
156151
} else {
157152
snprintf(buf, size,
158-
"Error:\tFile %s/%s not found.\n"
153+
"Error:\tFile %s/events/%s not found.\n"
159154
"Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
160-
tracing_events_path, filename);
155+
tracing_path, filename);
161156
}
162157
break;
163158
}
@@ -169,9 +164,9 @@ int tracing_path__strerror_open_tp(int err, char *buf, size_t size,
169164
break;
170165
case EACCES: {
171166
snprintf(buf, size,
172-
"Error:\tNo permissions to read %s/%s\n"
167+
"Error:\tNo permissions to read %s/events/%s\n"
173168
"Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
174-
tracing_events_path, filename, tracing_path_mount());
169+
tracing_path, filename, tracing_path_mount());
175170
}
176171
break;
177172
default:

0 commit comments

Comments
 (0)