Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tools: Add reference counting for cpu_map object

Adding refference counting for cpu_map object, so it could be easily
shared among other objects.

Using cpu_map__put instead cpu_map__delete and making cpu_map__delete
static.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1435012588-9007-4-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Jiri Olsa and committed by
Arnaldo Carvalho de Melo
f30a79b0 4cc97614

+45 -15
+1 -1
tools/perf/tests/code-reading.c
··· 545 545 if (evlist) { 546 546 perf_evlist__delete(evlist); 547 547 } else { 548 - cpu_map__delete(cpus); 548 + cpu_map__put(cpus); 549 549 thread_map__delete(threads); 550 550 } 551 551 machines__destroy_kernel_maps(&machines);
+1 -1
tools/perf/tests/keep-tracking.c
··· 144 144 perf_evlist__disable(evlist); 145 145 perf_evlist__delete(evlist); 146 146 } else { 147 - cpu_map__delete(cpus); 147 + cpu_map__put(cpus); 148 148 thread_map__delete(threads); 149 149 } 150 150
+1 -1
tools/perf/tests/mmap-basic.c
··· 140 140 cpus = NULL; 141 141 threads = NULL; 142 142 out_free_cpus: 143 - cpu_map__delete(cpus); 143 + cpu_map__put(cpus); 144 144 out_free_threads: 145 145 thread_map__delete(threads); 146 146 return err;
+1 -1
tools/perf/tests/switch-tracking.c
··· 560 560 perf_evlist__disable(evlist); 561 561 perf_evlist__delete(evlist); 562 562 } else { 563 - cpu_map__delete(cpus); 563 + cpu_map__put(cpus); 564 564 thread_map__delete(threads); 565 565 } 566 566
+24 -2
tools/perf/util/cpumap.c
··· 5 5 #include <assert.h> 6 6 #include <stdio.h> 7 7 #include <stdlib.h> 8 + #include "asm/bug.h" 8 9 9 10 static struct cpu_map *cpu_map__default_new(void) 10 11 { ··· 23 22 cpus->map[i] = i; 24 23 25 24 cpus->nr = nr_cpus; 25 + atomic_set(&cpus->refcnt, 1); 26 26 } 27 27 28 28 return cpus; ··· 37 35 if (cpus != NULL) { 38 36 cpus->nr = nr_cpus; 39 37 memcpy(cpus->map, tmp_cpus, payload_size); 38 + atomic_set(&cpus->refcnt, 1); 40 39 } 41 40 42 41 return cpus; ··· 197 194 if (cpus != NULL) { 198 195 cpus->nr = 1; 199 196 cpus->map[0] = -1; 197 + atomic_set(&cpus->refcnt, 1); 200 198 } 201 199 202 200 return cpus; 203 201 } 204 202 205 - void cpu_map__delete(struct cpu_map *map) 203 + static void cpu_map__delete(struct cpu_map *map) 206 204 { 207 - free(map); 205 + if (map) { 206 + WARN_ONCE(atomic_read(&map->refcnt) != 0, 207 + "cpu_map refcnt unbalanced\n"); 208 + free(map); 209 + } 210 + } 211 + 212 + struct cpu_map *cpu_map__get(struct cpu_map *map) 213 + { 214 + if (map) 215 + atomic_inc(&map->refcnt); 216 + return map; 217 + } 218 + 219 + void cpu_map__put(struct cpu_map *map) 220 + { 221 + if (map && atomic_dec_and_test(&map->refcnt)) 222 + cpu_map__delete(map); 208 223 } 209 224 210 225 int cpu_map__get_socket(struct cpu_map *map, int idx) ··· 284 263 /* ensure we process id in increasing order */ 285 264 qsort(c->map, c->nr, sizeof(int), cmp_ids); 286 265 266 + atomic_set(&cpus->refcnt, 1); 287 267 *res = c; 288 268 return 0; 289 269 }
+5 -1
tools/perf/util/cpumap.h
··· 3 3 4 4 #include <stdio.h> 5 5 #include <stdbool.h> 6 + #include <linux/atomic.h> 6 7 7 8 #include "perf.h" 8 9 #include "util/debug.h" 9 10 10 11 struct cpu_map { 12 + atomic_t refcnt; 11 13 int nr; 12 14 int map[]; 13 15 }; 14 16 15 17 struct cpu_map *cpu_map__new(const char *cpu_list); 16 18 struct cpu_map *cpu_map__dummy_new(void); 17 - void cpu_map__delete(struct cpu_map *map); 18 19 struct cpu_map *cpu_map__read(FILE *file); 19 20 size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); 20 21 int cpu_map__get_socket(struct cpu_map *map, int idx); 21 22 int cpu_map__get_core(struct cpu_map *map, int idx); 22 23 int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp); 23 24 int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep); 25 + 26 + struct cpu_map *cpu_map__get(struct cpu_map *map); 27 + void cpu_map__put(struct cpu_map *map); 24 28 25 29 static inline int cpu_map__socket(struct cpu_map *sock, int s) 26 30 {
+2 -2
tools/perf/util/evlist.c
··· 114 114 { 115 115 perf_evlist__munmap(evlist); 116 116 perf_evlist__close(evlist); 117 - cpu_map__delete(evlist->cpus); 117 + cpu_map__put(evlist->cpus); 118 118 thread_map__delete(evlist->threads); 119 119 evlist->cpus = NULL; 120 120 evlist->threads = NULL; ··· 1353 1353 out: 1354 1354 return err; 1355 1355 out_free_cpus: 1356 - cpu_map__delete(evlist->cpus); 1356 + cpu_map__put(evlist->cpus); 1357 1357 evlist->cpus = NULL; 1358 1358 goto out; 1359 1359 }
+1
tools/perf/util/evsel.c
··· 885 885 perf_evsel__free_fd(evsel); 886 886 perf_evsel__free_id(evsel); 887 887 close_cgroup(evsel->cgrp); 888 + cpu_map__put(evsel->cpus); 888 889 zfree(&evsel->group_name); 889 890 zfree(&evsel->name); 890 891 perf_evsel__object.fini(evsel);
+4 -1
tools/perf/util/parse-events.c
··· 17 17 #include "parse-events-flex.h" 18 18 #include "pmu.h" 19 19 #include "thread_map.h" 20 + #include "cpumap.h" 20 21 #include "asm/bug.h" 21 22 22 23 #define MAX_NAME_LEN 100 ··· 286 285 if (!evsel) 287 286 return NULL; 288 287 289 - evsel->cpus = cpus; 288 + if (cpus) 289 + evsel->cpus = cpu_map__get(cpus); 290 + 290 291 if (name) 291 292 evsel->name = strdup(name); 292 293 list_add_tail(&evsel->node, list);
+1 -1
tools/perf/util/python.c
··· 384 384 385 385 static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) 386 386 { 387 - cpu_map__delete(pcpus->cpus); 387 + cpu_map__put(pcpus->cpus); 388 388 pcpus->ob_type->tp_free((PyObject*)pcpus); 389 389 } 390 390
+2 -2
tools/perf/util/record.c
··· 64 64 if (!cpus) 65 65 return false; 66 66 cpu = cpus->map[0]; 67 - cpu_map__delete(cpus); 67 + cpu_map__put(cpus); 68 68 69 69 do { 70 70 ret = perf_do_probe_api(fn, cpu, try[i++]); ··· 226 226 struct cpu_map *cpus = cpu_map__new(NULL); 227 227 228 228 cpu = cpus ? cpus->map[0] : 0; 229 - cpu_map__delete(cpus); 229 + cpu_map__put(cpus); 230 230 } else { 231 231 cpu = evlist->cpus->map[0]; 232 232 }
+1 -1
tools/perf/util/session.c
··· 1895 1895 err = 0; 1896 1896 1897 1897 out_delete_map: 1898 - cpu_map__delete(map); 1898 + cpu_map__put(map); 1899 1899 return err; 1900 1900 } 1901 1901
+1 -1
tools/perf/util/svghelper.c
··· 748 748 set_bit(c, cpumask_bits(b)); 749 749 } 750 750 751 - cpu_map__delete(m); 751 + cpu_map__put(m); 752 752 753 753 return ret; 754 754 }