19a399944SArnaldo Carvalho de Melo // SPDX-License-Identifier: GPL-2.0-only
29a399944SArnaldo Carvalho de Melo
39a399944SArnaldo Carvalho de Melo #include "util/debug.h"
49a399944SArnaldo Carvalho de Melo #include "util/evlist.h"
59a399944SArnaldo Carvalho de Melo #include "util/evsel.h"
69a399944SArnaldo Carvalho de Melo #include "util/mmap.h"
7976be845SArnaldo Carvalho de Melo #include "util/perf_api_probe.h"
89a399944SArnaldo Carvalho de Melo #include <perf/mmap.h>
99a399944SArnaldo Carvalho de Melo #include <linux/perf_event.h>
109a399944SArnaldo Carvalho de Melo #include <limits.h>
119a399944SArnaldo Carvalho de Melo #include <pthread.h>
129a399944SArnaldo Carvalho de Melo #include <sched.h>
139a399944SArnaldo Carvalho de Melo #include <stdbool.h>
149a399944SArnaldo Carvalho de Melo
evlist__add_sb_event(struct evlist * evlist,struct perf_event_attr * attr,evsel__sb_cb_t cb,void * data)1508c83997SArnaldo Carvalho de Melo int evlist__add_sb_event(struct evlist *evlist, struct perf_event_attr *attr,
1665ddce3fSArnaldo Carvalho de Melo evsel__sb_cb_t cb, void *data)
179a399944SArnaldo Carvalho de Melo {
189a399944SArnaldo Carvalho de Melo struct evsel *evsel;
199a399944SArnaldo Carvalho de Melo
209a399944SArnaldo Carvalho de Melo if (!attr->sample_id_all) {
219a399944SArnaldo Carvalho de Melo pr_warning("enabling sample_id_all for all side band events\n");
229a399944SArnaldo Carvalho de Melo attr->sample_id_all = 1;
239a399944SArnaldo Carvalho de Melo }
249a399944SArnaldo Carvalho de Melo
258f6725a2SArnaldo Carvalho de Melo evsel = evsel__new_idx(attr, evlist->core.nr_entries);
269a399944SArnaldo Carvalho de Melo if (!evsel)
279a399944SArnaldo Carvalho de Melo return -1;
289a399944SArnaldo Carvalho de Melo
299a399944SArnaldo Carvalho de Melo evsel->side_band.cb = cb;
309a399944SArnaldo Carvalho de Melo evsel->side_band.data = data;
319a399944SArnaldo Carvalho de Melo evlist__add(evlist, evsel);
329a399944SArnaldo Carvalho de Melo return 0;
339a399944SArnaldo Carvalho de Melo }
349a399944SArnaldo Carvalho de Melo
perf_evlist__poll_thread(void * arg)359a399944SArnaldo Carvalho de Melo static void *perf_evlist__poll_thread(void *arg)
369a399944SArnaldo Carvalho de Melo {
379a399944SArnaldo Carvalho de Melo struct evlist *evlist = arg;
389a399944SArnaldo Carvalho de Melo bool draining = false;
399a399944SArnaldo Carvalho de Melo int i, done = 0;
409a399944SArnaldo Carvalho de Melo /*
419a399944SArnaldo Carvalho de Melo * In order to read symbols from other namespaces perf to needs to call
429a399944SArnaldo Carvalho de Melo * setns(2). This isn't permitted if the struct_fs has multiple users.
439a399944SArnaldo Carvalho de Melo * unshare(2) the fs so that we may continue to setns into namespaces
449a399944SArnaldo Carvalho de Melo * that we're observing when, for instance, reading the build-ids at
459a399944SArnaldo Carvalho de Melo * the end of a 'perf record' session.
469a399944SArnaldo Carvalho de Melo */
479a399944SArnaldo Carvalho de Melo unshare(CLONE_FS);
489a399944SArnaldo Carvalho de Melo
499a399944SArnaldo Carvalho de Melo while (!done) {
509a399944SArnaldo Carvalho de Melo bool got_data = false;
519a399944SArnaldo Carvalho de Melo
529a399944SArnaldo Carvalho de Melo if (evlist->thread.done)
539a399944SArnaldo Carvalho de Melo draining = true;
549a399944SArnaldo Carvalho de Melo
559a399944SArnaldo Carvalho de Melo if (!draining)
569a399944SArnaldo Carvalho de Melo evlist__poll(evlist, 1000);
579a399944SArnaldo Carvalho de Melo
589a399944SArnaldo Carvalho de Melo for (i = 0; i < evlist->core.nr_mmaps; i++) {
599a399944SArnaldo Carvalho de Melo struct mmap *map = &evlist->mmap[i];
609a399944SArnaldo Carvalho de Melo union perf_event *event;
619a399944SArnaldo Carvalho de Melo
629a399944SArnaldo Carvalho de Melo if (perf_mmap__read_init(&map->core))
639a399944SArnaldo Carvalho de Melo continue;
649a399944SArnaldo Carvalho de Melo while ((event = perf_mmap__read_event(&map->core)) != NULL) {
653ccf8a7bSArnaldo Carvalho de Melo struct evsel *evsel = evlist__event2evsel(evlist, event);
669a399944SArnaldo Carvalho de Melo
679a399944SArnaldo Carvalho de Melo if (evsel && evsel->side_band.cb)
689a399944SArnaldo Carvalho de Melo evsel->side_band.cb(event, evsel->side_band.data);
699a399944SArnaldo Carvalho de Melo else
709a399944SArnaldo Carvalho de Melo pr_warning("cannot locate proper evsel for the side band event\n");
719a399944SArnaldo Carvalho de Melo
729a399944SArnaldo Carvalho de Melo perf_mmap__consume(&map->core);
739a399944SArnaldo Carvalho de Melo got_data = true;
749a399944SArnaldo Carvalho de Melo }
759a399944SArnaldo Carvalho de Melo perf_mmap__read_done(&map->core);
769a399944SArnaldo Carvalho de Melo }
779a399944SArnaldo Carvalho de Melo
789a399944SArnaldo Carvalho de Melo if (draining && !got_data)
799a399944SArnaldo Carvalho de Melo break;
809a399944SArnaldo Carvalho de Melo }
819a399944SArnaldo Carvalho de Melo return NULL;
829a399944SArnaldo Carvalho de Melo }
839a399944SArnaldo Carvalho de Melo
evlist__set_cb(struct evlist * evlist,evsel__sb_cb_t cb,void * data)8465ddce3fSArnaldo Carvalho de Melo void evlist__set_cb(struct evlist *evlist, evsel__sb_cb_t cb, void *data)
85976be845SArnaldo Carvalho de Melo {
86976be845SArnaldo Carvalho de Melo struct evsel *evsel;
87976be845SArnaldo Carvalho de Melo
88976be845SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, evsel) {
89976be845SArnaldo Carvalho de Melo evsel->core.attr.sample_id_all = 1;
90976be845SArnaldo Carvalho de Melo evsel->core.attr.watermark = 1;
91976be845SArnaldo Carvalho de Melo evsel->core.attr.wakeup_watermark = 1;
92976be845SArnaldo Carvalho de Melo evsel->side_band.cb = cb;
93976be845SArnaldo Carvalho de Melo evsel->side_band.data = data;
94976be845SArnaldo Carvalho de Melo }
95976be845SArnaldo Carvalho de Melo }
96976be845SArnaldo Carvalho de Melo
evlist__start_sb_thread(struct evlist * evlist,struct target * target)9708c83997SArnaldo Carvalho de Melo int evlist__start_sb_thread(struct evlist *evlist, struct target *target)
989a399944SArnaldo Carvalho de Melo {
999a399944SArnaldo Carvalho de Melo struct evsel *counter;
1009a399944SArnaldo Carvalho de Melo
1019a399944SArnaldo Carvalho de Melo if (!evlist)
1029a399944SArnaldo Carvalho de Melo return 0;
1039a399944SArnaldo Carvalho de Melo
1047748bb71SArnaldo Carvalho de Melo if (evlist__create_maps(evlist, target))
1059a399944SArnaldo Carvalho de Melo goto out_delete_evlist;
1069a399944SArnaldo Carvalho de Melo
107976be845SArnaldo Carvalho de Melo if (evlist->core.nr_entries > 1) {
108976be845SArnaldo Carvalho de Melo bool can_sample_identifier = perf_can_sample_identifier();
109976be845SArnaldo Carvalho de Melo
110976be845SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, counter)
111862b2f8fSArnaldo Carvalho de Melo evsel__set_sample_id(counter, can_sample_identifier);
112976be845SArnaldo Carvalho de Melo
1130a7e7ec9SArnaldo Carvalho de Melo evlist__set_id_pos(evlist);
114976be845SArnaldo Carvalho de Melo }
115976be845SArnaldo Carvalho de Melo
1169a399944SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, counter) {
117*0df6ade7SIan Rogers if (evsel__open(counter, evlist->core.user_requested_cpus,
118*0df6ade7SIan Rogers evlist->core.threads) < 0)
1199a399944SArnaldo Carvalho de Melo goto out_delete_evlist;
1209a399944SArnaldo Carvalho de Melo }
1219a399944SArnaldo Carvalho de Melo
1229a399944SArnaldo Carvalho de Melo if (evlist__mmap(evlist, UINT_MAX))
1239a399944SArnaldo Carvalho de Melo goto out_delete_evlist;
1249a399944SArnaldo Carvalho de Melo
1259a399944SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, counter) {
1269a399944SArnaldo Carvalho de Melo if (evsel__enable(counter))
1279a399944SArnaldo Carvalho de Melo goto out_delete_evlist;
1289a399944SArnaldo Carvalho de Melo }
1299a399944SArnaldo Carvalho de Melo
1309a399944SArnaldo Carvalho de Melo evlist->thread.done = 0;
1319a399944SArnaldo Carvalho de Melo if (pthread_create(&evlist->thread.th, NULL, perf_evlist__poll_thread, evlist))
1329a399944SArnaldo Carvalho de Melo goto out_delete_evlist;
1339a399944SArnaldo Carvalho de Melo
1349a399944SArnaldo Carvalho de Melo return 0;
1359a399944SArnaldo Carvalho de Melo
1369a399944SArnaldo Carvalho de Melo out_delete_evlist:
1379a399944SArnaldo Carvalho de Melo evlist__delete(evlist);
1389a399944SArnaldo Carvalho de Melo evlist = NULL;
1399a399944SArnaldo Carvalho de Melo return -1;
1409a399944SArnaldo Carvalho de Melo }
1419a399944SArnaldo Carvalho de Melo
evlist__stop_sb_thread(struct evlist * evlist)14208c83997SArnaldo Carvalho de Melo void evlist__stop_sb_thread(struct evlist *evlist)
1439a399944SArnaldo Carvalho de Melo {
1449a399944SArnaldo Carvalho de Melo if (!evlist)
1459a399944SArnaldo Carvalho de Melo return;
1469a399944SArnaldo Carvalho de Melo evlist->thread.done = 1;
1479a399944SArnaldo Carvalho de Melo pthread_join(evlist->thread.th, NULL);
1489a399944SArnaldo Carvalho de Melo evlist__delete(evlist);
1499a399944SArnaldo Carvalho de Melo }
150