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