if (evlist) {
perf_evlist__delete(evlist);
} else {
- cpu_map__delete(cpus);
+ cpu_map__put(cpus);
thread_map__delete(threads);
}
machines__destroy_kernel_maps(&machines);
perf_evlist__disable(evlist);
perf_evlist__delete(evlist);
} else {
- cpu_map__delete(cpus);
+ cpu_map__put(cpus);
thread_map__delete(threads);
}
cpus = NULL;
threads = NULL;
out_free_cpus:
- cpu_map__delete(cpus);
+ cpu_map__put(cpus);
out_free_threads:
thread_map__delete(threads);
return err;
perf_evlist__disable(evlist);
perf_evlist__delete(evlist);
} else {
- cpu_map__delete(cpus);
+ cpu_map__put(cpus);
thread_map__delete(threads);
}
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
+#include "asm/bug.h"
static struct cpu_map *cpu_map__default_new(void)
{
cpus->map[i] = i;
cpus->nr = nr_cpus;
+ atomic_set(&cpus->refcnt, 1);
}
return cpus;
if (cpus != NULL) {
cpus->nr = nr_cpus;
memcpy(cpus->map, tmp_cpus, payload_size);
+ atomic_set(&cpus->refcnt, 1);
}
return cpus;
if (cpus != NULL) {
cpus->nr = 1;
cpus->map[0] = -1;
+ atomic_set(&cpus->refcnt, 1);
}
return cpus;
}
-void cpu_map__delete(struct cpu_map *map)
+static void cpu_map__delete(struct cpu_map *map)
{
- free(map);
+ if (map) {
+ WARN_ONCE(atomic_read(&map->refcnt) != 0,
+ "cpu_map refcnt unbalanced\n");
+ free(map);
+ }
+}
+
+struct cpu_map *cpu_map__get(struct cpu_map *map)
+{
+ if (map)
+ atomic_inc(&map->refcnt);
+ return map;
+}
+
+void cpu_map__put(struct cpu_map *map)
+{
+ if (map && atomic_dec_and_test(&map->refcnt))
+ cpu_map__delete(map);
}
int cpu_map__get_socket(struct cpu_map *map, int idx)
/* ensure we process id in increasing order */
qsort(c->map, c->nr, sizeof(int), cmp_ids);
+ atomic_set(&cpus->refcnt, 1);
*res = c;
return 0;
}
#include <stdio.h>
#include <stdbool.h>
+#include <linux/atomic.h>
#include "perf.h"
#include "util/debug.h"
struct cpu_map {
+ atomic_t refcnt;
int nr;
int map[];
};
struct cpu_map *cpu_map__new(const char *cpu_list);
struct cpu_map *cpu_map__dummy_new(void);
-void cpu_map__delete(struct cpu_map *map);
struct cpu_map *cpu_map__read(FILE *file);
size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
int cpu_map__get_socket(struct cpu_map *map, int idx);
int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp);
int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep);
+struct cpu_map *cpu_map__get(struct cpu_map *map);
+void cpu_map__put(struct cpu_map *map);
+
static inline int cpu_map__socket(struct cpu_map *sock, int s)
{
if (!sock || s > sock->nr || s < 0)
{
perf_evlist__munmap(evlist);
perf_evlist__close(evlist);
- cpu_map__delete(evlist->cpus);
+ cpu_map__put(evlist->cpus);
thread_map__delete(evlist->threads);
evlist->cpus = NULL;
evlist->threads = NULL;
out:
return err;
out_free_cpus:
- cpu_map__delete(evlist->cpus);
+ cpu_map__put(evlist->cpus);
evlist->cpus = NULL;
goto out;
}
perf_evsel__free_fd(evsel);
perf_evsel__free_id(evsel);
close_cgroup(evsel->cgrp);
+ cpu_map__put(evsel->cpus);
zfree(&evsel->group_name);
zfree(&evsel->name);
perf_evsel__object.fini(evsel);
#include "parse-events-flex.h"
#include "pmu.h"
#include "thread_map.h"
+#include "cpumap.h"
#include "asm/bug.h"
#define MAX_NAME_LEN 100
if (!evsel)
return NULL;
- evsel->cpus = cpus;
+ if (cpus)
+ evsel->cpus = cpu_map__get(cpus);
+
if (name)
evsel->name = strdup(name);
list_add_tail(&evsel->node, list);
static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
{
- cpu_map__delete(pcpus->cpus);
+ cpu_map__put(pcpus->cpus);
pcpus->ob_type->tp_free((PyObject*)pcpus);
}
if (!cpus)
return false;
cpu = cpus->map[0];
- cpu_map__delete(cpus);
+ cpu_map__put(cpus);
do {
ret = perf_do_probe_api(fn, cpu, try[i++]);
struct cpu_map *cpus = cpu_map__new(NULL);
cpu = cpus ? cpus->map[0] : 0;
- cpu_map__delete(cpus);
+ cpu_map__put(cpus);
} else {
cpu = evlist->cpus->map[0];
}
err = 0;
out_delete_map:
- cpu_map__delete(map);
+ cpu_map__put(map);
return err;
}
set_bit(c, cpumask_bits(b));
}
- cpu_map__delete(m);
+ cpu_map__put(m);
return ret;
}