0001
0002 #include <inttypes.h>
0003 #include <unistd.h>
0004 #include <sys/syscall.h>
0005 #include <sys/types.h>
0006 #include <sys/mman.h>
0007 #include <pthread.h>
0008 #include <stdlib.h>
0009 #include <stdio.h>
0010 #include "debug.h"
0011 #include "event.h"
0012 #include "tests.h"
0013 #include "machine.h"
0014 #include "thread_map.h"
0015 #include "map.h"
0016 #include "symbol.h"
0017 #include "util/synthetic-events.h"
0018 #include "thread.h"
0019 #include <internal/lib.h> // page_size
0020
0021 #define THREADS 4
0022
0023 static int go_away;
0024
0025 struct thread_data {
0026 pthread_t pt;
0027 pid_t tid;
0028 void *map;
0029 int ready[2];
0030 };
0031
0032 static struct thread_data threads[THREADS];
0033
0034 static int thread_init(struct thread_data *td)
0035 {
0036 void *map;
0037
0038 map = mmap(NULL, page_size,
0039 PROT_READ|PROT_WRITE|PROT_EXEC,
0040 MAP_SHARED|MAP_ANONYMOUS, -1, 0);
0041
0042 if (map == MAP_FAILED) {
0043 perror("mmap failed");
0044 return -1;
0045 }
0046
0047 td->map = map;
0048 td->tid = syscall(SYS_gettid);
0049
0050 pr_debug("tid = %d, map = %p\n", td->tid, map);
0051 return 0;
0052 }
0053
0054 static void *thread_fn(void *arg)
0055 {
0056 struct thread_data *td = arg;
0057 ssize_t ret;
0058 int go = 0;
0059
0060 if (thread_init(td))
0061 return NULL;
0062
0063
0064 ret = write(td->ready[1], &go, sizeof(int));
0065 if (ret != sizeof(int)) {
0066 pr_err("failed to notify\n");
0067 return NULL;
0068 }
0069
0070 while (!go_away) {
0071
0072 usleep(100);
0073 }
0074
0075 munmap(td->map, page_size);
0076 return NULL;
0077 }
0078
0079 static int thread_create(int i)
0080 {
0081 struct thread_data *td = &threads[i];
0082 int err, go;
0083
0084 if (pipe(td->ready))
0085 return -1;
0086
0087 err = pthread_create(&td->pt, NULL, thread_fn, td);
0088 if (!err) {
0089
0090 ssize_t ret = read(td->ready[0], &go, sizeof(int));
0091 err = ret != sizeof(int);
0092 }
0093
0094 close(td->ready[0]);
0095 close(td->ready[1]);
0096 return err;
0097 }
0098
0099 static int threads_create(void)
0100 {
0101 struct thread_data *td0 = &threads[0];
0102 int i, err = 0;
0103
0104 go_away = 0;
0105
0106
0107 if (thread_init(td0))
0108 return -1;
0109
0110 for (i = 1; !err && i < THREADS; i++)
0111 err = thread_create(i);
0112
0113 return err;
0114 }
0115
0116 static int threads_destroy(void)
0117 {
0118 struct thread_data *td0 = &threads[0];
0119 int i, err = 0;
0120
0121
0122 munmap(td0->map, page_size);
0123
0124 go_away = 1;
0125
0126 for (i = 1; !err && i < THREADS; i++)
0127 err = pthread_join(threads[i].pt, NULL);
0128
0129 return err;
0130 }
0131
0132 typedef int (*synth_cb)(struct machine *machine);
0133
0134 static int synth_all(struct machine *machine)
0135 {
0136 return perf_event__synthesize_threads(NULL,
0137 perf_event__process,
0138 machine, 1, 0, 1);
0139 }
0140
0141 static int synth_process(struct machine *machine)
0142 {
0143 struct perf_thread_map *map;
0144 int err;
0145
0146 map = thread_map__new_by_pid(getpid());
0147
0148 err = perf_event__synthesize_thread_map(NULL, map,
0149 perf_event__process,
0150 machine, 1, 0);
0151
0152 perf_thread_map__put(map);
0153 return err;
0154 }
0155
0156 static int mmap_events(synth_cb synth)
0157 {
0158 struct machine *machine;
0159 int err, i;
0160
0161
0162
0163
0164
0165
0166
0167
0168 TEST_ASSERT_VAL("failed to create threads", !threads_create());
0169
0170 machine = machine__new_host();
0171
0172 dump_trace = verbose > 1 ? 1 : 0;
0173
0174 err = synth(machine);
0175
0176 dump_trace = 0;
0177
0178 TEST_ASSERT_VAL("failed to destroy threads", !threads_destroy());
0179 TEST_ASSERT_VAL("failed to synthesize maps", !err);
0180
0181
0182
0183
0184
0185 for (i = 0; i < THREADS; i++) {
0186 struct thread_data *td = &threads[i];
0187 struct addr_location al;
0188 struct thread *thread;
0189
0190 thread = machine__findnew_thread(machine, getpid(), td->tid);
0191
0192 pr_debug("looking for map %p\n", td->map);
0193
0194 thread__find_map(thread, PERF_RECORD_MISC_USER,
0195 (unsigned long) (td->map + 1), &al);
0196
0197 thread__put(thread);
0198
0199 if (!al.map) {
0200 pr_debug("failed, couldn't find map\n");
0201 err = -1;
0202 break;
0203 }
0204
0205 pr_debug("map %p, addr %" PRIx64 "\n", al.map, al.map->start);
0206 }
0207
0208 machine__delete_threads(machine);
0209 machine__delete(machine);
0210 return err;
0211 }
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 static int test__mmap_thread_lookup(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
0228 {
0229
0230 TEST_ASSERT_VAL("failed with sythesizing all",
0231 !mmap_events(synth_all));
0232
0233
0234 TEST_ASSERT_VAL("failed with sythesizing process",
0235 !mmap_events(synth_process));
0236
0237 return 0;
0238 }
0239
0240 DEFINE_SUITE("Lookup mmap thread", mmap_thread_lookup);