diff options
Diffstat (limited to 'tools/perf/util/cgroup.c')
-rw-r--r-- | tools/perf/util/cgroup.c | 128 |
1 files changed, 95 insertions, 33 deletions
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index 984f69144f87..decb91f9da82 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c @@ -71,7 +71,7 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen) return -1; } -static int open_cgroup(char *name) +static int open_cgroup(const char *name) { char path[PATH_MAX + 1]; char mnt[PATH_MAX + 1]; @@ -81,7 +81,7 @@ static int open_cgroup(char *name) if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1)) return -1; - snprintf(path, PATH_MAX, "%s/%s", mnt, name); + scnprintf(path, PATH_MAX, "%s/%s", mnt, name); fd = open(path, O_RDONLY); if (fd == -1) @@ -90,41 +90,64 @@ static int open_cgroup(char *name) return fd; } -static int add_cgroup(struct perf_evlist *evlist, char *str) +static struct cgroup *evlist__find_cgroup(struct perf_evlist *evlist, const char *str) { struct perf_evsel *counter; - struct cgroup_sel *cgrp = NULL; - int n; + struct cgroup *cgrp = NULL; /* * check if cgrp is already defined, if so we reuse it */ evlist__for_each_entry(evlist, counter) { - cgrp = counter->cgrp; - if (!cgrp) + if (!counter->cgrp) continue; - if (!strcmp(cgrp->name, str)) { - refcount_inc(&cgrp->refcnt); + if (!strcmp(counter->cgrp->name, str)) { + cgrp = cgroup__get(counter->cgrp); break; } - - cgrp = NULL; } - if (!cgrp) { - cgrp = zalloc(sizeof(*cgrp)); - if (!cgrp) - return -1; + return cgrp; +} - cgrp->name = str; - refcount_set(&cgrp->refcnt, 1); +static struct cgroup *cgroup__new(const char *name) +{ + struct cgroup *cgroup = zalloc(sizeof(*cgroup)); - cgrp->fd = open_cgroup(str); - if (cgrp->fd == -1) { - free(cgrp); - return -1; - } + if (cgroup != NULL) { + refcount_set(&cgroup->refcnt, 1); + + cgroup->name = strdup(name); + if (!cgroup->name) + goto out_err; + cgroup->fd = open_cgroup(name); + if (cgroup->fd == -1) + goto out_free_name; } + return cgroup; + +out_free_name: + free(cgroup->name); +out_err: + free(cgroup); + return NULL; +} + +struct cgroup *evlist__findnew_cgroup(struct perf_evlist *evlist, const char *name) +{ + struct cgroup *cgroup = evlist__find_cgroup(evlist, name); + + return cgroup ?: cgroup__new(name); +} + +static int add_cgroup(struct perf_evlist *evlist, const char *str) +{ + struct perf_evsel *counter; + struct cgroup *cgrp = evlist__findnew_cgroup(evlist, str); + int n; + + if (!cgrp) + return -1; /* * find corresponding event * if add cgroup N, then need to find event N @@ -135,31 +158,58 @@ static int add_cgroup(struct perf_evlist *evlist, char *str) goto found; n++; } - if (refcount_dec_and_test(&cgrp->refcnt)) - free(cgrp); + cgroup__put(cgrp); return -1; found: counter->cgrp = cgrp; return 0; } -void close_cgroup(struct cgroup_sel *cgrp) +static void cgroup__delete(struct cgroup *cgroup) +{ + close(cgroup->fd); + zfree(&cgroup->name); + free(cgroup); +} + +void cgroup__put(struct cgroup *cgrp) { if (cgrp && refcount_dec_and_test(&cgrp->refcnt)) { - close(cgrp->fd); - zfree(&cgrp->name); - free(cgrp); + cgroup__delete(cgrp); } } -int parse_cgroups(const struct option *opt __maybe_unused, const char *str, +struct cgroup *cgroup__get(struct cgroup *cgroup) +{ + if (cgroup) + refcount_inc(&cgroup->refcnt); + return cgroup; +} + +static void evsel__set_default_cgroup(struct perf_evsel *evsel, struct cgroup *cgroup) +{ + if (evsel->cgrp == NULL) + evsel->cgrp = cgroup__get(cgroup); +} + +void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgroup) +{ + struct perf_evsel *evsel; + + evlist__for_each_entry(evlist, evsel) + evsel__set_default_cgroup(evsel, cgroup); +} + +int parse_cgroups(const struct option *opt, const char *str, int unset __maybe_unused) { struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; + struct perf_evsel *counter; + struct cgroup *cgrp = NULL; const char *p, *e, *eos = str + strlen(str); char *s; - int ret; + int ret, i; if (list_empty(&evlist->entries)) { fprintf(stderr, "must define events before cgroups\n"); @@ -177,10 +227,9 @@ int parse_cgroups(const struct option *opt __maybe_unused, const char *str, if (!s) return -1; ret = add_cgroup(evlist, s); - if (ret) { - free(s); + free(s); + if (ret) return -1; - } } /* nr_cgroups is increased een for empty cgroups */ nr_cgroups++; @@ -188,5 +237,18 @@ int parse_cgroups(const struct option *opt __maybe_unused, const char *str, break; str = p+1; } + /* for the case one cgroup combine to multiple events */ + i = 0; + if (nr_cgroups == 1) { + evlist__for_each_entry(evlist, counter) { + if (i == 0) + cgrp = counter->cgrp; + else { + counter->cgrp = cgrp; + refcount_inc(&cgrp->refcnt); + } + i++; + } + } return 0; } |