parse-events.c (e8d38345da249be17046b74d7bb64b77cdd07a08) parse-events.c (b161f25fa30644598007d752a1b802cda0140788)
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/hw_breakpoint.h>
3#include <linux/err.h>
4#include <linux/list_sort.h>
5#include <linux/zalloc.h>
6#include <dirent.h>
7#include <errno.h>
8#include <sys/ioctl.h>

--- 2086 unchanged lines hidden (view full) ---

2095}
2096
2097__weak int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs)
2098{
2099 /* Order by insertion index. */
2100 return lhs->core.idx - rhs->core.idx;
2101}
2102
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/hw_breakpoint.h>
3#include <linux/err.h>
4#include <linux/list_sort.h>
5#include <linux/zalloc.h>
6#include <dirent.h>
7#include <errno.h>
8#include <sys/ioctl.h>

--- 2086 unchanged lines hidden (view full) ---

2095}
2096
2097__weak int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs)
2098{
2099 /* Order by insertion index. */
2100 return lhs->core.idx - rhs->core.idx;
2101}
2102
2103static int evlist__cmp(void *state, const struct list_head *l, const struct list_head *r)
2103static int evlist__cmp(void *_fg_idx, const struct list_head *l, const struct list_head *r)
2104{
2105 const struct perf_evsel *lhs_core = container_of(l, struct perf_evsel, node);
2106 const struct evsel *lhs = container_of(lhs_core, struct evsel, core);
2107 const struct perf_evsel *rhs_core = container_of(r, struct perf_evsel, node);
2108 const struct evsel *rhs = container_of(rhs_core, struct evsel, core);
2104{
2105 const struct perf_evsel *lhs_core = container_of(l, struct perf_evsel, node);
2106 const struct evsel *lhs = container_of(lhs_core, struct evsel, core);
2107 const struct perf_evsel *rhs_core = container_of(r, struct perf_evsel, node);
2108 const struct evsel *rhs = container_of(rhs_core, struct evsel, core);
2109 int *leader_idx = state;
2110 int lhs_leader_idx = *leader_idx, rhs_leader_idx = *leader_idx, ret;
2109 int *force_grouped_idx = _fg_idx;
2110 int lhs_sort_idx, rhs_sort_idx, ret;
2111 const char *lhs_pmu_name, *rhs_pmu_name;
2111 const char *lhs_pmu_name, *rhs_pmu_name;
2112 bool lhs_has_group = false, rhs_has_group = false;
2112 bool lhs_has_group, rhs_has_group;
2113
2114 /*
2115 * First sort by grouping/leader. Read the leader idx only if the evsel
2116 * is part of a group, by default ungrouped events will be sorted
2117 * relative to grouped events based on where the first ungrouped event
2118 * occurs. If both events don't have a group we want to fall-through to
2119 * the arch specific sorting, that can reorder and fix things like
2120 * Intel's topdown events.
2121 */
2122 if (lhs_core->leader != lhs_core || lhs_core->nr_members > 1) {
2123 lhs_has_group = true;
2113
2114 /*
2115 * First sort by grouping/leader. Read the leader idx only if the evsel
2116 * is part of a group, by default ungrouped events will be sorted
2117 * relative to grouped events based on where the first ungrouped event
2118 * occurs. If both events don't have a group we want to fall-through to
2119 * the arch specific sorting, that can reorder and fix things like
2120 * Intel's topdown events.
2121 */
2122 if (lhs_core->leader != lhs_core || lhs_core->nr_members > 1) {
2123 lhs_has_group = true;
2124 lhs_leader_idx = lhs_core->leader->idx;
2124 lhs_sort_idx = lhs_core->leader->idx;
2125 } else {
2126 lhs_has_group = false;
2127 lhs_sort_idx = *force_grouped_idx != -1 && arch_evsel__must_be_in_group(lhs)
2128 ? *force_grouped_idx
2129 : lhs_core->idx;
2125 }
2126 if (rhs_core->leader != rhs_core || rhs_core->nr_members > 1) {
2127 rhs_has_group = true;
2130 }
2131 if (rhs_core->leader != rhs_core || rhs_core->nr_members > 1) {
2132 rhs_has_group = true;
2128 rhs_leader_idx = rhs_core->leader->idx;
2133 rhs_sort_idx = rhs_core->leader->idx;
2134 } else {
2135 rhs_has_group = false;
2136 rhs_sort_idx = *force_grouped_idx != -1 && arch_evsel__must_be_in_group(rhs)
2137 ? *force_grouped_idx
2138 : rhs_core->idx;
2129 }
2130
2139 }
2140
2131 if (lhs_leader_idx != rhs_leader_idx)
2132 return lhs_leader_idx - rhs_leader_idx;
2141 if (lhs_sort_idx != rhs_sort_idx)
2142 return lhs_sort_idx - rhs_sort_idx;
2133
2134 /* Group by PMU if there is a group. Groups can't span PMUs. */
2135 if (lhs_has_group && rhs_has_group) {
2136 lhs_pmu_name = lhs->group_pmu_name;
2137 rhs_pmu_name = rhs->group_pmu_name;
2138 ret = strcmp(lhs_pmu_name, rhs_pmu_name);
2139 if (ret)
2140 return ret;
2141 }
2142
2143 /* Architecture specific sorting. */
2144 return arch_evlist__cmp(lhs, rhs);
2145}
2146
2147static int parse_events__sort_events_and_fix_groups(struct list_head *list)
2148{
2143
2144 /* Group by PMU if there is a group. Groups can't span PMUs. */
2145 if (lhs_has_group && rhs_has_group) {
2146 lhs_pmu_name = lhs->group_pmu_name;
2147 rhs_pmu_name = rhs->group_pmu_name;
2148 ret = strcmp(lhs_pmu_name, rhs_pmu_name);
2149 if (ret)
2150 return ret;
2151 }
2152
2153 /* Architecture specific sorting. */
2154 return arch_evlist__cmp(lhs, rhs);
2155}
2156
2157static int parse_events__sort_events_and_fix_groups(struct list_head *list)
2158{
2149 int idx = 0, unsorted_idx = -1;
2159 int idx = 0, force_grouped_idx = -1;
2150 struct evsel *pos, *cur_leader = NULL;
2151 struct perf_evsel *cur_leaders_grp = NULL;
2152 bool idx_changed = false, cur_leader_force_grouped = false;
2153 int orig_num_leaders = 0, num_leaders = 0;
2154 int ret;
2155
2156 /*
2157 * Compute index to insert ungrouped events at. Place them where the

--- 11 unchanged lines hidden (view full) ---

2169
2170 /*
2171 * Ensure indexes are sequential, in particular for multiple
2172 * event lists being merged. The indexes are used to detect when
2173 * the user order is modified.
2174 */
2175 pos->core.idx = idx++;
2176
2160 struct evsel *pos, *cur_leader = NULL;
2161 struct perf_evsel *cur_leaders_grp = NULL;
2162 bool idx_changed = false, cur_leader_force_grouped = false;
2163 int orig_num_leaders = 0, num_leaders = 0;
2164 int ret;
2165
2166 /*
2167 * Compute index to insert ungrouped events at. Place them where the

--- 11 unchanged lines hidden (view full) ---

2179
2180 /*
2181 * Ensure indexes are sequential, in particular for multiple
2182 * event lists being merged. The indexes are used to detect when
2183 * the user order is modified.
2184 */
2185 pos->core.idx = idx++;
2186
2177 if (unsorted_idx == -1 && pos == pos_leader && pos->core.nr_members < 2)
2178 unsorted_idx = pos->core.idx;
2187 /* Remember an index to sort all forced grouped events together to. */
2188 if (force_grouped_idx == -1 && pos == pos_leader && pos->core.nr_members < 2 &&
2189 arch_evsel__must_be_in_group(pos))
2190 force_grouped_idx = pos->core.idx;
2179 }
2180
2181 /* Sort events. */
2191 }
2192
2193 /* Sort events. */
2182 list_sort(&unsorted_idx, list, evlist__cmp);
2194 list_sort(&force_grouped_idx, list, evlist__cmp);
2183
2184 /*
2185 * Recompute groups, splitting for PMUs and adding groups for events
2186 * that require them.
2187 */
2188 idx = 0;
2189 list_for_each_entry(pos, list, core.node) {
2190 const struct evsel *pos_leader = evsel__leader(pos);
2191 const char *pos_pmu_name = pos->group_pmu_name;
2192 const char *cur_leader_pmu_name;
2195
2196 /*
2197 * Recompute groups, splitting for PMUs and adding groups for events
2198 * that require them.
2199 */
2200 idx = 0;
2201 list_for_each_entry(pos, list, core.node) {
2202 const struct evsel *pos_leader = evsel__leader(pos);
2203 const char *pos_pmu_name = pos->group_pmu_name;
2204 const char *cur_leader_pmu_name;
2193 bool pos_force_grouped = arch_evsel__must_be_in_group(pos);
2205 bool pos_force_grouped = force_grouped_idx != -1 &&
2206 arch_evsel__must_be_in_group(pos);
2194
2195 /* Reset index and nr_members. */
2196 if (pos->core.idx != idx)
2197 idx_changed = true;
2198 pos->core.idx = idx++;
2199 pos->core.nr_members = 0;
2200
2201 /*

--- 623 unchanged lines hidden ---
2207
2208 /* Reset index and nr_members. */
2209 if (pos->core.idx != idx)
2210 idx_changed = true;
2211 pos->core.idx = idx++;
2212 pos->core.nr_members = 0;
2213
2214 /*

--- 623 unchanged lines hidden ---