3 #include <subcmd/parse-options.h>
11 cgroupfs_find_mountpoint(char *buf
, size_t maxlen
)
14 char mountpoint
[PATH_MAX
+ 1], tokens
[PATH_MAX
+ 1], type
[PATH_MAX
+ 1];
15 char *token
, *saved_ptr
= NULL
;
18 fp
= fopen("/proc/mounts", "r");
23 * in order to handle split hierarchy, we need to scan /proc/mounts
24 * and inspect every cgroupfs mount point to find one that has
25 * perf_event subsystem
27 while (fscanf(fp
, "%*s %"STR(PATH_MAX
)"s %"STR(PATH_MAX
)"s %"
28 STR(PATH_MAX
)"s %*d %*d\n",
29 mountpoint
, type
, tokens
) == 3) {
31 if (!strcmp(type
, "cgroup")) {
33 token
= strtok_r(tokens
, ",", &saved_ptr
);
35 while (token
!= NULL
) {
36 if (!strcmp(token
, "perf_event")) {
40 token
= strtok_r(NULL
, ",", &saved_ptr
);
50 if (strlen(mountpoint
) < maxlen
) {
51 strcpy(buf
, mountpoint
);
57 static int open_cgroup(char *name
)
59 char path
[PATH_MAX
+ 1];
60 char mnt
[PATH_MAX
+ 1];
64 if (cgroupfs_find_mountpoint(mnt
, PATH_MAX
+ 1))
67 snprintf(path
, PATH_MAX
, "%s/%s", mnt
, name
);
69 fd
= open(path
, O_RDONLY
);
71 fprintf(stderr
, "no access to cgroup %s\n", path
);
76 static int add_cgroup(struct perf_evlist
*evlist
, char *str
)
78 struct perf_evsel
*counter
;
79 struct cgroup_sel
*cgrp
= NULL
;
82 * check if cgrp is already defined, if so we reuse it
84 evlist__for_each_entry(evlist
, counter
) {
88 if (!strcmp(cgrp
->name
, str
))
95 cgrp
= zalloc(sizeof(*cgrp
));
101 cgrp
->fd
= open_cgroup(str
);
102 if (cgrp
->fd
== -1) {
109 * find corresponding event
110 * if add cgroup N, then need to find event N
113 evlist__for_each_entry(evlist
, counter
) {
118 if (atomic_read(&cgrp
->refcnt
) == 0)
123 atomic_inc(&cgrp
->refcnt
);
124 counter
->cgrp
= cgrp
;
128 void close_cgroup(struct cgroup_sel
*cgrp
)
130 if (cgrp
&& atomic_dec_and_test(&cgrp
->refcnt
)) {
137 int parse_cgroups(const struct option
*opt __maybe_unused
, const char *str
,
138 int unset __maybe_unused
)
140 struct perf_evlist
*evlist
= *(struct perf_evlist
**)opt
->value
;
141 const char *p
, *e
, *eos
= str
+ strlen(str
);
145 if (list_empty(&evlist
->entries
)) {
146 fprintf(stderr
, "must define events before cgroups\n");
151 p
= strchr(str
, ',');
154 /* allow empty cgroups, i.e., skip */
156 /* termination added */
157 s
= strndup(str
, e
- str
);
160 ret
= add_cgroup(evlist
, s
);
166 /* nr_cgroups is increased een for empty cgroups */