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 <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) }