/* Cleanup test PMU directory. */ staticint test_pmu_put(constchar *dir, struct perf_pmu *pmu)
{ char buf[PATH_MAX + 20]; int ret;
if (scnprintf(buf, sizeof(buf), "rm -fr %s", dir) < 0) {
pr_err("Failure to set up buffer for \"%s\"\n", dir); return -EINVAL;
}
ret = system(buf); if (ret)
pr_err("Failure to \"%s\"\n", buf);
/* Create equivalent of sysfs mount point. */
scnprintf(dir, sz, "/tmp/perf-pmu-test-XXXXXX"); if (!mkdtemp(dir)) {
pr_err("mkdtemp failed\n");
dir[0] = '\0'; return NULL;
}
dirfd = open(dir, O_DIRECTORY); if (dirfd < 0) {
pr_err("Failed to open test directory \"%s\"\n", dir); goto err_out;
}
/* Create the test PMU directory and give it a perf_event_attr type number. */ if (mkdirat(dirfd, "perf-pmu-test", 0755) < 0) {
pr_err("Failed to mkdir PMU directory\n"); goto err_out;
}
file = openat(dirfd, "perf-pmu-test/type", O_WRONLY | O_CREAT, 0600); if (!file) {
pr_err("Failed to open for writing file \"type\"\n"); goto err_out;
}
len = strlen("9999"); if (write(file, "9999\n", len) < len) {
close(file);
pr_err("Failed to write to 'type' file\n"); goto err_out;
}
close(file);
/* Create format directory and files. */ if (mkdirat(dirfd, "perf-pmu-test/format", 0755) < 0) {
pr_err("Failed to mkdir PMU format directory\n)"); goto err_out;
} for (size_t i = 0; i < ARRAY_SIZE(test_formats); i++) { conststruct test_format *format = &test_formats[i];
if (scnprintf(name, PATH_MAX, "perf-pmu-test/format/%s", format->name) < 0) {
pr_err("Failure to set up path for \"%s\"\n", format->name); goto err_out;
}
file = openat(dirfd, name, O_WRONLY | O_CREAT, 0600); if (!file) {
pr_err("Failed to open for writing file \"%s\"\n", name); goto err_out;
}
if (write(file, format->value, strlen(format->value)) < 0) {
pr_err("Failed to write to file \"%s\"\n", name);
close(file); goto err_out;
}
close(file);
}
/* Create test event. */ if (mkdirat(dirfd, "perf-pmu-test/events", 0755) < 0) {
pr_err("Failed to mkdir PMU events directory\n"); goto err_out;
}
file = openat(dirfd, "perf-pmu-test/events/test-event", O_WRONLY | O_CREAT, 0600); if (!file) {
pr_err("Failed to open for writing file \"type\"\n"); goto err_out;
}
len = strlen(test_event); if (write(file, test_event, len) < len) {
close(file);
pr_err("Failed to write to 'test-event' file\n"); goto err_out;
}
close(file);
/* Make the PMU reading the files created above. */
pmu = perf_pmus__add_test_pmu(dirfd, "perf-pmu-test"); if (!pmu)
pr_err("Test PMU creation failed\n");
err_out: if (!pmu)
test_pmu_put(dir, pmu); if (dirfd >= 0)
close(dirfd); return pmu;
}
staticint test__pmu_format(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{ char dir[PATH_MAX]; struct perf_event_attr attr; struct parse_events_terms terms; int ret = TEST_FAIL; struct perf_pmu *pmu = test_pmu_get(dir, sizeof(dir));
for (size_t i = 0; i < strlen(name); i++) { char c = name[i];
if (islower(c)) { if (has_upper) goto check_legacy;
has_lower = true; continue;
} if (isupper(c)) { if (has_lower) goto check_legacy;
has_upper = true; continue;
} if (!isdigit(c) && c != '.' && c != '_' && c != '-') goto check_legacy;
} returntrue;
check_legacy: /* * If the event name matches a legacy cache name the legacy encoding * will still be used. This isn't quite WAI as sysfs events should take * priority, but this case happens on PowerPC and matches the behavior * in older perf tools where legacy events were the priority. Be * permissive and assume later PMU drivers will use all lower or upper * case names.
*/ if (parse_events__decode_legacy_cache(name, /*extended_pmu_type=*/0, &config) == 0) {
pr_warning("sysfs event '%s' should be all lower/upper case, it will be matched using legacy encoding.",
name); returntrue;
} returnfalse;
}
staticint test__pmu_event_names(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{ char path[PATH_MAX];
DIR *pmu_dir, *event_dir; struct dirent *pmu_dent, *event_dent; constchar *sysfs = sysfs__mountpoint(); int ret = TEST_OK;
if (!sysfs) {
pr_err("Sysfs not mounted\n"); return TEST_FAIL;
}
snprintf(path, sizeof(path), "%s/bus/event_source/devices/", sysfs);
pmu_dir = opendir(path); if (!pmu_dir) {
pr_err("Error opening \"%s\"\n", path); return TEST_FAIL;
} while ((pmu_dent = readdir(pmu_dir))) { if (!strcmp(pmu_dent->d_name, ".") ||
!strcmp(pmu_dent->d_name, "..")) continue;
/** * Test perf_pmu__wildcard_match() that's used to search for a PMU given a name passed * on the command line. The name that's passed may also be a filename type glob * match. If the name does not match, perf_pmu__wildcard_match() attempts to match the * alias of the PMU, if provided.
*/ staticint test__pmu_match(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{ struct perf_pmu test_pmu = {
.name = "pmuname",
};
/* * 2 hex chars or less are not considered suffixes so it shouldn't be * possible to wildcard by skipping the suffix. Therefore there are more * false results here than above.
*/
test_pmu.name = "pmuname_a3";
TEST_PMU_MATCH("Diff suffix 2 hex_", "pmuname_2", false); /* * This one should be false, but because pmuname_a3 ends in 3 which is * decimal, it's not possible to determine if it's a short hex suffix or * a normal decimal suffix following text. And we want to match on any * length of decimal suffix. Run the test anyway and expect the wrong * result. And slightly fuzzy matching shouldn't do too much harm.
*/
TEST_PMU_MATCH("Sub suffix 2 hex_", "pmuname_a", true);
TEST_PMU_MATCH("Same suffix 2 hex_", "pmuname_a3", true);
TEST_PMU_MATCH("No suffix 2 hex_", "pmuname", false);
TEST_PMU_MATCH("Underscore 2 hex_", "pmuname_", false);
TEST_PMU_MATCH("Substring 2 hex_", "pmuna", false);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.