| @@ -166,11 +166,11 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) · 165 unmodified lines |
| 166 | return NULL; | 166 | return NULL; |
| 167 | } | 167 | } |
| 168 | | 168 | |
| 169 | union perf_event *perf_evlist__read_on_cpu(struct perf_evlist *evlist, int cpu) | 169 | union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) |
| 170 | { | 170 | { |
| 171 | /* XXX Move this to perf.c, making it generally available */ | 171 | /* XXX Move this to perf.c, making it generally available */ |
| 172 | unsigned int page_size = sysconf(_SC_PAGE_SIZE); | 172 | unsigned int page_size = sysconf(_SC_PAGE_SIZE); |
| 173 | struct perf_mmap *md = &evlist->mmap[cpu]; | 173 | struct perf_mmap *md = &evlist->mmap[idx]; |
| 174 | unsigned int head = perf_mmap__read_head(md); | 174 | unsigned int head = perf_mmap__read_head(md); |
| 175 | unsigned int old = md->prev; | 175 | unsigned int old = md->prev; |
| 176 | unsigned char *data = md->base + page_size; | 176 | unsigned char *data = md->base + page_size; |
| @@ -235,31 +235,37 @@ union perf_event *perf_evlist__read_on_cpu(struct perf_evlist *evlist, int cpu) · 58 unmodified lines |
| 235 | | 235 | |
| 236 | void perf_evlist__munmap(struct perf_evlist *evlist) | 236 | void perf_evlist__munmap(struct perf_evlist *evlist) |
| 237 | { | 237 | { |
| 238 | int cpu; | 238 | int i; |
| 239 | | 239 | |
| 240 | for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { | 240 | for (i = 0; i < evlist->nr_mmaps; i++) { |
| 241 | if (evlist->mmap[cpu].base != NULL) { | 241 | if (evlist->mmap[i].base != NULL) { |
| 242 | munmap(evlist->mmap[cpu].base, evlist->mmap_len); | 242 | munmap(evlist->mmap[i].base, evlist->mmap_len); |
| 243 | evlist->mmap[cpu].base = NULL; | 243 | evlist->mmap[i].base = NULL; |
| 244 | } | 244 | } |
| 245 | } | 245 | } |
| | 246 | |
| | 247 | free(evlist->mmap); |
| | 248 | evlist->mmap = NULL; |
| 246 | } | 249 | } |
| 247 | | 250 | |
| 248 | int perf_evlist__alloc_mmap(struct perf_evlist *evlist) | 251 | int perf_evlist__alloc_mmap(struct perf_evlist *evlist) |
| 249 | { | 252 | { |
| 250 | evlist->mmap = zalloc(evlist->cpus->nr * sizeof(struct perf_mmap)); | 253 | evlist->nr_mmaps = evlist->cpus->nr; |
| | 254 | if (evlist->cpus->map[0] == -1) |
| | 255 | evlist->nr_mmaps = evlist->threads->nr; |
| | 256 | evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); |
| 251 | return evlist->mmap != NULL ? 0 : -ENOMEM; | 257 | return evlist->mmap != NULL ? 0 : -ENOMEM; |
| 252 | } | 258 | } |
| 253 | | 259 | |
| 254 | static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel, | 260 | static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel, |
| 255 | int cpu, int prot, int mask, int fd) | 261 | int idx, int prot, int mask, int fd) |
| 256 | { | 262 | { |
| 257 | evlist->mmap[cpu].prev = 0; | 263 | evlist->mmap[idx].prev = 0; |
| 258 | evlist->mmap[cpu].mask = mask; | 264 | evlist->mmap[idx].mask = mask; |
| 259 | evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot, | 265 | evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, |
| 260 | MAP_SHARED, fd, 0); | 266 | MAP_SHARED, fd, 0); |
| 261 | if (evlist->mmap[cpu].base == MAP_FAILED) { | 267 | if (evlist->mmap[idx].base == MAP_FAILED) { |
| 262 | if (evlist->cpus->map[cpu] == -1 && evsel->attr.inherit) | 268 | if (evlist->cpus->map[idx] == -1 && evsel->attr.inherit) |
| 263 | ui__warning("Inherit is not allowed on per-task " | 269 | ui__warning("Inherit is not allowed on per-task " |
| 264 | "events using mmap.\n"); | 270 | "events using mmap.\n"); |
| 265 | return -1; | 271 | return -1; |
| @@ -269,6 +275,86 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *ev · 3 unmodified lines |
| 269 | return 0; | 275 | return 0; |
| 270 | } | 276 | } |
| 271 | | 277 | |
| | 278 | static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mask) |
| | 279 | { |
| | 280 | struct perf_evsel *evsel; |
| | 281 | int cpu, thread; |
| | 282 | |
| | 283 | for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { |
| | 284 | int output = -1; |
| | 285 | |
| | 286 | for (thread = 0; thread < evlist->threads->nr; thread++) { |
| | 287 | list_for_each_entry(evsel, &evlist->entries, node) { |
| | 288 | int fd = FD(evsel, cpu, thread); |
| | 289 | |
| | 290 | if (output == -1) { |
| | 291 | output = fd; |
| | 292 | if (__perf_evlist__mmap(evlist, evsel, cpu, |
| | 293 | prot, mask, output) < 0) |
| | 294 | goto out_unmap; |
| | 295 | } else { |
| | 296 | if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0) |
| | 297 | goto out_unmap; |
| | 298 | } |
| | 299 | |
| | 300 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && |
| | 301 | perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) |
| | 302 | goto out_unmap; |
| | 303 | } |
| | 304 | } |
| | 305 | } |
| | 306 | |
| | 307 | return 0; |
| | 308 | |
| | 309 | out_unmap: |
| | 310 | for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { |
| | 311 | if (evlist->mmap[cpu].base != NULL) { |
| | 312 | munmap(evlist->mmap[cpu].base, evlist->mmap_len); |
| | 313 | evlist->mmap[cpu].base = NULL; |
| | 314 | } |
| | 315 | } |
| | 316 | return -1; |
| | 317 | } |
| | 318 | |
| | 319 | static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, int mask) |
| | 320 | { |
| | 321 | struct perf_evsel *evsel; |
| | 322 | int thread; |
| | 323 | |
| | 324 | for (thread = 0; thread < evlist->threads->nr; thread++) { |
| | 325 | int output = -1; |
| | 326 | |
| | 327 | list_for_each_entry(evsel, &evlist->entries, node) { |
| | 328 | int fd = FD(evsel, 0, thread); |
| | 329 | |
| | 330 | if (output == -1) { |
| | 331 | output = fd; |
| | 332 | if (__perf_evlist__mmap(evlist, evsel, thread, |
| | 333 | prot, mask, output) < 0) |
| | 334 | goto out_unmap; |
| | 335 | } else { |
| | 336 | if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0) |
| | 337 | goto out_unmap; |
| | 338 | } |
| | 339 | |
| | 340 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && |
| | 341 | perf_evlist__id_add_fd(evlist, evsel, 0, thread, fd) < 0) |
| | 342 | goto out_unmap; |
| | 343 | } |
| | 344 | } |
| | 345 | |
| | 346 | return 0; |
| | 347 | |
| | 348 | out_unmap: |
| | 349 | for (thread = 0; thread < evlist->threads->nr; thread++) { |
| | 350 | if (evlist->mmap[thread].base != NULL) { |
| | 351 | munmap(evlist->mmap[thread].base, evlist->mmap_len); |
| | 352 | evlist->mmap[thread].base = NULL; |
| | 353 | } |
| | 354 | } |
| | 355 | return -1; |
| | 356 | } |
| | 357 | |
| 272 | /** perf_evlist__mmap - Create per cpu maps to receive events | 358 | /** perf_evlist__mmap - Create per cpu maps to receive events |
| 273 | * | 359 | * |
| 274 | * @evlist - list of events | 360 | * @evlist - list of events |
| @@ -287,11 +373,11 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *ev · 12 unmodified lines |
| 287 | int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite) | 373 | int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite) |
| 288 | { | 374 | { |
| 289 | unsigned int page_size = sysconf(_SC_PAGE_SIZE); | 375 | unsigned int page_size = sysconf(_SC_PAGE_SIZE); |
| 290 | int mask = pages * page_size - 1, cpu; | 376 | int mask = pages * page_size - 1; |
| 291 | struct perf_evsel *first_evsel, *evsel; | 377 | struct perf_evsel *evsel; |
| 292 | const struct cpu_map *cpus = evlist->cpus; | 378 | const struct cpu_map *cpus = evlist->cpus; |
| 293 | const struct thread_map *threads = evlist->threads; | 379 | const struct thread_map *threads = evlist->threads; |
| 294 | int thread, prot = PROT_READ | (overwrite ? 0 : PROT_WRITE); | 380 | int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE); |
| 295 | | 381 | |
| 296 | if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) | 382 | if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) |
| 297 | return -ENOMEM; | 383 | return -ENOMEM; |
| @@ -301,43 +387,18 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite) · 3 unmodified lines |
| 301 | | 387 | |
| 302 | evlist->overwrite = overwrite; | 388 | evlist->overwrite = overwrite; |
| 303 | evlist->mmap_len = (pages + 1) * page_size; | 389 | evlist->mmap_len = (pages + 1) * page_size; |
| 304 | first_evsel = list_entry(evlist->entries.next, struct perf_evsel, node); | | |
| 305 | | 390 | |
| 306 | list_for_each_entry(evsel, &evlist->entries, node) { | 391 | list_for_each_entry(evsel, &evlist->entries, node) { |
| 307 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && | 392 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && |
| 308 | evsel->sample_id == NULL && | 393 | evsel->sample_id == NULL && |
| 309 | perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0) | 394 | perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0) |
| 310 | return -ENOMEM; | 395 | return -ENOMEM; |
| 311 | | | |
| 312 | for (cpu = 0; cpu < cpus->nr; cpu++) { | | |
| 313 | for (thread = 0; thread < threads->nr; thread++) { | | |
| 314 | int fd = FD(evsel, cpu, thread); | | |
| 315 | | | |
| 316 | if (evsel->idx || thread) { | | |
| 317 | if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, | | |
| 318 | FD(first_evsel, cpu, 0)) != 0) | | |
| 319 | goto out_unmap; | | |
| 320 | } else if (__perf_evlist__mmap(evlist, evsel, cpu, | | |
| 321 | prot, mask, fd) < 0) | | |
| 322 | goto out_unmap; | | |
| 323 | | | |
| 324 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && | | |
| 325 | perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) | | |
| 326 | goto out_unmap; | | |
| 327 | } | | |
| 328 | } | | |
| 329 | } | 396 | } |
| 330 | | 397 | |
| 331 | return 0; | 398 | if (evlist->cpus->map[0] == -1) |
| | 399 | return perf_evlist__mmap_per_thread(evlist, prot, mask); |
| 332 | | 400 | |
| 333 | out_unmap: | 401 | return perf_evlist__mmap_per_cpu(evlist, prot, mask); |
| 334 | for (cpu = 0; cpu < cpus->nr; cpu++) { | | |
| 335 | if (evlist->mmap[cpu].base != NULL) { | | |
| 336 | munmap(evlist->mmap[cpu].base, evlist->mmap_len); | | |
| 337 | evlist->mmap[cpu].base = NULL; | | |
| 338 | } | | |
| 339 | } | | |
| 340 | return -1; | | |
| 341 | } | 402 | } |
| 342 | | 403 | |
| 343 | int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, | 404 | int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, |
| @@ -348,7 +409,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, · 4 unmodified lines |
| 348 | if (evlist->threads == NULL) | 409 | if (evlist->threads == NULL) |
| 349 | return -1; | 410 | return -1; |
| 350 | | 411 | |
| 351 | if (target_tid != -1) | 412 | if (cpu_list == NULL && target_tid != -1) |
| 352 | evlist->cpus = cpu_map__dummy_new(); | 413 | evlist->cpus = cpu_map__dummy_new(); |
| 353 | else | 414 | else |
| 354 | evlist->cpus = cpu_map__new(cpu_list); | 415 | evlist->cpus = cpu_map__new(cpu_list); |