+15
-10
kernel/events/core.c
+15
-10
kernel/events/core.c
···
3487
3487
int ret;
3488
3488
};
3489
3489
3490
-
static int find_cpu_to_read(struct perf_event *event, int local_cpu)
3490
+
static int __perf_event_read_cpu(struct perf_event *event, int event_cpu)
3491
3491
{
3492
-
int event_cpu = event->oncpu;
3493
3492
u16 local_pkg, event_pkg;
3494
3493
3495
3494
if (event->group_caps & PERF_EV_CAP_READ_ACTIVE_PKG) {
3496
-
event_pkg = topology_physical_package_id(event_cpu);
3497
-
local_pkg = topology_physical_package_id(local_cpu);
3495
+
int local_cpu = smp_processor_id();
3496
+
3497
+
event_pkg = topology_physical_package_id(event_cpu);
3498
+
local_pkg = topology_physical_package_id(local_cpu);
3498
3499
3499
3500
if (event_pkg == local_pkg)
3500
3501
return local_cpu;
···
3625
3624
3626
3625
static int perf_event_read(struct perf_event *event, bool group)
3627
3626
{
3628
-
int ret = 0, cpu_to_read, local_cpu;
3627
+
int event_cpu, ret = 0;
3629
3628
3630
3629
/*
3631
3630
* If event is enabled and currently active on a CPU, update the
···
3638
3637
.ret = 0,
3639
3638
};
3640
3639
3641
-
local_cpu = get_cpu();
3642
-
cpu_to_read = find_cpu_to_read(event, local_cpu);
3643
-
put_cpu();
3640
+
event_cpu = READ_ONCE(event->oncpu);
3641
+
if ((unsigned)event_cpu >= nr_cpu_ids)
3642
+
return 0;
3643
+
3644
+
preempt_disable();
3645
+
event_cpu = __perf_event_read_cpu(event, event_cpu);
3644
3646
3645
3647
/*
3646
3648
* Purposely ignore the smp_call_function_single() return
3647
3649
* value.
3648
3650
*
3649
-
* If event->oncpu isn't a valid CPU it means the event got
3651
+
* If event_cpu isn't a valid CPU it means the event got
3650
3652
* scheduled out and that will have updated the event count.
3651
3653
*
3652
3654
* Therefore, either way, we'll have an up-to-date event count
3653
3655
* after this.
3654
3656
*/
3655
-
(void)smp_call_function_single(cpu_to_read, __perf_event_read, &data, 1);
3657
+
(void)smp_call_function_single(event_cpu, __perf_event_read, &data, 1);
3658
+
preempt_enable();
3656
3659
ret = data.ret;
3657
3660
} else if (event->state == PERF_EVENT_STATE_INACTIVE) {
3658
3661
struct perf_event_context *ctx = event->ctx;
+1
-1
tools/perf/builtin-diff.c
+1
-1
tools/perf/builtin-diff.c
+10
tools/perf/ui/hist.c
+10
tools/perf/ui/hist.c
···
521
521
list_add_tail(&format->sort_list, &list->sorts);
522
522
}
523
523
524
+
void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,
525
+
struct perf_hpp_fmt *format)
526
+
{
527
+
list_add(&format->sort_list, &list->sorts);
528
+
}
529
+
524
530
void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
525
531
{
526
532
list_del(&format->list);
···
565
559
/* append sort keys to output field */
566
560
perf_hpp_list__for_each_sort_list(list, fmt) {
567
561
struct perf_hpp_fmt *pos;
562
+
563
+
/* skip sort-only fields ("sort_compute" in perf diff) */
564
+
if (!fmt->entry && !fmt->color)
565
+
continue;
568
566
569
567
perf_hpp_list__for_each_format(list, pos) {
570
568
if (fmt_equal(fmt, pos))
+9
-2
tools/perf/util/callchain.c
+9
-2
tools/perf/util/callchain.c
···
437
437
}
438
438
call->ip = cursor_node->ip;
439
439
call->ms.sym = cursor_node->sym;
440
-
call->ms.map = cursor_node->map;
440
+
call->ms.map = map__get(cursor_node->map);
441
441
442
442
if (cursor_node->branch) {
443
443
call->branch_count = 1;
···
477
477
478
478
list_for_each_entry_safe(call, tmp, &new->val, list) {
479
479
list_del(&call->list);
480
+
map__zput(call->ms.map);
480
481
free(call);
481
482
}
482
483
free(new);
···
762
761
list->ms.map, list->ms.sym,
763
762
false, NULL, 0, 0);
764
763
list_del(&list->list);
764
+
map__zput(list->ms.map);
765
765
free(list);
766
766
}
767
767
···
813
811
}
814
812
815
813
node->ip = ip;
816
-
node->map = map;
814
+
map__zput(node->map);
815
+
node->map = map__get(map);
817
816
node->sym = sym;
818
817
node->branch = branch;
819
818
node->nr_loop_iter = nr_loop_iter;
···
1145
1142
1146
1143
list_for_each_entry_safe(list, tmp, &node->parent_val, list) {
1147
1144
list_del(&list->list);
1145
+
map__zput(list->ms.map);
1148
1146
free(list);
1149
1147
}
1150
1148
1151
1149
list_for_each_entry_safe(list, tmp, &node->val, list) {
1152
1150
list_del(&list->list);
1151
+
map__zput(list->ms.map);
1153
1152
free(list);
1154
1153
}
1155
1154
···
1215
1210
goto out;
1216
1211
*new = *chain;
1217
1212
new->has_children = false;
1213
+
map__get(new->ms.map);
1218
1214
list_add_tail(&new->list, &head);
1219
1215
}
1220
1216
parent = parent->parent;
···
1236
1230
out:
1237
1231
list_for_each_entry_safe(chain, new, &head, list) {
1238
1232
list_del(&chain->list);
1233
+
map__zput(chain->ms.map);
1239
1234
free(chain);
1240
1235
}
1241
1236
return -ENOMEM;
+6
tools/perf/util/callchain.h
+6
tools/perf/util/callchain.h
···
5
5
#include <linux/list.h>
6
6
#include <linux/rbtree.h>
7
7
#include "event.h"
8
+
#include "map.h"
8
9
#include "symbol.h"
9
10
10
11
#define HELP_PAD "\t\t\t\t"
···
185
184
*/
186
185
static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
187
186
{
187
+
struct callchain_cursor_node *node;
188
+
188
189
cursor->nr = 0;
189
190
cursor->last = &cursor->first;
191
+
192
+
for (node = cursor->first; node != NULL; node = node->next)
193
+
map__zput(node->map);
190
194
}
191
195
192
196
int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
+7
tools/perf/util/hist.c
+7
tools/perf/util/hist.c
···
1
1
#include "util.h"
2
2
#include "build-id.h"
3
3
#include "hist.h"
4
+
#include "map.h"
4
5
#include "session.h"
5
6
#include "sort.h"
6
7
#include "evlist.h"
···
1020
1019
int max_stack_depth, void *arg)
1021
1020
{
1022
1021
int err, err2;
1022
+
struct map *alm = NULL;
1023
+
1024
+
if (al && al->map)
1025
+
alm = map__get(al->map);
1023
1026
1024
1027
err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent,
1025
1028
iter->evsel, al, max_stack_depth);
···
1062
1057
err2 = iter->ops->finish_entry(iter, al);
1063
1058
if (!err)
1064
1059
err = err2;
1060
+
1061
+
map__put(alm);
1065
1062
1066
1063
return err;
1067
1064
}
+7
tools/perf/util/hist.h
+7
tools/perf/util/hist.h
···
283
283
struct perf_hpp_fmt *format);
284
284
void perf_hpp_list__register_sort_field(struct perf_hpp_list *list,
285
285
struct perf_hpp_fmt *format);
286
+
void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,
287
+
struct perf_hpp_fmt *format);
286
288
287
289
static inline void perf_hpp__column_register(struct perf_hpp_fmt *format)
288
290
{
···
294
292
static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format)
295
293
{
296
294
perf_hpp_list__register_sort_field(&perf_hpp_list, format);
295
+
}
296
+
297
+
static inline void perf_hpp__prepend_sort_field(struct perf_hpp_fmt *format)
298
+
{
299
+
perf_hpp_list__prepend_sort_field(&perf_hpp_list, format);
297
300
}
298
301
299
302
#define perf_hpp_list__for_each_format(_list, format) \