aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/events/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/events/core.c')
-rw-r--r--kernel/events/core.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 0463c1151bae..2aad959e6def 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1887,6 +1887,89 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
1887 ctx->generation++; 1887 ctx->generation++;
1888} 1888}
1889 1889
1890static int
1891perf_aux_output_match(struct perf_event *event, struct perf_event *aux_event)
1892{
1893 if (!has_aux(aux_event))
1894 return 0;
1895
1896 if (!event->pmu->aux_output_match)
1897 return 0;
1898
1899 return event->pmu->aux_output_match(aux_event);
1900}
1901
1902static void put_event(struct perf_event *event);
1903static void event_sched_out(struct perf_event *event,
1904 struct perf_cpu_context *cpuctx,
1905 struct perf_event_context *ctx);
1906
1907static void perf_put_aux_event(struct perf_event *event)
1908{
1909 struct perf_event_context *ctx = event->ctx;
1910 struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
1911 struct perf_event *iter;
1912
1913 /*
1914 * If event uses aux_event tear down the link
1915 */
1916 if (event->aux_event) {
1917 iter = event->aux_event;
1918 event->aux_event = NULL;
1919 put_event(iter);
1920 return;
1921 }
1922
1923 /*
1924 * If the event is an aux_event, tear down all links to
1925 * it from other events.
1926 */
1927 for_each_sibling_event(iter, event->group_leader) {
1928 if (iter->aux_event != event)
1929 continue;
1930
1931 iter->aux_event = NULL;
1932 put_event(event);
1933
1934 /*
1935 * If it's ACTIVE, schedule it out and put it into ERROR
1936 * state so that we don't try to schedule it again. Note
1937 * that perf_event_enable() will clear the ERROR status.
1938 */
1939 event_sched_out(iter, cpuctx, ctx);
1940 perf_event_set_state(event, PERF_EVENT_STATE_ERROR);
1941 }
1942}
1943
1944static int perf_get_aux_event(struct perf_event *event,
1945 struct perf_event *group_leader)
1946{
1947 /*
1948 * Our group leader must be an aux event if we want to be
1949 * an aux_output. This way, the aux event will precede its
1950 * aux_output events in the group, and therefore will always
1951 * schedule first.
1952 */
1953 if (!group_leader)
1954 return 0;
1955
1956 if (!perf_aux_output_match(event, group_leader))
1957 return 0;
1958
1959 if (!atomic_long_inc_not_zero(&group_leader->refcount))
1960 return 0;
1961
1962 /*
1963 * Link aux_outputs to their aux event; this is undone in
1964 * perf_group_detach() by perf_put_aux_event(). When the
1965 * group in torn down, the aux_output events loose their
1966 * link to the aux_event and can't schedule any more.
1967 */
1968 event->aux_event = group_leader;
1969
1970 return 1;
1971}
1972
1890static void perf_group_detach(struct perf_event *event) 1973static void perf_group_detach(struct perf_event *event)
1891{ 1974{
1892 struct perf_event *sibling, *tmp; 1975 struct perf_event *sibling, *tmp;
@@ -1902,6 +1985,8 @@ static void perf_group_detach(struct perf_event *event)
1902 1985
1903 event->attach_state &= ~PERF_ATTACH_GROUP; 1986 event->attach_state &= ~PERF_ATTACH_GROUP;
1904 1987
1988 perf_put_aux_event(event);
1989
1905 /* 1990 /*
1906 * If this is a sibling, remove it from its group. 1991 * If this is a sibling, remove it from its group.
1907 */ 1992 */
@@ -10426,6 +10511,12 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
10426 goto err_ns; 10511 goto err_ns;
10427 } 10512 }
10428 10513
10514 if (event->attr.aux_output &&
10515 !(pmu->capabilities & PERF_PMU_CAP_AUX_OUTPUT)) {
10516 err = -EOPNOTSUPP;
10517 goto err_pmu;
10518 }
10519
10429 err = exclusive_event_init(event); 10520 err = exclusive_event_init(event);
10430 if (err) 10521 if (err)
10431 goto err_pmu; 10522 goto err_pmu;
@@ -11082,6 +11173,8 @@ SYSCALL_DEFINE5(perf_event_open,
11082 } 11173 }
11083 } 11174 }
11084 11175
11176 if (event->attr.aux_output && !perf_get_aux_event(event, group_leader))
11177 goto err_locked;
11085 11178
11086 /* 11179 /*
11087 * Must be under the same ctx::mutex as perf_install_in_context(), 11180 * Must be under the same ctx::mutex as perf_install_in_context(),