]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - tools/perf/util/util.c
Merge 3.16-rc2 into staging-next
[karo-tx-linux.git] / tools / perf / util / util.c
1 #include "../perf.h"
2 #include "util.h"
3 #include <api/fs/fs.h>
4 #include <sys/mman.h>
5 #ifdef HAVE_BACKTRACE_SUPPORT
6 #include <execinfo.h>
7 #endif
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <limits.h>
13 #include <byteswap.h>
14 #include <linux/kernel.h>
15
16 /*
17  * XXX We need to find a better place for these things...
18  */
19 unsigned int page_size;
20 int cacheline_size;
21
22 bool test_attr__enabled;
23
24 bool perf_host  = true;
25 bool perf_guest = false;
26
27 char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
28
29 void event_attr_init(struct perf_event_attr *attr)
30 {
31         if (!perf_host)
32                 attr->exclude_host  = 1;
33         if (!perf_guest)
34                 attr->exclude_guest = 1;
35         /* to capture ABI version */
36         attr->size = sizeof(*attr);
37 }
38
39 int mkdir_p(char *path, mode_t mode)
40 {
41         struct stat st;
42         int err;
43         char *d = path;
44
45         if (*d != '/')
46                 return -1;
47
48         if (stat(path, &st) == 0)
49                 return 0;
50
51         while (*++d == '/');
52
53         while ((d = strchr(d, '/'))) {
54                 *d = '\0';
55                 err = stat(path, &st) && mkdir(path, mode);
56                 *d++ = '/';
57                 if (err)
58                         return -1;
59                 while (*d == '/')
60                         ++d;
61         }
62         return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
63 }
64
65 static int slow_copyfile(const char *from, const char *to, mode_t mode)
66 {
67         int err = -1;
68         char *line = NULL;
69         size_t n;
70         FILE *from_fp = fopen(from, "r"), *to_fp;
71         mode_t old_umask;
72
73         if (from_fp == NULL)
74                 goto out;
75
76         old_umask = umask(mode ^ 0777);
77         to_fp = fopen(to, "w");
78         umask(old_umask);
79         if (to_fp == NULL)
80                 goto out_fclose_from;
81
82         while (getline(&line, &n, from_fp) > 0)
83                 if (fputs(line, to_fp) == EOF)
84                         goto out_fclose_to;
85         err = 0;
86 out_fclose_to:
87         fclose(to_fp);
88         free(line);
89 out_fclose_from:
90         fclose(from_fp);
91 out:
92         return err;
93 }
94
95 int copyfile_mode(const char *from, const char *to, mode_t mode)
96 {
97         int fromfd, tofd;
98         struct stat st;
99         void *addr;
100         int err = -1;
101
102         if (stat(from, &st))
103                 goto out;
104
105         if (st.st_size == 0) /* /proc? do it slowly... */
106                 return slow_copyfile(from, to, mode);
107
108         fromfd = open(from, O_RDONLY);
109         if (fromfd < 0)
110                 goto out;
111
112         tofd = creat(to, mode);
113         if (tofd < 0)
114                 goto out_close_from;
115
116         addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0);
117         if (addr == MAP_FAILED)
118                 goto out_close_to;
119
120         if (write(tofd, addr, st.st_size) == st.st_size)
121                 err = 0;
122
123         munmap(addr, st.st_size);
124 out_close_to:
125         close(tofd);
126         if (err)
127                 unlink(to);
128 out_close_from:
129         close(fromfd);
130 out:
131         return err;
132 }
133
134 int copyfile(const char *from, const char *to)
135 {
136         return copyfile_mode(from, to, 0755);
137 }
138
139 unsigned long convert_unit(unsigned long value, char *unit)
140 {
141         *unit = ' ';
142
143         if (value > 1000) {
144                 value /= 1000;
145                 *unit = 'K';
146         }
147
148         if (value > 1000) {
149                 value /= 1000;
150                 *unit = 'M';
151         }
152
153         if (value > 1000) {
154                 value /= 1000;
155                 *unit = 'G';
156         }
157
158         return value;
159 }
160
161 static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
162 {
163         void *buf_start = buf;
164         size_t left = n;
165
166         while (left) {
167                 ssize_t ret = is_read ? read(fd, buf, left) :
168                                         write(fd, buf, left);
169
170                 if (ret < 0 && errno == EINTR)
171                         continue;
172                 if (ret <= 0)
173                         return ret;
174
175                 left -= ret;
176                 buf  += ret;
177         }
178
179         BUG_ON((size_t)(buf - buf_start) != n);
180         return n;
181 }
182
183 /*
184  * Read exactly 'n' bytes or return an error.
185  */
186 ssize_t readn(int fd, void *buf, size_t n)
187 {
188         return ion(true, fd, buf, n);
189 }
190
191 /*
192  * Write exactly 'n' bytes or return an error.
193  */
194 ssize_t writen(int fd, void *buf, size_t n)
195 {
196         return ion(false, fd, buf, n);
197 }
198
199 size_t hex_width(u64 v)
200 {
201         size_t n = 1;
202
203         while ((v >>= 4))
204                 ++n;
205
206         return n;
207 }
208
209 static int hex(char ch)
210 {
211         if ((ch >= '0') && (ch <= '9'))
212                 return ch - '0';
213         if ((ch >= 'a') && (ch <= 'f'))
214                 return ch - 'a' + 10;
215         if ((ch >= 'A') && (ch <= 'F'))
216                 return ch - 'A' + 10;
217         return -1;
218 }
219
220 /*
221  * While we find nice hex chars, build a long_val.
222  * Return number of chars processed.
223  */
224 int hex2u64(const char *ptr, u64 *long_val)
225 {
226         const char *p = ptr;
227         *long_val = 0;
228
229         while (*p) {
230                 const int hex_val = hex(*p);
231
232                 if (hex_val < 0)
233                         break;
234
235                 *long_val = (*long_val << 4) | hex_val;
236                 p++;
237         }
238
239         return p - ptr;
240 }
241
242 /* Obtain a backtrace and print it to stdout. */
243 #ifdef HAVE_BACKTRACE_SUPPORT
244 void dump_stack(void)
245 {
246         void *array[16];
247         size_t size = backtrace(array, ARRAY_SIZE(array));
248         char **strings = backtrace_symbols(array, size);
249         size_t i;
250
251         printf("Obtained %zd stack frames.\n", size);
252
253         for (i = 0; i < size; i++)
254                 printf("%s\n", strings[i]);
255
256         free(strings);
257 }
258 #else
259 void dump_stack(void) {}
260 #endif
261
262 void get_term_dimensions(struct winsize *ws)
263 {
264         char *s = getenv("LINES");
265
266         if (s != NULL) {
267                 ws->ws_row = atoi(s);
268                 s = getenv("COLUMNS");
269                 if (s != NULL) {
270                         ws->ws_col = atoi(s);
271                         if (ws->ws_row && ws->ws_col)
272                                 return;
273                 }
274         }
275 #ifdef TIOCGWINSZ
276         if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
277             ws->ws_row && ws->ws_col)
278                 return;
279 #endif
280         ws->ws_row = 25;
281         ws->ws_col = 80;
282 }
283
284 static void set_tracing_events_path(const char *mountpoint)
285 {
286         snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
287                  mountpoint, "tracing/events");
288 }
289
290 const char *perf_debugfs_mount(const char *mountpoint)
291 {
292         const char *mnt;
293
294         mnt = debugfs_mount(mountpoint);
295         if (!mnt)
296                 return NULL;
297
298         set_tracing_events_path(mnt);
299
300         return mnt;
301 }
302
303 void perf_debugfs_set_path(const char *mntpt)
304 {
305         snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt);
306         set_tracing_events_path(mntpt);
307 }
308
309 static const char *find_debugfs(void)
310 {
311         const char *path = perf_debugfs_mount(NULL);
312
313         if (!path)
314                 fprintf(stderr, "Your kernel does not support the debugfs filesystem");
315
316         return path;
317 }
318
319 /*
320  * Finds the path to the debugfs/tracing
321  * Allocates the string and stores it.
322  */
323 const char *find_tracing_dir(void)
324 {
325         static char *tracing;
326         static int tracing_found;
327         const char *debugfs;
328
329         if (tracing_found)
330                 return tracing;
331
332         debugfs = find_debugfs();
333         if (!debugfs)
334                 return NULL;
335
336         tracing = malloc(strlen(debugfs) + 9);
337         if (!tracing)
338                 return NULL;
339
340         sprintf(tracing, "%s/tracing", debugfs);
341
342         tracing_found = 1;
343         return tracing;
344 }
345
346 char *get_tracing_file(const char *name)
347 {
348         const char *tracing;
349         char *file;
350
351         tracing = find_tracing_dir();
352         if (!tracing)
353                 return NULL;
354
355         file = malloc(strlen(tracing) + strlen(name) + 2);
356         if (!file)
357                 return NULL;
358
359         sprintf(file, "%s/%s", tracing, name);
360         return file;
361 }
362
363 void put_tracing_file(char *file)
364 {
365         free(file);
366 }
367
368 int parse_nsec_time(const char *str, u64 *ptime)
369 {
370         u64 time_sec, time_nsec;
371         char *end;
372
373         time_sec = strtoul(str, &end, 10);
374         if (*end != '.' && *end != '\0')
375                 return -1;
376
377         if (*end == '.') {
378                 int i;
379                 char nsec_buf[10];
380
381                 if (strlen(++end) > 9)
382                         return -1;
383
384                 strncpy(nsec_buf, end, 9);
385                 nsec_buf[9] = '\0';
386
387                 /* make it nsec precision */
388                 for (i = strlen(nsec_buf); i < 9; i++)
389                         nsec_buf[i] = '0';
390
391                 time_nsec = strtoul(nsec_buf, &end, 10);
392                 if (*end != '\0')
393                         return -1;
394         } else
395                 time_nsec = 0;
396
397         *ptime = time_sec * NSEC_PER_SEC + time_nsec;
398         return 0;
399 }
400
401 unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
402 {
403         struct parse_tag *i = tags;
404
405         while (i->tag) {
406                 char *s;
407
408                 s = strchr(str, i->tag);
409                 if (s) {
410                         unsigned long int value;
411                         char *endptr;
412
413                         value = strtoul(str, &endptr, 10);
414                         if (s != endptr)
415                                 break;
416
417                         if (value > ULONG_MAX / i->mult)
418                                 break;
419                         value *= i->mult;
420                         return value;
421                 }
422                 i++;
423         }
424
425         return (unsigned long) -1;
426 }
427
428 int filename__read_int(const char *filename, int *value)
429 {
430         char line[64];
431         int fd = open(filename, O_RDONLY), err = -1;
432
433         if (fd < 0)
434                 return -1;
435
436         if (read(fd, line, sizeof(line)) > 0) {
437                 *value = atoi(line);
438                 err = 0;
439         }
440
441         close(fd);
442         return err;
443 }
444
445 int filename__read_str(const char *filename, char **buf, size_t *sizep)
446 {
447         size_t size = 0, alloc_size = 0;
448         void *bf = NULL, *nbf;
449         int fd, n, err = 0;
450
451         fd = open(filename, O_RDONLY);
452         if (fd < 0)
453                 return -errno;
454
455         do {
456                 if (size == alloc_size) {
457                         alloc_size += BUFSIZ;
458                         nbf = realloc(bf, alloc_size);
459                         if (!nbf) {
460                                 err = -ENOMEM;
461                                 break;
462                         }
463
464                         bf = nbf;
465                 }
466
467                 n = read(fd, bf + size, alloc_size - size);
468                 if (n < 0) {
469                         if (size) {
470                                 pr_warning("read failed %d: %s\n",
471                                            errno, strerror(errno));
472                                 err = 0;
473                         } else
474                                 err = -errno;
475
476                         break;
477                 }
478
479                 size += n;
480         } while (n > 0);
481
482         if (!err) {
483                 *sizep = size;
484                 *buf   = bf;
485         } else
486                 free(bf);
487
488         close(fd);
489         return err;
490 }
491
492 const char *get_filename_for_perf_kvm(void)
493 {
494         const char *filename;
495
496         if (perf_host && !perf_guest)
497                 filename = strdup("perf.data.host");
498         else if (!perf_host && perf_guest)
499                 filename = strdup("perf.data.guest");
500         else
501                 filename = strdup("perf.data.kvm");
502
503         return filename;
504 }
505
506 int perf_event_paranoid(void)
507 {
508         char path[PATH_MAX];
509         const char *procfs = procfs__mountpoint();
510         int value;
511
512         if (!procfs)
513                 return INT_MAX;
514
515         scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs);
516
517         if (filename__read_int(path, &value))
518                 return INT_MAX;
519
520         return value;
521 }
522
523 void mem_bswap_32(void *src, int byte_size)
524 {
525         u32 *m = src;
526         while (byte_size > 0) {
527                 *m = bswap_32(*m);
528                 byte_size -= sizeof(u32);
529                 ++m;
530         }
531 }
532
533 void mem_bswap_64(void *src, int byte_size)
534 {
535         u64 *m = src;
536
537         while (byte_size > 0) {
538                 *m = bswap_64(*m);
539                 byte_size -= sizeof(u64);
540                 ++m;
541         }
542 }