brintos

brintos / linux-shallow public Read only

0
0
Text · 5.4 KiB · e155f0e Raw
244 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <linux/compiler.h>3#include <linux/string.h>4#include <errno.h>5#include <inttypes.h>6#include <string.h>7#include <sys/wait.h>8#include <perf/cpumap.h>9#include "tests.h"10#include "evlist.h"11#include "evsel.h"12#include "debug.h"13#include "parse-events.h"14#include "thread_map.h"15#include "target.h"16 17static int attach__enable_on_exec(struct evlist *evlist)18{19	struct evsel *evsel = evlist__last(evlist);20	struct target target = {21		.uid = UINT_MAX,22	};23	const char *argv[] = { "true", NULL, };24	char sbuf[STRERR_BUFSIZE];25	int err;26 27	pr_debug("attaching to spawned child, enable on exec\n");28 29	err = evlist__create_maps(evlist, &target);30	if (err < 0) {31		pr_debug("Not enough memory to create thread/cpu maps\n");32		return err;33	}34 35	err = evlist__prepare_workload(evlist, &target, argv, false, NULL);36	if (err < 0) {37		pr_debug("Couldn't run the workload!\n");38		return err;39	}40 41	evsel->core.attr.enable_on_exec = 1;42 43	err = evlist__open(evlist);44	if (err < 0) {45		pr_debug("perf_evlist__open: %s\n",46			 str_error_r(errno, sbuf, sizeof(sbuf)));47		return err;48	}49 50	return evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL;51}52 53static int detach__enable_on_exec(struct evlist *evlist)54{55	waitpid(evlist->workload.pid, NULL, 0);56	return 0;57}58 59static int attach__current_disabled(struct evlist *evlist)60{61	struct evsel *evsel = evlist__last(evlist);62	struct perf_thread_map *threads;63	int err;64 65	pr_debug("attaching to current thread as disabled\n");66 67	threads = thread_map__new(-1, getpid(), UINT_MAX);68	if (threads == NULL) {69		pr_debug("thread_map__new\n");70		return -1;71	}72 73	evsel->core.attr.disabled = 1;74 75	err = evsel__open_per_thread(evsel, threads);76	if (err) {77		pr_debug("Failed to open event cpu-clock:u\n");78		return err;79	}80 81	perf_thread_map__put(threads);82	return evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL;83}84 85static int attach__current_enabled(struct evlist *evlist)86{87	struct evsel *evsel = evlist__last(evlist);88	struct perf_thread_map *threads;89	int err;90 91	pr_debug("attaching to current thread as enabled\n");92 93	threads = thread_map__new(-1, getpid(), UINT_MAX);94	if (threads == NULL) {95		pr_debug("failed to call thread_map__new\n");96		return -1;97	}98 99	err = evsel__open_per_thread(evsel, threads);100 101	perf_thread_map__put(threads);102	return err == 0 ? TEST_OK : TEST_FAIL;103}104 105static int detach__disable(struct evlist *evlist)106{107	struct evsel *evsel = evlist__last(evlist);108 109	return evsel__enable(evsel);110}111 112static int attach__cpu_disabled(struct evlist *evlist)113{114	struct evsel *evsel = evlist__last(evlist);115	struct perf_cpu_map *cpus;116	int err;117 118	pr_debug("attaching to CPU 0 as enabled\n");119 120	cpus = perf_cpu_map__new("0");121	if (cpus == NULL) {122		pr_debug("failed to call perf_cpu_map__new\n");123		return -1;124	}125 126	evsel->core.attr.disabled = 1;127 128	err = evsel__open_per_cpu(evsel, cpus, -1);129	if (err) {130		if (err == -EACCES)131			return TEST_SKIP;132 133		pr_debug("Failed to open event cpu-clock:u\n");134		return err;135	}136 137	perf_cpu_map__put(cpus);138	return evsel__enable(evsel);139}140 141static int attach__cpu_enabled(struct evlist *evlist)142{143	struct evsel *evsel = evlist__last(evlist);144	struct perf_cpu_map *cpus;145	int err;146 147	pr_debug("attaching to CPU 0 as enabled\n");148 149	cpus = perf_cpu_map__new("0");150	if (cpus == NULL) {151		pr_debug("failed to call perf_cpu_map__new\n");152		return -1;153	}154 155	err = evsel__open_per_cpu(evsel, cpus, -1);156	if (err == -EACCES)157		return TEST_SKIP;158 159	perf_cpu_map__put(cpus);160	return err ? TEST_FAIL : TEST_OK;161}162 163static int test_times(int (attach)(struct evlist *),164		      int (detach)(struct evlist *))165{166	struct perf_counts_values count;167	struct evlist *evlist = NULL;168	struct evsel *evsel;169	int err = -1, i;170 171	evlist = evlist__new();172	if (!evlist) {173		pr_debug("failed to create event list\n");174		goto out_err;175	}176 177	err = parse_event(evlist, "cpu-clock:u");178	if (err) {179		pr_debug("failed to parse event cpu-clock:u\n");180		goto out_err;181	}182 183	evsel = evlist__last(evlist);184	evsel->core.attr.read_format |=185		PERF_FORMAT_TOTAL_TIME_ENABLED |186		PERF_FORMAT_TOTAL_TIME_RUNNING;187 188	err = attach(evlist);189	if (err == TEST_SKIP) {190		pr_debug("  SKIP  : not enough rights\n");191		return err;192	}193 194	TEST_ASSERT_VAL("failed to attach", !err);195 196	for (i = 0; i < 100000000; i++) { }197 198	TEST_ASSERT_VAL("failed to detach", !detach(evlist));199 200	perf_evsel__read(&evsel->core, 0, 0, &count);201 202	err = !(count.ena == count.run);203 204	pr_debug("  %s: ena %" PRIu64", run %" PRIu64"\n",205		 !err ? "OK    " : "FAILED",206		 count.ena, count.run);207 208out_err:209	evlist__delete(evlist);210	return !err ? TEST_OK : TEST_FAIL;211}212 213/*214 * This test creates software event 'cpu-clock'215 * attaches it in several ways (explained below)216 * and checks that enabled and running times217 * match.218 */219static int test__event_times(struct test_suite *test __maybe_unused, int subtest __maybe_unused)220{221	int err, ret = 0;222 223#define _T(attach, detach)			\224	err = test_times(attach, detach);	\225	if (err && (ret == TEST_OK || ret == TEST_SKIP))	\226		ret = err;227 228	/* attach on newly spawned process after exec */229	_T(attach__enable_on_exec,   detach__enable_on_exec)230	/* attach on current process as enabled */231	_T(attach__current_enabled,  detach__disable)232	/* attach on current process as disabled */233	_T(attach__current_disabled, detach__disable)234	/* attach on cpu as disabled */235	_T(attach__cpu_disabled,     detach__disable)236	/* attach on cpu as enabled */237	_T(attach__cpu_enabled,      detach__disable)238 239#undef _T240	return ret;241}242 243DEFINE_SUITE("Event times", event_times);244