^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 <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <sys/syscall.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <sys/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <pthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "event.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "tests.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "machine.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 "map.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "symbol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "util/synthetic-events.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "thread.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <internal/lib.h> // page_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define THREADS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static int go_away;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct thread_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) pthread_t pt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) pid_t tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) void *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int ready[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static struct thread_data threads[THREADS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int thread_init(struct thread_data *td)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) void *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) map = mmap(NULL, page_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) PROT_READ|PROT_WRITE|PROT_EXEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) MAP_SHARED|MAP_ANONYMOUS, -1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (map == MAP_FAILED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) perror("mmap failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) td->map = map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) td->tid = syscall(SYS_gettid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) pr_debug("tid = %d, map = %p\n", td->tid, map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static void *thread_fn(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct thread_data *td = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int go = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (thread_init(td))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* Signal thread_create thread is initialized. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) ret = write(td->ready[1], &go, sizeof(int));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (ret != sizeof(int)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) pr_err("failed to notify\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) while (!go_away) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* Waiting for main thread to kill us. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) usleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) munmap(td->map, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static int thread_create(int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct thread_data *td = &threads[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int err, go;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (pipe(td->ready))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) err = pthread_create(&td->pt, NULL, thread_fn, td);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* Wait for thread initialization. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ssize_t ret = read(td->ready[0], &go, sizeof(int));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) err = ret != sizeof(int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) close(td->ready[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) close(td->ready[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return err;
^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) static int threads_create(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct thread_data *td0 = &threads[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int i, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) go_away = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* 0 is main thread */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (thread_init(td0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) for (i = 1; !err && i < THREADS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) err = thread_create(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static int threads_destroy(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct thread_data *td0 = &threads[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int i, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* cleanup the main thread */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) munmap(td0->map, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) go_away = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) for (i = 1; !err && i < THREADS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) err = pthread_join(threads[i].pt, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) typedef int (*synth_cb)(struct machine *machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static int synth_all(struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return perf_event__synthesize_threads(NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) perf_event__process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) machine, 0, 1);
^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 synth_process(struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct perf_thread_map *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) map = thread_map__new_by_pid(getpid());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) err = perf_event__synthesize_thread_map(NULL, map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) perf_event__process,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) machine, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) perf_thread_map__put(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static int mmap_events(synth_cb synth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct machine *machine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * The threads_create will not return before all threads
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * are spawned and all created memory map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * They will loop until threads_destroy is called, so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * can safely run synthesizing function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) TEST_ASSERT_VAL("failed to create threads", !threads_create());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) machine = machine__new_host();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) dump_trace = verbose > 1 ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) err = synth(machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) dump_trace = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) TEST_ASSERT_VAL("failed to destroy threads", !threads_destroy());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) TEST_ASSERT_VAL("failed to synthesize maps", !err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * All data is synthesized, try to find map for each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * thread object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) for (i = 0; i < THREADS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct thread_data *td = &threads[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct addr_location al;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct thread *thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) thread = machine__findnew_thread(machine, getpid(), td->tid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) pr_debug("looking for map %p\n", td->map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) thread__find_map(thread, PERF_RECORD_MISC_USER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) (unsigned long) (td->map + 1), &al);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) thread__put(thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (!al.map) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) pr_debug("failed, couldn't find map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) pr_debug("map %p, addr %" PRIx64 "\n", al.map, al.map->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) machine__delete_threads(machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) machine__delete(machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return err;
^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 'THREADS' number of threads (including
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * main thread) and each thread creates memory map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * When threads are created, we synthesize them with both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * (separate tests):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * perf_event__synthesize_thread_map (process based)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * perf_event__synthesize_threads (global)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * We test we can find all memory maps via:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * thread__find_map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * by using all thread objects.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int test__mmap_thread_lookup(struct test *test __maybe_unused, int subtest __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* perf_event__synthesize_threads synthesize */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) TEST_ASSERT_VAL("failed with sythesizing all",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) !mmap_events(synth_all));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* perf_event__synthesize_thread_map synthesize */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) TEST_ASSERT_VAL("failed with sythesizing process",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) !mmap_events(synth_process));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }