Root/
1 | #include <dirent.h> |
2 | #include <limits.h> |
3 | #include <stdbool.h> |
4 | #include <stdlib.h> |
5 | #include <stdio.h> |
6 | #include <sys/types.h> |
7 | #include <sys/stat.h> |
8 | #include <unistd.h> |
9 | #include "strlist.h" |
10 | #include <string.h> |
11 | #include "thread_map.h" |
12 | |
13 | /* Skip "." and ".." directories */ |
14 | static int filter(const struct dirent *dir) |
15 | { |
16 | if (dir->d_name[0] == '.') |
17 | return 0; |
18 | else |
19 | return 1; |
20 | } |
21 | |
22 | struct thread_map *thread_map__new_by_pid(pid_t pid) |
23 | { |
24 | struct thread_map *threads; |
25 | char name[256]; |
26 | int items; |
27 | struct dirent **namelist = NULL; |
28 | int i; |
29 | |
30 | sprintf(name, "/proc/%d/task", pid); |
31 | items = scandir(name, &namelist, filter, NULL); |
32 | if (items <= 0) |
33 | return NULL; |
34 | |
35 | threads = malloc(sizeof(*threads) + sizeof(pid_t) * items); |
36 | if (threads != NULL) { |
37 | for (i = 0; i < items; i++) |
38 | threads->map[i] = atoi(namelist[i]->d_name); |
39 | threads->nr = items; |
40 | } |
41 | |
42 | for (i=0; i<items; i++) |
43 | free(namelist[i]); |
44 | free(namelist); |
45 | |
46 | return threads; |
47 | } |
48 | |
49 | struct thread_map *thread_map__new_by_tid(pid_t tid) |
50 | { |
51 | struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t)); |
52 | |
53 | if (threads != NULL) { |
54 | threads->map[0] = tid; |
55 | threads->nr = 1; |
56 | } |
57 | |
58 | return threads; |
59 | } |
60 | |
61 | struct thread_map *thread_map__new_by_uid(uid_t uid) |
62 | { |
63 | DIR *proc; |
64 | int max_threads = 32, items, i; |
65 | char path[256]; |
66 | struct dirent dirent, *next, **namelist = NULL; |
67 | struct thread_map *threads = malloc(sizeof(*threads) + |
68 | max_threads * sizeof(pid_t)); |
69 | if (threads == NULL) |
70 | goto out; |
71 | |
72 | proc = opendir("/proc"); |
73 | if (proc == NULL) |
74 | goto out_free_threads; |
75 | |
76 | threads->nr = 0; |
77 | |
78 | while (!readdir_r(proc, &dirent, &next) && next) { |
79 | char *end; |
80 | bool grow = false; |
81 | struct stat st; |
82 | pid_t pid = strtol(dirent.d_name, &end, 10); |
83 | |
84 | if (*end) /* only interested in proper numerical dirents */ |
85 | continue; |
86 | |
87 | snprintf(path, sizeof(path), "/proc/%s", dirent.d_name); |
88 | |
89 | if (stat(path, &st) != 0) |
90 | continue; |
91 | |
92 | if (st.st_uid != uid) |
93 | continue; |
94 | |
95 | snprintf(path, sizeof(path), "/proc/%d/task", pid); |
96 | items = scandir(path, &namelist, filter, NULL); |
97 | if (items <= 0) |
98 | goto out_free_closedir; |
99 | |
100 | while (threads->nr + items >= max_threads) { |
101 | max_threads *= 2; |
102 | grow = true; |
103 | } |
104 | |
105 | if (grow) { |
106 | struct thread_map *tmp; |
107 | |
108 | tmp = realloc(threads, (sizeof(*threads) + |
109 | max_threads * sizeof(pid_t))); |
110 | if (tmp == NULL) |
111 | goto out_free_namelist; |
112 | |
113 | threads = tmp; |
114 | } |
115 | |
116 | for (i = 0; i < items; i++) |
117 | threads->map[threads->nr + i] = atoi(namelist[i]->d_name); |
118 | |
119 | for (i = 0; i < items; i++) |
120 | free(namelist[i]); |
121 | free(namelist); |
122 | |
123 | threads->nr += items; |
124 | } |
125 | |
126 | out_closedir: |
127 | closedir(proc); |
128 | out: |
129 | return threads; |
130 | |
131 | out_free_threads: |
132 | free(threads); |
133 | return NULL; |
134 | |
135 | out_free_namelist: |
136 | for (i = 0; i < items; i++) |
137 | free(namelist[i]); |
138 | free(namelist); |
139 | |
140 | out_free_closedir: |
141 | free(threads); |
142 | threads = NULL; |
143 | goto out_closedir; |
144 | } |
145 | |
146 | struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid) |
147 | { |
148 | if (pid != -1) |
149 | return thread_map__new_by_pid(pid); |
150 | |
151 | if (tid == -1 && uid != UINT_MAX) |
152 | return thread_map__new_by_uid(uid); |
153 | |
154 | return thread_map__new_by_tid(tid); |
155 | } |
156 | |
157 | static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) |
158 | { |
159 | struct thread_map *threads = NULL, *nt; |
160 | char name[256]; |
161 | int items, total_tasks = 0; |
162 | struct dirent **namelist = NULL; |
163 | int i, j = 0; |
164 | pid_t pid, prev_pid = INT_MAX; |
165 | char *end_ptr; |
166 | struct str_node *pos; |
167 | struct strlist *slist = strlist__new(false, pid_str); |
168 | |
169 | if (!slist) |
170 | return NULL; |
171 | |
172 | strlist__for_each(pos, slist) { |
173 | pid = strtol(pos->s, &end_ptr, 10); |
174 | |
175 | if (pid == INT_MIN || pid == INT_MAX || |
176 | (*end_ptr != '\0' && *end_ptr != ',')) |
177 | goto out_free_threads; |
178 | |
179 | if (pid == prev_pid) |
180 | continue; |
181 | |
182 | sprintf(name, "/proc/%d/task", pid); |
183 | items = scandir(name, &namelist, filter, NULL); |
184 | if (items <= 0) |
185 | goto out_free_threads; |
186 | |
187 | total_tasks += items; |
188 | nt = realloc(threads, (sizeof(*threads) + |
189 | sizeof(pid_t) * total_tasks)); |
190 | if (nt == NULL) |
191 | goto out_free_namelist; |
192 | |
193 | threads = nt; |
194 | |
195 | for (i = 0; i < items; i++) { |
196 | threads->map[j++] = atoi(namelist[i]->d_name); |
197 | free(namelist[i]); |
198 | } |
199 | threads->nr = total_tasks; |
200 | free(namelist); |
201 | } |
202 | |
203 | out: |
204 | strlist__delete(slist); |
205 | return threads; |
206 | |
207 | out_free_namelist: |
208 | for (i = 0; i < items; i++) |
209 | free(namelist[i]); |
210 | free(namelist); |
211 | |
212 | out_free_threads: |
213 | free(threads); |
214 | threads = NULL; |
215 | goto out; |
216 | } |
217 | |
218 | static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) |
219 | { |
220 | struct thread_map *threads = NULL, *nt; |
221 | int ntasks = 0; |
222 | pid_t tid, prev_tid = INT_MAX; |
223 | char *end_ptr; |
224 | struct str_node *pos; |
225 | struct strlist *slist; |
226 | |
227 | /* perf-stat expects threads to be generated even if tid not given */ |
228 | if (!tid_str) { |
229 | threads = malloc(sizeof(*threads) + sizeof(pid_t)); |
230 | if (threads != NULL) { |
231 | threads->map[0] = -1; |
232 | threads->nr = 1; |
233 | } |
234 | return threads; |
235 | } |
236 | |
237 | slist = strlist__new(false, tid_str); |
238 | if (!slist) |
239 | return NULL; |
240 | |
241 | strlist__for_each(pos, slist) { |
242 | tid = strtol(pos->s, &end_ptr, 10); |
243 | |
244 | if (tid == INT_MIN || tid == INT_MAX || |
245 | (*end_ptr != '\0' && *end_ptr != ',')) |
246 | goto out_free_threads; |
247 | |
248 | if (tid == prev_tid) |
249 | continue; |
250 | |
251 | ntasks++; |
252 | nt = realloc(threads, sizeof(*threads) + sizeof(pid_t) * ntasks); |
253 | |
254 | if (nt == NULL) |
255 | goto out_free_threads; |
256 | |
257 | threads = nt; |
258 | threads->map[ntasks - 1] = tid; |
259 | threads->nr = ntasks; |
260 | } |
261 | out: |
262 | return threads; |
263 | |
264 | out_free_threads: |
265 | free(threads); |
266 | threads = NULL; |
267 | goto out; |
268 | } |
269 | |
270 | struct thread_map *thread_map__new_str(const char *pid, const char *tid, |
271 | uid_t uid) |
272 | { |
273 | if (pid) |
274 | return thread_map__new_by_pid_str(pid); |
275 | |
276 | if (!tid && uid != UINT_MAX) |
277 | return thread_map__new_by_uid(uid); |
278 | |
279 | return thread_map__new_by_tid_str(tid); |
280 | } |
281 | |
282 | void thread_map__delete(struct thread_map *threads) |
283 | { |
284 | free(threads); |
285 | } |
286 | |
287 | size_t thread_map__fprintf(struct thread_map *threads, FILE *fp) |
288 | { |
289 | int i; |
290 | size_t printed = fprintf(fp, "%d thread%s: ", |
291 | threads->nr, threads->nr > 1 ? "s" : ""); |
292 | for (i = 0; i < threads->nr; ++i) |
293 | printed += fprintf(fp, "%s%d", i ? ", " : "", threads->map[i]); |
294 | |
295 | return printed + fprintf(fp, "\n"); |
296 | } |
297 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9