diff options
Diffstat (limited to 'tools/perf/util/util.c')
| -rw-r--r-- | tools/perf/util/util.c | 205 | 
1 files changed, 192 insertions, 13 deletions
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 6d17b18e915..95aefa78bb0 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -1,16 +1,23 @@  #include "../perf.h"  #include "util.h" +#include <api/fs/fs.h>  #include <sys/mman.h> -#ifdef BACKTRACE_SUPPORT +#ifdef HAVE_BACKTRACE_SUPPORT  #include <execinfo.h>  #endif  #include <stdio.h>  #include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <limits.h> +#include <byteswap.h> +#include <linux/kernel.h>  /*   * XXX We need to find a better place for these things...   */  unsigned int page_size; +int cacheline_size;  bool test_attr__enabled; @@ -55,17 +62,20 @@ int mkdir_p(char *path, mode_t mode)  	return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;  } -static int slow_copyfile(const char *from, const char *to) +static int slow_copyfile(const char *from, const char *to, mode_t mode)  { -	int err = 0; +	int err = -1;  	char *line = NULL;  	size_t n;  	FILE *from_fp = fopen(from, "r"), *to_fp; +	mode_t old_umask;  	if (from_fp == NULL)  		goto out; +	old_umask = umask(mode ^ 0777);  	to_fp = fopen(to, "w"); +	umask(old_umask);  	if (to_fp == NULL)  		goto out_fclose_from; @@ -82,7 +92,7 @@ out:  	return err;  } -int copyfile(const char *from, const char *to) +int copyfile_mode(const char *from, const char *to, mode_t mode)  {  	int fromfd, tofd;  	struct stat st; @@ -93,13 +103,13 @@ int copyfile(const char *from, const char *to)  		goto out;  	if (st.st_size == 0) /* /proc? do it slowly... */ -		return slow_copyfile(from, to); +		return slow_copyfile(from, to, mode);  	fromfd = open(from, O_RDONLY);  	if (fromfd < 0)  		goto out; -	tofd = creat(to, 0755); +	tofd = creat(to, mode);  	if (tofd < 0)  		goto out_close_from; @@ -121,6 +131,11 @@ out:  	return err;  } +int copyfile(const char *from, const char *to) +{ +	return copyfile_mode(from, to, 0755); +} +  unsigned long convert_unit(unsigned long value, char *unit)  {  	*unit = ' '; @@ -143,21 +158,42 @@ unsigned long convert_unit(unsigned long value, char *unit)  	return value;  } -int readn(int fd, void *buf, size_t n) +static ssize_t ion(bool is_read, int fd, void *buf, size_t n)  {  	void *buf_start = buf; +	size_t left = n; -	while (n) { -		int ret = read(fd, buf, n); +	while (left) { +		ssize_t ret = is_read ? read(fd, buf, left) : +					write(fd, buf, left); +		if (ret < 0 && errno == EINTR) +			continue;  		if (ret <= 0)  			return ret; -		n -= ret; -		buf += ret; +		left -= ret; +		buf  += ret;  	} -	return buf - buf_start; +	BUG_ON((size_t)(buf - buf_start) != n); +	return n; +} + +/* + * Read exactly 'n' bytes or return an error. + */ +ssize_t readn(int fd, void *buf, size_t n) +{ +	return ion(true, fd, buf, n); +} + +/* + * Write exactly 'n' bytes or return an error. + */ +ssize_t writen(int fd, void *buf, size_t n) +{ +	return ion(false, fd, buf, n);  }  size_t hex_width(u64 v) @@ -204,7 +240,7 @@ int hex2u64(const char *ptr, u64 *long_val)  }  /* Obtain a backtrace and print it to stdout. */ -#ifdef BACKTRACE_SUPPORT +#ifdef HAVE_BACKTRACE_SUPPORT  void dump_stack(void)  {  	void *array[16]; @@ -361,3 +397,146 @@ int parse_nsec_time(const char *str, u64 *ptime)  	*ptime = time_sec * NSEC_PER_SEC + time_nsec;  	return 0;  } + +unsigned long parse_tag_value(const char *str, struct parse_tag *tags) +{ +	struct parse_tag *i = tags; + +	while (i->tag) { +		char *s; + +		s = strchr(str, i->tag); +		if (s) { +			unsigned long int value; +			char *endptr; + +			value = strtoul(str, &endptr, 10); +			if (s != endptr) +				break; + +			if (value > ULONG_MAX / i->mult) +				break; +			value *= i->mult; +			return value; +		} +		i++; +	} + +	return (unsigned long) -1; +} + +int filename__read_int(const char *filename, int *value) +{ +	char line[64]; +	int fd = open(filename, O_RDONLY), err = -1; + +	if (fd < 0) +		return -1; + +	if (read(fd, line, sizeof(line)) > 0) { +		*value = atoi(line); +		err = 0; +	} + +	close(fd); +	return err; +} + +int filename__read_str(const char *filename, char **buf, size_t *sizep) +{ +	size_t size = 0, alloc_size = 0; +	void *bf = NULL, *nbf; +	int fd, n, err = 0; + +	fd = open(filename, O_RDONLY); +	if (fd < 0) +		return -errno; + +	do { +		if (size == alloc_size) { +			alloc_size += BUFSIZ; +			nbf = realloc(bf, alloc_size); +			if (!nbf) { +				err = -ENOMEM; +				break; +			} + +			bf = nbf; +		} + +		n = read(fd, bf + size, alloc_size - size); +		if (n < 0) { +			if (size) { +				pr_warning("read failed %d: %s\n", +					   errno, strerror(errno)); +				err = 0; +			} else +				err = -errno; + +			break; +		} + +		size += n; +	} while (n > 0); + +	if (!err) { +		*sizep = size; +		*buf   = bf; +	} else +		free(bf); + +	close(fd); +	return err; +} + +const char *get_filename_for_perf_kvm(void) +{ +	const char *filename; + +	if (perf_host && !perf_guest) +		filename = strdup("perf.data.host"); +	else if (!perf_host && perf_guest) +		filename = strdup("perf.data.guest"); +	else +		filename = strdup("perf.data.kvm"); + +	return filename; +} + +int perf_event_paranoid(void) +{ +	char path[PATH_MAX]; +	const char *procfs = procfs__mountpoint(); +	int value; + +	if (!procfs) +		return INT_MAX; + +	scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs); + +	if (filename__read_int(path, &value)) +		return INT_MAX; + +	return value; +} + +void mem_bswap_32(void *src, int byte_size) +{ +	u32 *m = src; +	while (byte_size > 0) { +		*m = bswap_32(*m); +		byte_size -= sizeof(u32); +		++m; +	} +} + +void mem_bswap_64(void *src, int byte_size) +{ +	u64 *m = src; + +	while (byte_size > 0) { +		*m = bswap_64(*m); +		byte_size -= sizeof(u64); +		++m; +	} +}  | 
