~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/util/sideband_evlist.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 
  3 #include "util/debug.h"
  4 #include "util/evlist.h"
  5 #include "util/evsel.h"
  6 #include "util/mmap.h"
  7 #include "util/perf_api_probe.h"
  8 #include <perf/mmap.h>
  9 #include <linux/perf_event.h>
 10 #include <limits.h>
 11 #include <pthread.h>
 12 #include <sched.h>
 13 #include <stdbool.h>
 14 
 15 int evlist__add_sb_event(struct evlist *evlist, struct perf_event_attr *attr,
 16                          evsel__sb_cb_t cb, void *data)
 17 {
 18         struct evsel *evsel;
 19 
 20         if (!attr->sample_id_all) {
 21                 pr_warning("enabling sample_id_all for all side band events\n");
 22                 attr->sample_id_all = 1;
 23         }
 24 
 25         evsel = evsel__new_idx(attr, evlist->core.nr_entries);
 26         if (!evsel)
 27                 return -1;
 28 
 29         evsel->side_band.cb = cb;
 30         evsel->side_band.data = data;
 31         evlist__add(evlist, evsel);
 32         return 0;
 33 }
 34 
 35 static void *perf_evlist__poll_thread(void *arg)
 36 {
 37         struct evlist *evlist = arg;
 38         bool draining = false;
 39         int i, done = 0;
 40         /*
 41          * In order to read symbols from other namespaces perf to needs to call
 42          * setns(2).  This isn't permitted if the struct_fs has multiple users.
 43          * unshare(2) the fs so that we may continue to setns into namespaces
 44          * that we're observing when, for instance, reading the build-ids at
 45          * the end of a 'perf record' session.
 46          */
 47         unshare(CLONE_FS);
 48 
 49         while (!done) {
 50                 bool got_data = false;
 51 
 52                 if (evlist->thread.done)
 53                         draining = true;
 54 
 55                 if (!draining)
 56                         evlist__poll(evlist, 1000);
 57 
 58                 for (i = 0; i < evlist->core.nr_mmaps; i++) {
 59                         struct mmap *map = &evlist->mmap[i];
 60                         union perf_event *event;
 61 
 62                         if (perf_mmap__read_init(&map->core))
 63                                 continue;
 64                         while ((event = perf_mmap__read_event(&map->core)) != NULL) {
 65                                 struct evsel *evsel = evlist__event2evsel(evlist, event);
 66 
 67                                 if (evsel && evsel->side_band.cb)
 68                                         evsel->side_band.cb(event, evsel->side_band.data);
 69                                 else
 70                                         pr_warning("cannot locate proper evsel for the side band event\n");
 71 
 72                                 perf_mmap__consume(&map->core);
 73                                 got_data = true;
 74                         }
 75                         perf_mmap__read_done(&map->core);
 76                 }
 77 
 78                 if (draining && !got_data)
 79                         break;
 80         }
 81         return NULL;
 82 }
 83 
 84 void evlist__set_cb(struct evlist *evlist, evsel__sb_cb_t cb, void *data)
 85 {
 86         struct evsel *evsel;
 87 
 88         evlist__for_each_entry(evlist, evsel) {
 89                 evsel->core.attr.sample_id_all    = 1;
 90                 evsel->core.attr.watermark        = 1;
 91                 evsel->core.attr.wakeup_watermark = 1;
 92                 evsel->side_band.cb   = cb;
 93                 evsel->side_band.data = data;
 94       }
 95 }
 96 
 97 int evlist__start_sb_thread(struct evlist *evlist, struct target *target)
 98 {
 99         struct evsel *counter;
100 
101         if (!evlist)
102                 return 0;
103 
104         if (evlist__create_maps(evlist, target))
105                 goto out_delete_evlist;
106 
107         if (evlist->core.nr_entries > 1) {
108                 bool can_sample_identifier = perf_can_sample_identifier();
109 
110                 evlist__for_each_entry(evlist, counter)
111                         evsel__set_sample_id(counter, can_sample_identifier);
112 
113                 evlist__set_id_pos(evlist);
114         }
115 
116         evlist__for_each_entry(evlist, counter) {
117                 if (evsel__open(counter, evlist->core.user_requested_cpus,
118                                 evlist->core.threads) < 0)
119                         goto out_delete_evlist;
120         }
121 
122         if (evlist__mmap(evlist, UINT_MAX))
123                 goto out_delete_evlist;
124 
125         evlist__for_each_entry(evlist, counter) {
126                 if (evsel__enable(counter))
127                         goto out_delete_evlist;
128         }
129 
130         evlist->thread.done = 0;
131         if (pthread_create(&evlist->thread.th, NULL, perf_evlist__poll_thread, evlist))
132                 goto out_delete_evlist;
133 
134         return 0;
135 
136 out_delete_evlist:
137         evlist__delete(evlist);
138         evlist = NULL;
139         return -1;
140 }
141 
142 void evlist__stop_sb_thread(struct evlist *evlist)
143 {
144         if (!evlist)
145                 return;
146         evlist->thread.done = 1;
147         pthread_join(evlist->thread.th, NULL);
148         evlist__delete(evlist);
149 }
150 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php