Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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 <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #include <stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #include <ftw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <pthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <sys/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <sys/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/time64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <internal/lib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <subcmd/parse-options.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include "bench.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "util/data.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include "util/stat.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include "util/debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include "util/event.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include "util/symbol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include "util/session.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include "util/build-id.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include "util/synthetic-events.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define MMAP_DEV_MAJOR  8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define DSO_MMAP_RATIO  4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) static unsigned int iterations = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) static unsigned int nr_mmaps   = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) static unsigned int nr_samples = 100;  /* samples per mmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static u64 bench_sample_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) static u16 bench_id_hdr_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) struct bench_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	int			pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	int			input_pipe[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	int			output_pipe[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	pthread_t		th;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) struct bench_dso {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	struct list_head	list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	char			*name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	int			ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) static int nr_dsos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) static struct bench_dso *dsos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) extern int cmd_inject(int argc, const char *argv[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) static const struct option options[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	OPT_UINTEGER('i', "iterations", &iterations,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		     "Number of iterations used to compute average (default: 100)"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	OPT_UINTEGER('m', "nr-mmaps", &nr_mmaps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		     "Number of mmap events for each iteration (default: 100)"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	OPT_UINTEGER('n', "nr-samples", &nr_samples,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		     "Number of sample events per mmap event (default: 100)"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	OPT_INCR('v', "verbose", &verbose,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		 "be more verbose (show iteration count, DSO name, etc)"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	OPT_END()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) static const char *const bench_usage[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	"perf bench internals inject-build-id <options>",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	NULL
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * Helper for collect_dso that adds the given file as a dso to dso_list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * if it contains a build-id.  Stops after collecting 4 times more than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  * we need (for MMAP2 events).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) static int add_dso(const char *fpath, const struct stat *sb __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		   int typeflag, struct FTW *ftwbuf __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	struct bench_dso *dso = &dsos[nr_dsos];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	struct build_id bid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	if (typeflag == FTW_D || typeflag == FTW_SL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	if (filename__read_build_id(fpath, &bid) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	dso->name = realpath(fpath, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	if (dso->name == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	dso->ino = nr_dsos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	pr_debug2("  Adding DSO: %s\n", fpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	/* stop if we collected enough DSOs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	if ((unsigned int)nr_dsos == DSO_MMAP_RATIO * nr_mmaps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static void collect_dso(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	dsos = calloc(nr_mmaps * DSO_MMAP_RATIO, sizeof(*dsos));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	if (dsos == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		printf("  Memory allocation failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		exit(1);
^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) 	if (nftw("/usr/lib/", add_dso, 10, FTW_PHYS) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	pr_debug("  Collected %d DSOs\n", nr_dsos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static void release_dso(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	for (i = 0; i < nr_dsos; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		struct bench_dso *dso = &dsos[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		free(dso->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	free(dsos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* Fake address used by mmap and sample events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static u64 dso_map_addr(struct bench_dso *dso)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	return 0x400000ULL + dso->ino * 8192ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static ssize_t synthesize_attr(struct bench_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	union perf_event event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	memset(&event, 0, sizeof(event.attr) + sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	event.header.type = PERF_RECORD_HEADER_ATTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	event.header.size = sizeof(event.attr) + sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	event.attr.attr.type = PERF_TYPE_SOFTWARE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	event.attr.attr.config = PERF_COUNT_SW_TASK_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	event.attr.attr.exclude_kernel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	event.attr.attr.sample_id_all = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	event.attr.attr.sample_type = bench_sample_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	return writen(data->input_pipe[1], &event, event.header.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static ssize_t synthesize_fork(struct bench_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	union perf_event event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	memset(&event, 0, sizeof(event.fork) + bench_id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	event.header.type = PERF_RECORD_FORK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	event.header.misc = PERF_RECORD_MISC_FORK_EXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	event.header.size = sizeof(event.fork) + bench_id_hdr_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	event.fork.ppid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	event.fork.ptid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	event.fork.pid = data->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	event.fork.tid = data->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	return writen(data->input_pipe[1], &event, event.header.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static ssize_t synthesize_mmap(struct bench_data *data, struct bench_dso *dso, u64 timestamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	union perf_event event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	size_t len = offsetof(struct perf_record_mmap2, filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	u64 *id_hdr_ptr = (void *)&event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	int ts_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	len += roundup(strlen(dso->name) + 1, 8) + bench_id_hdr_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	memset(&event, 0, min(len, sizeof(event.mmap2)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	event.header.type = PERF_RECORD_MMAP2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	event.header.misc = PERF_RECORD_MISC_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	event.header.size = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	event.mmap2.pid = data->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	event.mmap2.tid = data->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	event.mmap2.maj = MMAP_DEV_MAJOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	event.mmap2.ino = dso->ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	strcpy(event.mmap2.filename, dso->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	event.mmap2.start = dso_map_addr(dso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	event.mmap2.len = 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	event.mmap2.prot = PROT_EXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	if (len > sizeof(event.mmap2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		/* write mmap2 event first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		if (writen(data->input_pipe[1], &event, len - bench_id_hdr_size) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		/* zero-fill sample id header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		memset(id_hdr_ptr, 0, bench_id_hdr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		/* put timestamp in the right position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		ts_idx = (bench_id_hdr_size / sizeof(u64)) - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		id_hdr_ptr[ts_idx] = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		if (writen(data->input_pipe[1], id_hdr_ptr, bench_id_hdr_size) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		return len;
^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) 	ts_idx = (len / sizeof(u64)) - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	id_hdr_ptr[ts_idx] = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	return writen(data->input_pipe[1], &event, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static ssize_t synthesize_sample(struct bench_data *data, struct bench_dso *dso, u64 timestamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	union perf_event event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	struct perf_sample sample = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		.tid = data->pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		.pid = data->pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		.ip = dso_map_addr(dso),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		.time = timestamp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	event.header.type = PERF_RECORD_SAMPLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	event.header.misc = PERF_RECORD_MISC_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	event.header.size = perf_event__sample_event_size(&sample, bench_sample_type, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	perf_event__synthesize_sample(&event, bench_sample_type, 0, &sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	return writen(data->input_pipe[1], &event, event.header.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static ssize_t synthesize_flush(struct bench_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	struct perf_event_header header = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		.size = sizeof(header),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		.type = PERF_RECORD_FINISHED_ROUND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	return writen(data->input_pipe[1], &header, header.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static void *data_reader(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	struct bench_data *data = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	char buf[8192];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	int flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	flag = fcntl(data->output_pipe[0], F_GETFL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	fcntl(data->output_pipe[0], F_SETFL, flag | O_NONBLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	/* read out data from child */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	while (true) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		n = read(data->output_pipe[0], buf, sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		if (n > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		if (n == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		if (errno != EINTR && errno != EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		usleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	close(data->output_pipe[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static int setup_injection(struct bench_data *data, bool build_id_all)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	int ready_pipe[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	int dev_null_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	char buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	if (pipe(ready_pipe) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	if (pipe(data->input_pipe) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	if (pipe(data->output_pipe) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	data->pid = fork();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	if (data->pid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	if (data->pid == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		const char **inject_argv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		int inject_argc = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		close(data->input_pipe[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		close(data->output_pipe[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		close(ready_pipe[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		dup2(data->input_pipe[0], STDIN_FILENO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		close(data->input_pipe[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		dup2(data->output_pipe[1], STDOUT_FILENO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		close(data->output_pipe[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		dev_null_fd = open("/dev/null", O_WRONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		if (dev_null_fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 			exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		dup2(dev_null_fd, STDERR_FILENO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		if (build_id_all)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 			inject_argc++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		inject_argv = calloc(inject_argc + 1, sizeof(*inject_argv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		if (inject_argv == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 			exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		inject_argv[0] = strdup("inject");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		inject_argv[1] = strdup("-b");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		if (build_id_all)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 			inject_argv[2] = strdup("--buildid-all");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		/* signal that we're ready to go */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		close(ready_pipe[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		cmd_inject(inject_argc, inject_argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		exit(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	pthread_create(&data->th, NULL, data_reader, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	close(ready_pipe[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	close(data->input_pipe[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	close(data->output_pipe[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	/* wait for child ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	if (read(ready_pipe[0], &buf, 1) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	close(ready_pipe[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static int inject_build_id(struct bench_data *data, u64 *max_rss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	unsigned int i, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	struct rusage rusage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	/* this makes the child to run */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	if (perf_header__write_pipe(data->input_pipe[1]) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	if (synthesize_attr(data) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	if (synthesize_fork(data) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	for (i = 0; i < nr_mmaps; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		int idx = rand() % (nr_dsos - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		struct bench_dso *dso = &dsos[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		u64 timestamp = rand() % 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		pr_debug2("   [%d] injecting: %s\n", i+1, dso->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		if (synthesize_mmap(data, dso, timestamp) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 		for (k = 0; k < nr_samples; k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 			if (synthesize_sample(data, dso, timestamp + k * 1000) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		if ((i + 1) % 10 == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 			if (synthesize_flush(data) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	/* tihs makes the child to finish */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	close(data->input_pipe[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	wait4(data->pid, &status, 0, &rusage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	*max_rss = rusage.ru_maxrss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	pr_debug("   Child %d exited with %d\n", data->pid, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static void do_inject_loop(struct bench_data *data, bool build_id_all)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	struct stats time_stats, mem_stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	double time_average, time_stddev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	double mem_average, mem_stddev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	init_stats(&time_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	init_stats(&mem_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	pr_debug("  Build-id%s injection benchmark\n", build_id_all ? "-all" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	for (i = 0; i < iterations; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		struct timeval start, end, diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		u64 runtime_us, max_rss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		pr_debug("  Iteration #%d\n", i+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		if (setup_injection(data, build_id_all) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 			printf("  Build-id injection setup failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		gettimeofday(&start, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		if (inject_build_id(data, &max_rss) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 			printf("  Build-id injection failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 		gettimeofday(&end, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 		timersub(&end, &start, &diff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		update_stats(&time_stats, runtime_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		update_stats(&mem_stats, max_rss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		pthread_join(data->th, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	time_average = avg_stats(&time_stats) / USEC_PER_MSEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	time_stddev = stddev_stats(&time_stats) / USEC_PER_MSEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	printf("  Average build-id%s injection took: %.3f msec (+- %.3f msec)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	       build_id_all ? "-all" : "", time_average, time_stddev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	/* each iteration, it processes MMAP2 + BUILD_ID + nr_samples * SAMPLE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	time_average = avg_stats(&time_stats) / (nr_mmaps * (nr_samples + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	time_stddev = stddev_stats(&time_stats) / (nr_mmaps * (nr_samples + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	printf("  Average time per event: %.3f usec (+- %.3f usec)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		time_average, time_stddev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	mem_average = avg_stats(&mem_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	mem_stddev = stddev_stats(&mem_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	printf("  Average memory usage: %.0f KB (+- %.0f KB)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 		mem_average, mem_stddev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static int do_inject_loops(struct bench_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	srand(time(NULL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	symbol__init(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	bench_sample_type  = PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_IP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	bench_sample_type |= PERF_SAMPLE_TID | PERF_SAMPLE_TIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	bench_id_hdr_size  = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	collect_dso();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	if (nr_dsos == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		printf("  Cannot collect DSOs for injection\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	do_inject_loop(data, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	do_inject_loop(data, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	release_dso();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) int bench_inject_build_id(int argc, const char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	struct bench_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	argc = parse_options(argc, argv, options, bench_usage, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	if (argc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		usage_with_options(bench_usage, options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	return do_inject_loops(&data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)