|
19 | 19 | #include "debug.h"
|
20 | 20 | #include "units.h"
|
21 | 21 | #include "asm/bug.h"
|
| 22 | +#include "bpf-event.h" |
22 | 23 | #include <signal.h>
|
23 | 24 | #include <unistd.h>
|
24 | 25 |
|
@@ -1856,3 +1857,121 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list,
|
1856 | 1857 | }
|
1857 | 1858 | return leader;
|
1858 | 1859 | }
|
| 1860 | + |
| 1861 | +int perf_evlist__add_sb_event(struct perf_evlist **evlist, |
| 1862 | + struct perf_event_attr *attr, |
| 1863 | + perf_evsel__sb_cb_t cb, |
| 1864 | + void *data) |
| 1865 | +{ |
| 1866 | + struct perf_evsel *evsel; |
| 1867 | + bool new_evlist = (*evlist) == NULL; |
| 1868 | + |
| 1869 | + if (*evlist == NULL) |
| 1870 | + *evlist = perf_evlist__new(); |
| 1871 | + if (*evlist == NULL) |
| 1872 | + return -1; |
| 1873 | + |
| 1874 | + if (!attr->sample_id_all) { |
| 1875 | + pr_warning("enabling sample_id_all for all side band events\n"); |
| 1876 | + attr->sample_id_all = 1; |
| 1877 | + } |
| 1878 | + |
| 1879 | + evsel = perf_evsel__new_idx(attr, (*evlist)->nr_entries); |
| 1880 | + if (!evsel) |
| 1881 | + goto out_err; |
| 1882 | + |
| 1883 | + evsel->side_band.cb = cb; |
| 1884 | + evsel->side_band.data = data; |
| 1885 | + perf_evlist__add(*evlist, evsel); |
| 1886 | + return 0; |
| 1887 | + |
| 1888 | +out_err: |
| 1889 | + if (new_evlist) { |
| 1890 | + perf_evlist__delete(*evlist); |
| 1891 | + *evlist = NULL; |
| 1892 | + } |
| 1893 | + return -1; |
| 1894 | +} |
| 1895 | + |
| 1896 | +static void *perf_evlist__poll_thread(void *arg) |
| 1897 | +{ |
| 1898 | + struct perf_evlist *evlist = arg; |
| 1899 | + bool draining = false; |
| 1900 | + int i; |
| 1901 | + |
| 1902 | + while (draining || !(evlist->thread.done)) { |
| 1903 | + if (draining) |
| 1904 | + draining = false; |
| 1905 | + else if (evlist->thread.done) |
| 1906 | + draining = true; |
| 1907 | + |
| 1908 | + if (!draining) |
| 1909 | + perf_evlist__poll(evlist, 1000); |
| 1910 | + |
| 1911 | + for (i = 0; i < evlist->nr_mmaps; i++) { |
| 1912 | + struct perf_mmap *map = &evlist->mmap[i]; |
| 1913 | + union perf_event *event; |
| 1914 | + |
| 1915 | + if (perf_mmap__read_init(map)) |
| 1916 | + continue; |
| 1917 | + while ((event = perf_mmap__read_event(map)) != NULL) { |
| 1918 | + struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event); |
| 1919 | + |
| 1920 | + if (evsel && evsel->side_band.cb) |
| 1921 | + evsel->side_band.cb(event, evsel->side_band.data); |
| 1922 | + else |
| 1923 | + pr_warning("cannot locate proper evsel for the side band event\n"); |
| 1924 | + |
| 1925 | + perf_mmap__consume(map); |
| 1926 | + } |
| 1927 | + perf_mmap__read_done(map); |
| 1928 | + } |
| 1929 | + } |
| 1930 | + return NULL; |
| 1931 | +} |
| 1932 | + |
| 1933 | +int perf_evlist__start_sb_thread(struct perf_evlist *evlist, |
| 1934 | + struct target *target) |
| 1935 | +{ |
| 1936 | + struct perf_evsel *counter; |
| 1937 | + |
| 1938 | + if (!evlist) |
| 1939 | + return 0; |
| 1940 | + |
| 1941 | + if (perf_evlist__create_maps(evlist, target)) |
| 1942 | + goto out_delete_evlist; |
| 1943 | + |
| 1944 | + evlist__for_each_entry(evlist, counter) { |
| 1945 | + if (perf_evsel__open(counter, evlist->cpus, |
| 1946 | + evlist->threads) < 0) |
| 1947 | + goto out_delete_evlist; |
| 1948 | + } |
| 1949 | + |
| 1950 | + if (perf_evlist__mmap(evlist, UINT_MAX)) |
| 1951 | + goto out_delete_evlist; |
| 1952 | + |
| 1953 | + evlist__for_each_entry(evlist, counter) { |
| 1954 | + if (perf_evsel__enable(counter)) |
| 1955 | + goto out_delete_evlist; |
| 1956 | + } |
| 1957 | + |
| 1958 | + evlist->thread.done = 0; |
| 1959 | + if (pthread_create(&evlist->thread.th, NULL, perf_evlist__poll_thread, evlist)) |
| 1960 | + goto out_delete_evlist; |
| 1961 | + |
| 1962 | + return 0; |
| 1963 | + |
| 1964 | +out_delete_evlist: |
| 1965 | + perf_evlist__delete(evlist); |
| 1966 | + evlist = NULL; |
| 1967 | + return -1; |
| 1968 | +} |
| 1969 | + |
| 1970 | +void perf_evlist__stop_sb_thread(struct perf_evlist *evlist) |
| 1971 | +{ |
| 1972 | + if (!evlist) |
| 1973 | + return; |
| 1974 | + evlist->thread.done = 1; |
| 1975 | + pthread_join(evlist->thread.th, NULL); |
| 1976 | + perf_evlist__delete(evlist); |
| 1977 | +} |
0 commit comments