diff options
Diffstat (limited to 'tools')
62 files changed, 1655 insertions, 1026 deletions
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 5a1f6489d185..ca9fa4d32e07 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -127,7 +127,8 @@ static void kvp_acquire_lock(int pool) fl.l_pid = getpid(); if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) { - syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool); + syslog(LOG_ERR, "Failed to acquire the lock pool: %d; error: %d %s", pool, + errno, strerror(errno)); exit(EXIT_FAILURE); } } @@ -138,8 +139,8 @@ static void kvp_release_lock(int pool) fl.l_pid = getpid(); if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) { - perror("fcntl"); - syslog(LOG_ERR, "Failed to release the lock pool: %d", pool); + syslog(LOG_ERR, "Failed to release the lock pool: %d; error: %d %s", pool, + errno, strerror(errno)); exit(EXIT_FAILURE); } } @@ -157,8 +158,9 @@ static void kvp_update_file(int pool) filep = fopen(kvp_file_info[pool].fname, "we"); if (!filep) { + syslog(LOG_ERR, "Failed to open file, pool: %d; error: %d %s", pool, + errno, strerror(errno)); kvp_release_lock(pool); - syslog(LOG_ERR, "Failed to open file, pool: %d", pool); exit(EXIT_FAILURE); } @@ -188,8 +190,9 @@ static void kvp_update_mem_state(int pool) filep = fopen(kvp_file_info[pool].fname, "re"); if (!filep) { + syslog(LOG_ERR, "Failed to open file, pool: %d; error: %d %s", pool, + errno, strerror(errno)); kvp_release_lock(pool); - syslog(LOG_ERR, "Failed to open file, pool: %d", pool); exit(EXIT_FAILURE); } for (;;) { @@ -240,7 +243,8 @@ static int kvp_file_init(void) if (access(KVP_CONFIG_LOC, F_OK)) { if (mkdir(KVP_CONFIG_LOC, 0755 /* rwxr-xr-x */)) { - syslog(LOG_ERR, " Failed to create %s", KVP_CONFIG_LOC); + syslog(LOG_ERR, "Failed to create '%s'; error: %d %s", KVP_CONFIG_LOC, + errno, strerror(errno)); exit(EXIT_FAILURE); } } @@ -257,12 +261,15 @@ static int kvp_file_init(void) filep = fopen(fname, "re"); - if (!filep) + if (!filep) { + close(fd); return 1; + } record = malloc(alloc_unit * num_blocks); if (record == NULL) { fclose(filep); + close(fd); return 1; } for (;;) { @@ -286,6 +293,7 @@ static int kvp_file_init(void) num_blocks); if (record == NULL) { fclose(filep); + close(fd); return 1; } continue; @@ -765,7 +773,9 @@ static void kvp_process_ipconfig_file(char *cmd, break; x = strchr(p, '\n'); - *x = '\0'; + if (x) + *x = '\0'; + strcat(config_buf, p); strcat(config_buf, ";"); } @@ -1274,7 +1284,8 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) file = fopen(if_file, "w"); if (file == NULL) { - syslog(LOG_ERR, "Failed to open config file"); + syslog(LOG_ERR, "Failed to open config file; error: %d %s", + errno, strerror(errno)); return HV_E_FAIL; } @@ -1441,7 +1452,8 @@ int main(void) fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (fd < 0) { - syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); + syslog(LOG_ERR, "netlink socket creation failed; error: %d %s", errno, + strerror(errno)); exit(EXIT_FAILURE); } addr.nl_family = AF_NETLINK; @@ -1452,12 +1464,18 @@ int main(void) error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); if (error < 0) { - syslog(LOG_ERR, "bind failed; error:%d", error); + syslog(LOG_ERR, "bind failed; error: %d %s", errno, strerror(errno)); close(fd); exit(EXIT_FAILURE); } nl_group = CN_KVP_IDX; - setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)); + + if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)) < 0) { + syslog(LOG_ERR, "setsockopt failed; error: %d %s", errno, strerror(errno)); + close(fd); + exit(EXIT_FAILURE); + } + /* * Register ourselves with the kernel. */ @@ -1472,7 +1490,7 @@ int main(void) len = netlink_send(fd, message); if (len < 0) { - syslog(LOG_ERR, "netlink_send failed; error:%d", len); + syslog(LOG_ERR, "netlink_send failed; error: %d %s", errno, strerror(errno)); close(fd); exit(EXIT_FAILURE); } @@ -1484,7 +1502,16 @@ int main(void) socklen_t addr_l = sizeof(addr); pfd.events = POLLIN; pfd.revents = 0; - poll(&pfd, 1, -1); + + if (poll(&pfd, 1, -1) < 0) { + syslog(LOG_ERR, "poll failed; error: %d %s", errno, strerror(errno)); + if (errno == EINVAL) { + close(fd); + exit(EXIT_FAILURE); + } + else + continue; + } len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0, addr_p, &addr_l); @@ -1695,7 +1722,8 @@ kvp_done: len = netlink_send(fd, incoming_cn_msg); if (len < 0) { - syslog(LOG_ERR, "net_link send failed; error:%d", len); + syslog(LOG_ERR, "net_link send failed; error: %d %s", errno, + strerror(errno)); exit(EXIT_FAILURE); } } diff --git a/tools/include/tools/be_byteshift.h b/tools/include/tools/be_byteshift.h index f4912e2668ba..84c17d836578 100644 --- a/tools/include/tools/be_byteshift.h +++ b/tools/include/tools/be_byteshift.h @@ -1,68 +1,68 @@ #ifndef _TOOLS_BE_BYTESHIFT_H #define _TOOLS_BE_BYTESHIFT_H -#include <linux/types.h> +#include <stdint.h> -static inline __u16 __get_unaligned_be16(const __u8 *p) +static inline uint16_t __get_unaligned_be16(const uint8_t *p) { return p[0] << 8 | p[1]; } -static inline __u32 __get_unaligned_be32(const __u8 *p) +static inline uint32_t __get_unaligned_be32(const uint8_t *p) { return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; } -static inline __u64 __get_unaligned_be64(const __u8 *p) +static inline uint64_t __get_unaligned_be64(const uint8_t *p) { - return (__u64)__get_unaligned_be32(p) << 32 | + return (uint64_t)__get_unaligned_be32(p) << 32 | __get_unaligned_be32(p + 4); } -static inline void __put_unaligned_be16(__u16 val, __u8 *p) +static inline void __put_unaligned_be16(uint16_t val, uint8_t *p) { *p++ = val >> 8; *p++ = val; } -static inline void __put_unaligned_be32(__u32 val, __u8 *p) +static inline void __put_unaligned_be32(uint32_t val, uint8_t *p) { __put_unaligned_be16(val >> 16, p); __put_unaligned_be16(val, p + 2); } -static inline void __put_unaligned_be64(__u64 val, __u8 *p) +static inline void __put_unaligned_be64(uint64_t val, uint8_t *p) { __put_unaligned_be32(val >> 32, p); __put_unaligned_be32(val, p + 4); } -static inline __u16 get_unaligned_be16(const void *p) +static inline uint16_t get_unaligned_be16(const void *p) { - return __get_unaligned_be16((const __u8 *)p); + return __get_unaligned_be16((const uint8_t *)p); } -static inline __u32 get_unaligned_be32(const void *p) +static inline uint32_t get_unaligned_be32(const void *p) { - return __get_unaligned_be32((const __u8 *)p); + return __get_unaligned_be32((const uint8_t *)p); } -static inline __u64 get_unaligned_be64(const void *p) +static inline uint64_t get_unaligned_be64(const void *p) { - return __get_unaligned_be64((const __u8 *)p); + return __get_unaligned_be64((const uint8_t *)p); } -static inline void put_unaligned_be16(__u16 val, void *p) +static inline void put_unaligned_be16(uint16_t val, void *p) { __put_unaligned_be16(val, p); } -static inline void put_unaligned_be32(__u32 val, void *p) +static inline void put_unaligned_be32(uint32_t val, void *p) { __put_unaligned_be32(val, p); } -static inline void put_unaligned_be64(__u64 val, void *p) +static inline void put_unaligned_be64(uint64_t val, void *p) { __put_unaligned_be64(val, p); } diff --git a/tools/include/tools/le_byteshift.h b/tools/include/tools/le_byteshift.h index c99d45a68bda..8fe9f2488ec7 100644 --- a/tools/include/tools/le_byteshift.h +++ b/tools/include/tools/le_byteshift.h @@ -1,68 +1,68 @@ #ifndef _TOOLS_LE_BYTESHIFT_H #define _TOOLS_LE_BYTESHIFT_H -#include <linux/types.h> +#include <stdint.h> -static inline __u16 __get_unaligned_le16(const __u8 *p) +static inline uint16_t __get_unaligned_le16(const uint8_t *p) { return p[0] | p[1] << 8; } -static inline __u32 __get_unaligned_le32(const __u8 *p) +static inline uint32_t __get_unaligned_le32(const uint8_t *p) { return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; } -static inline __u64 __get_unaligned_le64(const __u8 *p) +static inline uint64_t __get_unaligned_le64(const uint8_t *p) { - return (__u64)__get_unaligned_le32(p + 4) << 32 | + return (uint64_t)__get_unaligned_le32(p + 4) << 32 | __get_unaligned_le32(p); } -static inline void __put_unaligned_le16(__u16 val, __u8 *p) +static inline void __put_unaligned_le16(uint16_t val, uint8_t *p) { *p++ = val; *p++ = val >> 8; } -static inline void __put_unaligned_le32(__u32 val, __u8 *p) +static inline void __put_unaligned_le32(uint32_t val, uint8_t *p) { __put_unaligned_le16(val >> 16, p + 2); __put_unaligned_le16(val, p); } -static inline void __put_unaligned_le64(__u64 val, __u8 *p) +static inline void __put_unaligned_le64(uint64_t val, uint8_t *p) { __put_unaligned_le32(val >> 32, p + 4); __put_unaligned_le32(val, p); } -static inline __u16 get_unaligned_le16(const void *p) +static inline uint16_t get_unaligned_le16(const void *p) { - return __get_unaligned_le16((const __u8 *)p); + return __get_unaligned_le16((const uint8_t *)p); } -static inline __u32 get_unaligned_le32(const void *p) +static inline uint32_t get_unaligned_le32(const void *p) { - return __get_unaligned_le32((const __u8 *)p); + return __get_unaligned_le32((const uint8_t *)p); } -static inline __u64 get_unaligned_le64(const void *p) +static inline uint64_t get_unaligned_le64(const void *p) { - return __get_unaligned_le64((const __u8 *)p); + return __get_unaligned_le64((const uint8_t *)p); } -static inline void put_unaligned_le16(__u16 val, void *p) +static inline void put_unaligned_le16(uint16_t val, void *p) { __put_unaligned_le16(val, p); } -static inline void put_unaligned_le32(__u32 val, void *p) +static inline void put_unaligned_le32(uint32_t val, void *p) { __put_unaligned_le32(val, p); } -static inline void put_unaligned_le64(__u64 val, void *p) +static inline void put_unaligned_le64(uint64_t val, void *p) { __put_unaligned_le64(val, p); } diff --git a/tools/lguest/Makefile b/tools/lguest/Makefile index 0ac34206f7a7..97bca4871ea3 100644 --- a/tools/lguest/Makefile +++ b/tools/lguest/Makefile @@ -1,5 +1,4 @@ # This creates the demonstration utility "lguest" which runs a Linux guest. -# Missing headers? Add "-I../../../include -I../../../arch/x86/include" CFLAGS:=-m32 -Wall -Wmissing-declarations -Wmissing-prototypes -O3 -U_FORTIFY_SOURCE all: lguest diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c index 07a03452c227..68f67cf3d318 100644 --- a/tools/lguest/lguest.c +++ b/tools/lguest/lguest.c @@ -42,14 +42,6 @@ #include <pwd.h> #include <grp.h> -#include <linux/virtio_config.h> -#include <linux/virtio_net.h> -#include <linux/virtio_blk.h> -#include <linux/virtio_console.h> -#include <linux/virtio_rng.h> -#include <linux/virtio_ring.h> -#include <asm/bootparam.h> -#include "../../include/linux/lguest_launcher.h" /*L:110 * We can ignore the 43 include files we need for this program, but I do want * to draw attention to the use of kernel-style types. @@ -65,6 +57,15 @@ typedef uint16_t u16; typedef uint8_t u8; /*:*/ +#include <linux/virtio_config.h> +#include <linux/virtio_net.h> +#include <linux/virtio_blk.h> +#include <linux/virtio_console.h> +#include <linux/virtio_rng.h> +#include <linux/virtio_ring.h> +#include <asm/bootparam.h> +#include "../../include/linux/lguest_launcher.h" + #define BRIDGE_PFX "bridge:" #ifndef SIOCBRADDIF #define SIOCBRADDIF 0x89a2 /* add interface to bridge */ @@ -177,7 +178,8 @@ static struct termios orig_term; * in precise order. */ #define wmb() __asm__ __volatile__("" : : : "memory") -#define mb() __asm__ __volatile__("" : : : "memory") +#define rmb() __asm__ __volatile__("lock; addl $0,0(%%esp)" : : : "memory") +#define mb() __asm__ __volatile__("lock; addl $0,0(%%esp)" : : : "memory") /* Wrapper for the last available index. Makes it easier to change. */ #define lg_last_avail(vq) ((vq)->last_avail_idx) @@ -676,6 +678,12 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq, errx(1, "Guest moved used index from %u to %u", last_avail, vq->vring.avail->idx); + /* + * Make sure we read the descriptor number *after* we read the ring + * update; don't let the cpu or compiler change the order. + */ + rmb(); + /* * Grab the next descriptor number they're advertising, and increment * the index we've seen. @@ -695,6 +703,12 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq, i = head; /* + * We have to read the descriptor after we read the descriptor number, + * but there's a data dependency there so the CPU shouldn't reorder + * that: no rmb() required. + */ + + /* * If this is an indirect entry, then this buffer contains a descriptor * table which we handle as if it's any normal descriptor chain. */ diff --git a/tools/lib/lk/Makefile b/tools/lib/lk/Makefile index 926cbf3efc7f..2c5a19733357 100644 --- a/tools/lib/lk/Makefile +++ b/tools/lib/lk/Makefile @@ -1,5 +1,8 @@ include ../../scripts/Makefile.include +CC = $(CROSS_COMPILE)gcc +AR = $(CROSS_COMPILE)ar + # guard against environment variables LIB_H= LIB_OBJS= diff --git a/tools/perf/Documentation/perf-archive.txt b/tools/perf/Documentation/perf-archive.txt index fae174dc7d01..5032a142853e 100644 --- a/tools/perf/Documentation/perf-archive.txt +++ b/tools/perf/Documentation/perf-archive.txt @@ -13,7 +13,7 @@ SYNOPSIS DESCRIPTION ----------- This command runs runs perf-buildid-list --with-hits, and collects the files -with the buildids found so that analisys of perf.data contents can be possible +with the buildids found so that analysis of perf.data contents can be possible on another machine. diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 7d5f4f38aa52..66dab7410c1d 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -210,6 +210,10 @@ OPTIONS Demangle symbol names to human readable form. It's enabled by default, disable with --no-demangle. +--percent-limit:: + Do not show entries which have an overhead under that percent. + (Default: 0). + SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-annotate[1] diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index 9f1a2fe54757..7fdd1909e376 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt @@ -155,6 +155,10 @@ Default is to monitor all CPUS. Default: fractal,0.5,callee. +--percent-limit:: + Do not show entries which have an overhead under that percent. + (Default: 0). + INTERACTIVE PROMPTING KEYS -------------------------- diff --git a/tools/perf/Makefile b/tools/perf/Makefile index b0f164b133d9..203cb0eecff2 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -51,189 +51,63 @@ include config/utilities.mak # Define NO_BACKTRACE if you do not want stack backtrace debug feature # # Define NO_LIBNUMA if you do not want numa perf benchmark +# +# Define NO_LIBAUDIT if you do not want libaudit support +# +# Define NO_LIBBIONIC if you do not want bionic support -$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE - @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) - -uname_M := $(shell uname -m 2>/dev/null || echo not) - -ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ - -e s/arm.*/arm/ -e s/sa110/arm/ \ - -e s/s390x/s390/ -e s/parisc64/parisc/ \ - -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ - -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ ) -NO_PERF_REGS := 1 - -CC = $(CROSS_COMPILE)gcc -AR = $(CROSS_COMPILE)ar - -# Additional ARCH settings for x86 -ifeq ($(ARCH),i386) - override ARCH := x86 - NO_PERF_REGS := 0 - LIBUNWIND_LIBS = -lunwind -lunwind-x86 -endif -ifeq ($(ARCH),x86_64) - override ARCH := x86 - IS_X86_64 := 0 - ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) - IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) - endif - ifeq (${IS_X86_64}, 1) - RAW_ARCH := x86_64 - ARCH_CFLAGS := -DARCH_X86_64 - ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S - endif - NO_PERF_REGS := 0 - LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 -endif - -# Treat warnings as errors unless directed not to -ifneq ($(WERROR),0) - CFLAGS_WERROR := -Werror -endif - -ifeq ("$(origin DEBUG)", "command line") - PERF_DEBUG = $(DEBUG) -endif -ifndef PERF_DEBUG - CFLAGS_OPTIMIZE = -O6 +ifeq ($(srctree),) +srctree := $(patsubst %/,%,$(dir $(shell pwd))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +#$(info Determined 'srctree' to be $(srctree)) endif -ifdef PARSER_DEBUG - PARSER_DEBUG_BISON := -t - PARSER_DEBUG_FLEX := -d - PARSER_DEBUG_CFLAGS := -DPARSER_DEBUG +ifneq ($(objtree),) +#$(info Determined 'objtree' to be $(objtree)) endif -ifdef NO_NEWT - NO_SLANG=1 +ifneq ($(OUTPUT),) +#$(info Determined 'OUTPUT' to be $(OUTPUT)) endif -CFLAGS = -fno-omit-frame-pointer -ggdb3 -funwind-tables -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS) -EXTLIBS = -lpthread -lrt -lelf -lm -ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -ALL_LDFLAGS = $(LDFLAGS) -STRIP ?= strip - -# Among the variables below, these: -# perfexecdir -# template_dir -# mandir -# infodir -# htmldir -# ETC_PERFCONFIG (but not sysconfdir) -# can be specified as a relative path some/where/else; -# this is interpreted as relative to $(prefix) and "perf" at -# runtime figures out where they are based on the path to the executable. -# This can help installing the suite in a relocatable way. - -# Make the path relative to DESTDIR, not to prefix -ifndef DESTDIR -prefix = $(HOME) -endif -bindir_relative = bin -bindir = $(prefix)/$(bindir_relative) -mandir = share/man -infodir = share/info -perfexecdir = libexec/perf-core -sharedir = $(prefix)/share -template_dir = share/perf-core/templates -htmldir = share/doc/perf-doc -ifeq ($(prefix),/usr) -sysconfdir = /etc -ETC_PERFCONFIG = $(sysconfdir)/perfconfig -else -sysconfdir = $(prefix)/etc -ETC_PERFCONFIG = etc/perfconfig -endif -lib = lib +$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE + @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) -export prefix bindir sharedir sysconfdir +CC = $(CROSS_COMPILE)gcc +AR = $(CROSS_COMPILE)ar -RM = rm -f -MKDIR = mkdir -FIND = find +RM = rm -f +MKDIR = mkdir +FIND = find INSTALL = install -FLEX = flex -BISON= bison - -# sparse is architecture-neutral, which means that we need to tell it -# explicitly what architecture to check for. Fix this up for yours.. -SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ - -ifneq ($(MAKECMDGOALS),clean) -ifneq ($(MAKECMDGOALS),tags) --include config/feature-tests.mak - -ifeq ($(call get-executable,$(FLEX)),) - dummy := $(error Error: $(FLEX) is missing on this system, please install it) -endif - -ifeq ($(call get-executable,$(BISON)),) - dummy := $(error Error: $(BISON) is missing on this system, please install it) -endif +FLEX = flex +BISON = bison +STRIP = strip -ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y) - CFLAGS := $(CFLAGS) -fstack-protector-all -endif +LK_DIR = $(srctree)/tools/lib/lk/ +TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ -ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wstack-protector,-Wstack-protector),y) - CFLAGS := $(CFLAGS) -Wstack-protector -endif +# include config/Makefile by default and rule out +# non-config cases +config := 1 -ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var,-Wvolatile-register-var),y) - CFLAGS := $(CFLAGS) -Wvolatile-register-var -endif +NON_CONFIG_TARGETS := clean TAGS tags cscope help -ifndef PERF_DEBUG - ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -D_FORTIFY_SOURCE=2,-D_FORTIFY_SOURCE=2),y) - CFLAGS := $(CFLAGS) -D_FORTIFY_SOURCE=2 - endif +ifdef MAKECMDGOALS +ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),) + config := 0 endif - -### --- END CONFIGURATION SECTION --- - -ifeq ($(srctree),) -srctree := $(patsubst %/,%,$(dir $(shell pwd))) -srctree := $(patsubst %/,%,$(dir $(srctree))) -#$(info Determined 'srctree' to be $(srctree)) endif -ifneq ($(objtree),) -#$(info Determined 'objtree' to be $(objtree)) +ifeq ($(config),1) +include config/Makefile endif -ifneq ($(OUTPUT),) -#$(info Determined 'OUTPUT' to be $(OUTPUT)) -endif +export prefix bindir sharedir sysconfdir -BASIC_CFLAGS = \ - -Iutil/include \ - -Iarch/$(ARCH)/include \ - $(if $(objtree),-I$(objtree)/arch/$(ARCH)/include/generated/uapi) \ - -I$(srctree)/arch/$(ARCH)/include/uapi \ - -I$(srctree)/arch/$(ARCH)/include \ - $(if $(objtree),-I$(objtree)/include/generated/uapi) \ - -I$(srctree)/include/uapi \ - -I$(srctree)/include \ - -I$(OUTPUT)util \ - -Iutil \ - -I. \ - -I$(TRACE_EVENT_DIR) \ - -I../lib/ \ - -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE - -BASIC_LDFLAGS = - -ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y) - BIONIC := 1 - EXTLIBS := $(filter-out -lrt,$(EXTLIBS)) - EXTLIBS := $(filter-out -lpthread,$(EXTLIBS)) - BASIC_CFLAGS += -I. -endif -endif # MAKECMDGOALS != tags -endif # MAKECMDGOALS != clean +# sparse is architecture-neutral, which means that we need to tell it +# explicitly what architecture to check for. Fix this up for yours.. +SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ # Guard against environment variables BUILTIN_OBJS = @@ -247,20 +121,17 @@ SCRIPT_SH += perf-archive.sh grep-libs = $(filter -l%,$(1)) strip-libs = $(filter-out -l%,$(1)) -LK_DIR = ../lib/lk/ -TRACE_EVENT_DIR = ../lib/traceevent/ - LK_PATH=$(LK_DIR) ifneq ($(OUTPUT),) - TE_PATH=$(OUTPUT) + TE_PATH=$(OUTPUT) ifneq ($(subdir),) - LK_PATH=$(OUTPUT)$(LK_DIR) + LK_PATH=$(OUTPUT)$(LK_DIR) else - LK_PATH=$(OUTPUT) + LK_PATH=$(OUTPUT) endif else - TE_PATH=$(TRACE_EVENT_DIR) + TE_PATH=$(TRACE_EVENT_DIR) endif LIBTRACEEVENT = $(TE_PATH)libtraceevent.a @@ -278,10 +149,10 @@ export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) -PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) +PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBLK) $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) - $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ + $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \ --quiet build_ext; \ mkdir -p $(OUTPUT)python && \ cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/ @@ -296,8 +167,6 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) # PROGRAMS += $(OUTPUT)perf -LANG_BINDINGS = - # what 'all' will build and 'install' will install, in perfexecdir ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) @@ -306,10 +175,10 @@ OTHER_PROGRAMS = $(OUTPUT)perf # Set paths to tools early so that they can be used for version tests. ifndef SHELL_PATH - SHELL_PATH = /bin/sh + SHELL_PATH = /bin/sh endif ifndef PERL_PATH - PERL_PATH = /usr/bin/perl + PERL_PATH = /usr/bin/perl endif export PERL_PATH @@ -557,79 +426,14 @@ BUILTIN_OBJS += $(OUTPUT)builtin-mem.o PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT) -# -# Platform specific tweaks -# -ifneq ($(MAKECMDGOALS),clean) -ifneq ($(MAKECMDGOALS),tags) - # We choose to avoid "if .. else if .. else .. endif endif" # because maintaining the nesting to match is a pain. If # we had "elif" things would have been much nicer... -ifdef NO_LIBELF - NO_DWARF := 1 - NO_DEMANGLE := 1 - NO_LIBUNWIND := 1 -else -FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF),libelf),y) - FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS) - ifeq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC),glibc),y) - LIBC_SUPPORT := 1 - endif - ifeq ($(BIONIC),1) - LIBC_SUPPORT := 1 - endif - ifeq ($(LIBC_SUPPORT),1) - msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev); - - NO_LIBELF := 1 - NO_DWARF := 1 - NO_DEMANGLE := 1 - else - msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); - endif -else - # for linking with debug library, run like: - # make DEBUG=1 LIBDW_DIR=/opt/libdw/ - ifdef LIBDW_DIR - LIBDW_CFLAGS := -I$(LIBDW_DIR)/include - LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib - endif - - FLAGS_DWARF=$(ALL_CFLAGS) $(LIBDW_CFLAGS) -ldw -lelf $(LIBDW_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) - ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y) - msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); - NO_DWARF := 1 - endif # Dwarf support -endif # SOURCE_LIBELF -endif # NO_LIBELF - -# There's only x86 (both 32 and 64) support for CFI unwind so far -ifneq ($(ARCH),x86) - NO_LIBUNWIND := 1 -endif - -ifndef NO_LIBUNWIND -# for linking with debug library, run like: -# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ -ifdef LIBUNWIND_DIR - LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include - LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib -endif - -FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS) -ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND),libunwind),y) - msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99); - NO_LIBUNWIND := 1 -endif # Libunwind support -endif # NO_LIBUNWIND - -include arch/$(ARCH)/Makefile ifneq ($(OUTPUT),) - BASIC_CFLAGS += -I$(OUTPUT) + CFLAGS += -I$(OUTPUT) endif ifdef NO_LIBELF @@ -647,281 +451,74 @@ BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS)) LIB_OBJS += $(OUTPUT)util/symbol-minimal.o else # NO_LIBELF -BASIC_CFLAGS += -DLIBELF_SUPPORT - -FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y) - BASIC_CFLAGS += -DLIBELF_MMAP -endif - ifndef NO_DWARF -ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) - msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); -else - BASIC_CFLAGS := -DDWARF_SUPPORT $(LIBDW_CFLAGS) $(BASIC_CFLAGS) - BASIC_LDFLAGS := $(LIBDW_LDFLAGS) $(BASIC_LDFLAGS) - EXTLIBS += -lelf -ldw - LIB_OBJS += $(OUTPUT)util/probe-finder.o - LIB_OBJS += $(OUTPUT)util/dwarf-aux.o -endif # PERF_HAVE_DWARF_REGS + LIB_OBJS += $(OUTPUT)util/probe-finder.o + LIB_OBJS += $(OUTPUT)util/dwarf-aux.o endif # NO_DWARF endif # NO_LIBELF ifndef NO_LIBUNWIND - BASIC_CFLAGS += -DLIBUNWIND_SUPPORT - EXTLIBS += $(LIBUNWIND_LIBS) - BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS) - BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS) - LIB_OBJS += $(OUTPUT)util/unwind.o + LIB_OBJS += $(OUTPUT)util/unwind.o endif ifndef NO_LIBAUDIT - FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit - ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT),libaudit),y) - msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev); - else - BASIC_CFLAGS += -DLIBAUDIT_SUPPORT - BUILTIN_OBJS += $(OUTPUT)builtin-trace.o - EXTLIBS += -laudit - endif + BUILTIN_OBJS += $(OUTPUT)builtin-trace.o endif ifndef NO_SLANG - FLAGS_SLANG=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -I/usr/include/slang -lslang - ifneq ($(call try-cc,$(SOURCE_SLANG),$(FLAGS_SLANG),libslang),y) - msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev); - else - # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h - BASIC_CFLAGS += -I/usr/include/slang - BASIC_CFLAGS += -DSLANG_SUPPORT - EXTLIBS += -lslang - LIB_OBJS += $(OUTPUT)ui/browser.o - LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o - LIB_OBJS += $(OUTPUT)ui/browsers/hists.o - LIB_OBJS += $(OUTPUT)ui/browsers/map.o - LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o - LIB_OBJS += $(OUTPUT)ui/tui/setup.o - LIB_OBJS += $(OUTPUT)ui/tui/util.o - LIB_OBJS += $(OUTPUT)ui/tui/helpline.o - LIB_OBJS += $(OUTPUT)ui/tui/progress.o - LIB_H += ui/browser.h - LIB_H += ui/browsers/map.h - LIB_H += ui/keysyms.h - LIB_H += ui/libslang.h - endif + LIB_OBJS += $(OUTPUT)ui/browser.o + LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o + LIB_OBJS += $(OUTPUT)ui/browsers/hists.o + LIB_OBJS += $(OUTPUT)ui/browsers/map.o + LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o + LIB_OBJS += $(OUTPUT)ui/tui/setup.o + LIB_OBJS += $(OUTPUT)ui/tui/util.o + LIB_OBJS += $(OUTPUT)ui/tui/helpline.o + LIB_OBJS += $(OUTPUT)ui/tui/progress.o + LIB_H += ui/browser.h + LIB_H += ui/browsers/map.h + LIB_H += ui/keysyms.h + LIB_H += ui/libslang.h endif ifndef NO_GTK2 - FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) - ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2),gtk2),y) - msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); - else - ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2),-DHAVE_GTK_INFO_BAR),y) - BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR - endif - BASIC_CFLAGS += -DGTK2_SUPPORT - BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null) - EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null) - LIB_OBJS += $(OUTPUT)ui/gtk/browser.o - LIB_OBJS += $(OUTPUT)ui/gtk/hists.o - LIB_OBJS += $(OUTPUT)ui/gtk/setup.o - LIB_OBJS += $(OUTPUT)ui/gtk/util.o - LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o - LIB_OBJS += $(OUTPUT)ui/gtk/progress.o - LIB_OBJS += $(OUTPUT)ui/gtk/annotate.o - endif + LIB_OBJS += $(OUTPUT)ui/gtk/browser.o + LIB_OBJS += $(OUTPUT)ui/gtk/hists.o + LIB_OBJS += $(OUTPUT)ui/gtk/setup.o + LIB_OBJS += $(OUTPUT)ui/gtk/util.o + LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o + LIB_OBJS += $(OUTPUT)ui/gtk/progress.o + LIB_OBJS += $(OUTPUT)ui/gtk/annotate.o endif -ifdef NO_LIBPERL - BASIC_CFLAGS += -DNO_LIBPERL -else - PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null) - PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS)) - PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS)) - PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` - FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) - - ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED),perl),y) - BASIC_CFLAGS += -DNO_LIBPERL - else - ALL_LDFLAGS += $(PERL_EMBED_LDFLAGS) - EXTLIBS += $(PERL_EMBED_LIBADD) - LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o - LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o - endif +ifndef NO_LIBPERL + LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o + LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o endif -disable-python = $(eval $(disable-python_code)) -define disable-python_code - BASIC_CFLAGS += -DNO_LIBPYTHON - $(if $(1),$(warning No $(1) was found)) - $(warning Python support will not be built) -endef - -override PYTHON := \ - $(call get-executable-or-default,PYTHON,python) - -ifndef PYTHON - $(call disable-python,python interpreter) -else - - PYTHON_WORD := $(call shell-wordify,$(PYTHON)) - - ifdef NO_LIBPYTHON - $(call disable-python) - else - - override PYTHON_CONFIG := \ - $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON)-config) - - ifndef PYTHON_CONFIG - $(call disable-python,python-config tool) - else - - PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG)) - - PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null) - PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) - PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) - PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) - FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) - - ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED),python),y) - $(call disable-python,Python.h (for Python 2.x)) - else - - ifneq ($(call try-cc,$(SOURCE_PYTHON_VERSION),$(FLAGS_PYTHON_EMBED),python version),y) - $(warning Python 3 is not yet supported; please set) - $(warning PYTHON and/or PYTHON_CONFIG appropriately.) - $(warning If you also have Python 2 installed, then) - $(warning try something like:) - $(warning $(and ,)) - $(warning $(and ,) make PYTHON=python2) - $(warning $(and ,)) - $(warning Otherwise, disable Python support entirely:) - $(warning $(and ,)) - $(warning $(and ,) make NO_LIBPYTHON=1) - $(warning $(and ,)) - $(error $(and ,)) - else - ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS) - EXTLIBS += $(PYTHON_EMBED_LIBADD) - LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o - LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o - LANG_BINDINGS += $(OUTPUT)python/perf.so - endif - - endif - endif - endif -endif - -ifdef NO_DEMANGLE - BASIC_CFLAGS += -DNO_DEMANGLE -else - ifdef HAVE_CPLUS_DEMANGLE - EXTLIBS += -liberty - BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE - else - FLAGS_BFD=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -DPACKAGE='perf' -lbfd - has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD),libbfd) - ifeq ($(has_bfd),y) - EXTLIBS += -lbfd - else - FLAGS_BFD_IBERTY=$(FLAGS_BFD) -liberty - has_bfd_iberty := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY),liberty) - ifeq ($(has_bfd_iberty),y) - EXTLIBS += -lbfd -liberty - else - FLAGS_BFD_IBERTY_Z=$(FLAGS_BFD_IBERTY) -lz - has_bfd_iberty_z := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY_Z),libz) - ifeq ($(has_bfd_iberty_z),y) - EXTLIBS += -lbfd -liberty -lz - else - FLAGS_CPLUS_DEMANGLE=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -liberty - has_cplus_demangle := $(call try-cc,$(SOURCE_CPLUS_DEMANGLE),$(FLAGS_CPLUS_DEMANGLE),demangle) - ifeq ($(has_cplus_demangle),y) - EXTLIBS += -liberty - BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE - else - msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling) - BASIC_CFLAGS += -DNO_DEMANGLE - endif - endif - endif - endif - endif +ifndef NO_LIBPYTHON + LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o + LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o endif ifeq ($(NO_PERF_REGS),0) - ifeq ($(ARCH),x86) - LIB_H += arch/x86/include/perf_regs.h - endif - BASIC_CFLAGS += -DHAVE_PERF_REGS -endif - -ifndef NO_STRLCPY - ifeq ($(call try-cc,$(SOURCE_STRLCPY),,-DHAVE_STRLCPY),y) - BASIC_CFLAGS += -DHAVE_STRLCPY - endif -endif - -ifndef NO_ON_EXIT - ifeq ($(call try-cc,$(SOURCE_ON_EXIT),,-DHAVE_ON_EXIT),y) - BASIC_CFLAGS += -DHAVE_ON_EXIT - endif -endif - -ifndef NO_BACKTRACE - ifeq ($(call try-cc,$(SOURCE_BACKTRACE),,-DBACKTRACE_SUPPORT),y) - BASIC_CFLAGS += -DBACKTRACE_SUPPORT - endif + ifeq ($(ARCH),x86) + LIB_H += arch/x86/include/perf_regs.h + endif endif ifndef NO_LIBNUMA - FLAGS_LIBNUMA = $(ALL_CFLAGS) $(ALL_LDFLAGS) -lnuma - ifneq ($(call try-cc,$(SOURCE_LIBNUMA),$(FLAGS_LIBNUMA),libnuma),y) - msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev); - else - BASIC_CFLAGS += -DLIBNUMA_SUPPORT - BUILTIN_OBJS += $(OUTPUT)bench/numa.o - EXTLIBS += -lnuma - endif + BUILTIN_OBJS += $(OUTPUT)bench/numa.o endif ifdef ASCIIDOC8 - export ASCIIDOC8 + export ASCIIDOC8 endif -endif # MAKECMDGOALS != tags -endif # MAKECMDGOALS != clean - -# Shell quote (do not use $(call) to accommodate ancient setups); - -ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG)) - -DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) -bindir_SQ = $(subst ','\'',$(bindir)) -bindir_relative_SQ = $(subst ','\'',$(bindir_relative)) -mandir_SQ = $(subst ','\'',$(mandir)) -infodir_SQ = $(subst ','\'',$(infodir)) -perfexecdir_SQ = $(subst ','\'',$(perfexecdir)) -template_dir_SQ = $(subst ','\'',$(template_dir)) -htmldir_SQ = $(subst ','\'',$(htmldir)) -prefix_SQ = $(subst ','\'',$(prefix)) -sysconfdir_SQ = $(subst ','\'',$(sysconfdir)) - -SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) - LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group -ALL_CFLAGS += $(BASIC_CFLAGS) -ALL_CFLAGS += $(ARCH_CFLAGS) -ALL_LDFLAGS += $(BASIC_LDFLAGS) - export INSTALL SHELL_PATH - ### Build rules SHELL = $(SHELL_PATH) @@ -939,20 +536,20 @@ strip: $(PROGRAMS) $(OUTPUT)perf $(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \ '-DPERF_HTML_PATH="$(htmldir_SQ)"' \ - $(ALL_CFLAGS) -c $(filter %.c,$^) -o $@ + $(CFLAGS) -c $(filter %.c,$^) -o $@ $(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS) - $(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(OUTPUT)perf.o \ + $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUT)perf.o \ $(BUILTIN_OBJS) $(LIBS) -o $@ $(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \ '-DPERF_HTML_PATH="$(htmldir_SQ)"' \ '-DPERF_MAN_PATH="$(mandir_SQ)"' \ '-DPERF_INFO_PATH="$(infodir_SQ)"' $< $(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \ '-DPERF_HTML_PATH="$(htmldir_SQ)"' \ '-DPERF_MAN_PATH="$(mandir_SQ)"' \ '-DPERF_INFO_PATH="$(infodir_SQ)"' $< @@ -977,77 +574,77 @@ $(OUTPUT)perf.o perf.spec \ # over the general rule for .o $(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(ALL_CFLAGS) -w $< + $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -w $< $(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(ALL_CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $< + $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $< $(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $< $(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -E $(ALL_CFLAGS) $< + $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $< $(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -S $(ALL_CFLAGS) $< + $(QUIET_CC)$(CC) -o $@ -S $(CFLAGS) $< $(OUTPUT)%.o: %.S - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $< $(OUTPUT)%.s: %.S - $(QUIET_CC)$(CC) -o $@ -E $(ALL_CFLAGS) $< + $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $< $(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \ '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \ '-DPREFIX="$(prefix_SQ)"' \ $< $(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \ '-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \ $< $(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \ -DPYTHONPATH='"$(OUTPUT)python"' \ -DPYTHON='"$(PYTHON_WORD)"' \ $< $(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< $(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< $(OUTPUT)ui/browsers/annotate.o: ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< $(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< $(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< $(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< $(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-redundant-decls $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $< $(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $< $(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $< $(OUTPUT)perf-%: %.o $(PERFLIBS) - $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) + $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS) $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) $(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) @@ -1134,7 +731,7 @@ cscope: $(FIND) . -name '*.[hcS]' -print | xargs cscope -b ### Detect prefix changes -TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):\ +TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\ $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ) $(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS @@ -1155,7 +752,7 @@ check: $(OUTPUT)common-cmds.h then \ for i in *.c */*.c; \ do \ - sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; \ + sparse $(CFLAGS) $(SPARSE_FLAGS) $$i || exit; \ done; \ else \ exit 1; \ @@ -1163,13 +760,6 @@ check: $(OUTPUT)common-cmds.h ### Installation rules -ifneq ($(filter /%,$(firstword $(perfexecdir))),) -perfexec_instdir = $(perfexecdir) -else -perfexec_instdir = $(prefix)/$(perfexecdir) -endif -perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) - install-bin: all $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)' $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)' diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 2d0462d89a97..da8f8eb383a0 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -323,13 +323,20 @@ static void hists__baseline_only(struct hists *hists) static void hists__precompute(struct hists *hists) { - struct rb_node *next = rb_first(&hists->entries); + struct rb_root *root; + struct rb_node *next; + + if (sort__need_collapse) + root = &hists->entries_collapsed; + else + root = hists->entries_in; + next = rb_first(root); while (next != NULL) { - struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node); + struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in); struct hist_entry *pair = hist_entry__next_pair(he); - next = rb_next(&he->rb_node); + next = rb_next(&he->rb_node_in); if (!pair) continue; @@ -457,7 +464,7 @@ static void hists__process(struct hists *old, struct hists *new) hists__output_resort(new); } - hists__fprintf(new, true, 0, 0, stdout); + hists__fprintf(new, true, 0, 0, 0, stdout); } static int __cmd_diff(void) @@ -611,9 +618,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) setup_pager(); - sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", NULL); - sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", NULL); - sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", NULL); + sort__setup_elide(NULL); return __cmd_diff(); } diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 533501e2b07c..24b78aecc928 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -328,6 +328,7 @@ static int kvm_events_hash_fn(u64 key) static bool kvm_event_expand(struct kvm_event *event, int vcpu_id) { int old_max_vcpu = event->max_vcpu; + void *prev; if (vcpu_id < event->max_vcpu) return true; @@ -335,9 +336,11 @@ static bool kvm_event_expand(struct kvm_event *event, int vcpu_id) while (event->max_vcpu <= vcpu_id) event->max_vcpu += DEFAULT_VCPU_NUM; + prev = event->vcpu; event->vcpu = realloc(event->vcpu, event->max_vcpu * sizeof(*event->vcpu)); if (!event->vcpu) { + free(prev); pr_err("Not enough memory\n"); return false; } diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index cdf58ecc04b1..fff985cf3852 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -198,7 +198,6 @@ static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) return; signal(signr, SIG_DFL); - kill(getpid(), signr); } static bool perf_evlist__equal(struct perf_evlist *evlist, @@ -404,6 +403,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); signal(SIGUSR1, sig_handler); + signal(SIGTERM, sig_handler); if (!output_name) { if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index bd0ca81eeaca..ca98d34cd58b 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -52,6 +52,7 @@ struct perf_report { symbol_filter_t annotate_init; const char *cpu_list; const char *symbol_filter_str; + float min_percent; DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); }; @@ -61,6 +62,11 @@ static int perf_report_config(const char *var, const char *value, void *cb) symbol_conf.event_group = perf_config_bool(var, value); return 0; } + if (!strcmp(var, "report.percent-limit")) { + struct perf_report *rep = cb; + rep->min_percent = strtof(value, NULL); + return 0; + } return perf_default_config(var, value, cb); } @@ -187,6 +193,9 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, for (i = 0; i < sample->branch_stack->nr; i++) { if (rep->hide_unresolved && !(bi[i].from.sym && bi[i].to.sym)) continue; + + err = -ENOMEM; + /* * The report shows the percentage of total branches captured * and not events sampled. Thus we use a pseudo period of 1. @@ -195,7 +204,6 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, &bi[i], 1, 1); if (he) { struct annotation *notes; - err = -ENOMEM; bx = he->branch_info; if (bx->from.sym && use_browser == 1 && sort__has_sym) { notes = symbol__annotation(bx->from.sym); @@ -226,11 +234,12 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, } evsel->hists.stats.total_period += 1; hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); - err = 0; } else - return -ENOMEM; + goto out; } + err = 0; out: + free(bi); return err; } @@ -294,6 +303,7 @@ static int process_sample_event(struct perf_tool *tool, { struct perf_report *rep = container_of(tool, struct perf_report, tool); struct addr_location al; + int ret; if (perf_event__preprocess_sample(event, machine, &al, sample, rep->annotate_init) < 0) { @@ -308,28 +318,25 @@ static int process_sample_event(struct perf_tool *tool, if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap)) return 0; - if (sort__branch_mode == 1) { - if (perf_report__add_branch_hist_entry(tool, &al, sample, - evsel, machine)) { + if (sort__mode == SORT_MODE__BRANCH) { + ret = perf_report__add_branch_hist_entry(tool, &al, sample, + evsel, machine); + if (ret < 0) pr_debug("problem adding lbr entry, skipping event\n"); - return -1; - } } else if (rep->mem_mode == 1) { - if (perf_report__add_mem_hist_entry(tool, &al, sample, - evsel, machine, event)) { + ret = perf_report__add_mem_hist_entry(tool, &al, sample, + evsel, machine, event); + if (ret < 0) pr_debug("problem adding mem entry, skipping event\n"); - return -1; - } } else { if (al.map != NULL) al.map->dso->hit = 1; - if (perf_evsel__add_hist_entry(evsel, &al, sample, machine)) { + ret = perf_evsel__add_hist_entry(evsel, &al, sample, machine); + if (ret < 0) pr_debug("problem incrementing symbol period, skipping event\n"); - return -1; - } } - return 0; + return ret; } static int process_read_event(struct perf_tool *tool, @@ -384,7 +391,7 @@ static int perf_report__setup_sample_type(struct perf_report *rep) } } - if (sort__branch_mode == 1) { + if (sort__mode == SORT_MODE__BRANCH) { if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_BRANCH_STACK)) { ui__error("Selected -b but no branch data. " @@ -455,7 +462,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, continue; hists__fprintf_nr_sample_events(rep, hists, evname, stdout); - hists__fprintf(hists, true, 0, 0, stdout); + hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout); fprintf(stdout, "\n\n"); } @@ -574,8 +581,8 @@ static int __cmd_report(struct perf_report *rep) if (use_browser > 0) { if (use_browser == 1) { ret = perf_evlist__tui_browse_hists(session->evlist, - help, - NULL, + help, NULL, + rep->min_percent, &session->header.env); /* * Usually "ret" is the last pressed key, and we only @@ -586,7 +593,7 @@ static int __cmd_report(struct perf_report *rep) } else if (use_browser == 2) { perf_evlist__gtk_browse_hists(session->evlist, help, - NULL); + NULL, rep->min_percent); } } else perf_evlist__tty_browse_hists(session->evlist, rep, help); @@ -691,7 +698,19 @@ static int parse_branch_mode(const struct option *opt __maybe_unused, const char *str __maybe_unused, int unset) { - sort__branch_mode = !unset; + int *branch_mode = opt->value; + + *branch_mode = !unset; + return 0; +} + +static int +parse_percent_limit(const struct option *opt, const char *str, + int unset __maybe_unused) +{ + struct perf_report *rep = opt->value; + + rep->min_percent = strtof(str, NULL); return 0; } @@ -700,6 +719,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) struct perf_session *session; struct stat st; bool has_br_stack = false; + int branch_mode = -1; int ret = -1; char callchain_default_opt[] = "fractal,0.5,callee"; const char * const report_usage[] = { @@ -796,17 +816,19 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "Show a column with the sum of periods"), OPT_BOOLEAN(0, "group", &symbol_conf.event_group, "Show event group information together"), - OPT_CALLBACK_NOOPT('b', "branch-stack", &sort__branch_mode, "", + OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "", "use branch records for histogram filling", parse_branch_mode), OPT_STRING(0, "objdump", &objdump_path, "path", "objdump binary to use for disassembly and annotations"), OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, "Disable symbol demangling"), OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), + OPT_CALLBACK(0, "percent-limit", &report, "percent", + "Don't show entries under that percent", parse_percent_limit), OPT_END() }; - perf_config(perf_report_config, NULL); + perf_config(perf_report_config, &report); argc = parse_options(argc, argv, options, report_usage, 0); @@ -846,11 +868,11 @@ repeat: has_br_stack = perf_header__has_feat(&session->header, HEADER_BRANCH_STACK); - if (sort__branch_mode == -1 && has_br_stack) - sort__branch_mode = 1; + if (branch_mode == -1 && has_br_stack) + sort__mode = SORT_MODE__BRANCH; - /* sort__branch_mode could be 0 if --no-branch-stack */ - if (sort__branch_mode == 1) { + /* sort__mode could be NORMAL if --no-branch-stack */ + if (sort__mode == SORT_MODE__BRANCH) { /* * if no sort_order is provided, then specify * branch-mode specific order @@ -861,10 +883,12 @@ repeat: } if (report.mem_mode) { - if (sort__branch_mode == 1) { + if (sort__mode == SORT_MODE__BRANCH) { fprintf(stderr, "branch and mem mode incompatible\n"); goto error; } + sort__mode = SORT_MODE__MEMORY; + /* * if no sort_order is provided, then specify * branch-mode specific order @@ -929,25 +953,7 @@ repeat: report.symbol_filter_str = argv[0]; } - sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout); - - if (sort__branch_mode == 1) { - sort_entry__setup_elide(&sort_dso_from, symbol_conf.dso_from_list, "dso_from", stdout); - sort_entry__setup_elide(&sort_dso_to, symbol_conf.dso_to_list, "dso_to", stdout); - sort_entry__setup_elide(&sort_sym_from, symbol_conf.sym_from_list, "sym_from", stdout); - sort_entry__setup_elide(&sort_sym_to, symbol_conf.sym_to_list, "sym_to", stdout); - } else { - if (report.mem_mode) { - sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "symbol_daddr", stdout); - sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso_daddr", stdout); - sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "mem", stdout); - sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "local_weight", stdout); - sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "tlb", stdout); - sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "snoop", stdout); - } - sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout); - sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout); - } + sort__setup_elide(stdout); ret = __cmd_report(&report); if (ret == K_SWITCH_INPUT_DATA) { diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 67bdb9f14ad6..f036af9b6f09 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -70,10 +70,11 @@ static volatile int done; +#define HEADER_LINE_NR 5 + static void perf_top__update_print_entries(struct perf_top *top) { - if (top->print_entries > 9) - top->print_entries -= 9; + top->print_entries = top->winsize.ws_row - HEADER_LINE_NR; } static void perf_top__sig_winch(int sig __maybe_unused, @@ -82,13 +83,6 @@ static void perf_top__sig_winch(int sig __maybe_unused, struct perf_top *top = arg; get_term_dimensions(&top->winsize); - if (!top->print_entries - || (top->print_entries+4) > top->winsize.ws_row) { - top->print_entries = top->winsize.ws_row; - } else { - top->print_entries += 4; - top->winsize.ws_row = top->print_entries; - } perf_top__update_print_entries(top); } @@ -251,8 +245,11 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel, { struct hist_entry *he; + pthread_mutex_lock(&evsel->hists.lock); he = __hists__add_entry(&evsel->hists, al, NULL, sample->period, sample->weight); + pthread_mutex_unlock(&evsel->hists.lock); + if (he == NULL) return NULL; @@ -290,16 +287,17 @@ static void perf_top__print_sym_table(struct perf_top *top) return; } - hists__collapse_resort_threaded(&top->sym_evsel->hists); - hists__output_resort_threaded(&top->sym_evsel->hists); - hists__decay_entries_threaded(&top->sym_evsel->hists, - top->hide_user_symbols, - top->hide_kernel_symbols); + hists__collapse_resort(&top->sym_evsel->hists); + hists__output_resort(&top->sym_evsel->hists); + hists__decay_entries(&top->sym_evsel->hists, + top->hide_user_symbols, + top->hide_kernel_symbols); hists__output_recalc_col_len(&top->sym_evsel->hists, - top->winsize.ws_row - 3); + top->print_entries - printed); putchar('\n'); hists__fprintf(&top->sym_evsel->hists, false, - top->winsize.ws_row - 4 - printed, win_width, stdout); + top->print_entries - printed, win_width, + top->min_percent, stdout); } static void prompt_integer(int *target, const char *msg) @@ -477,7 +475,6 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) perf_top__sig_winch(SIGWINCH, NULL, top); sigaction(SIGWINCH, &act, NULL); } else { - perf_top__sig_winch(SIGWINCH, NULL, top); signal(SIGWINCH, SIG_DFL); } break; @@ -556,11 +553,11 @@ static void perf_top__sort_new_samples(void *arg) if (t->evlist->selected != NULL) t->sym_evsel = t->evlist->selected; - hists__collapse_resort_threaded(&t->sym_evsel->hists); - hists__output_resort_threaded(&t->sym_evsel->hists); - hists__decay_entries_threaded(&t->sym_evsel->hists, - t->hide_user_symbols, - t->hide_kernel_symbols); + hists__collapse_resort(&t->sym_evsel->hists); + hists__output_resort(&t->sym_evsel->hists); + hists__decay_entries(&t->sym_evsel->hists, + t->hide_user_symbols, + t->hide_kernel_symbols); } static void *display_thread_tui(void *arg) @@ -584,7 +581,7 @@ static void *display_thread_tui(void *arg) list_for_each_entry(pos, &top->evlist->entries, node) pos->hists.uid_filter_str = top->record_opts.target.uid_str; - perf_evlist__tui_browse_hists(top->evlist, help, &hbt, + perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent, &top->session->header.env); done = 1; @@ -794,7 +791,7 @@ static void perf_event__process_sample(struct perf_tool *tool, return; } - if (top->sort_has_symbols) + if (sort__has_sym) perf_top__record_precise_ip(top, he, evsel->idx, ip); } @@ -912,9 +909,9 @@ out_err: return -1; } -static int perf_top__setup_sample_type(struct perf_top *top) +static int perf_top__setup_sample_type(struct perf_top *top __maybe_unused) { - if (!top->sort_has_symbols) { + if (!sort__has_sym) { if (symbol_conf.use_callchain) { ui__error("Selected -g but \"sym\" not present in --sort/-s."); return -EINVAL; @@ -1025,6 +1022,16 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset) return record_parse_callchain_opt(opt, arg, unset); } +static int +parse_percent_limit(const struct option *opt, const char *arg, + int unset __maybe_unused) +{ + struct perf_top *top = opt->value; + + top->min_percent = strtof(arg, NULL); + return 0; +} + int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) { int status; @@ -1110,6 +1117,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", "Specify disassembler style (e.g. -M intel for intel syntax)"), OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"), + OPT_CALLBACK(0, "percent-limit", &top, "percent", + "Don't show entries under that percent", parse_percent_limit), OPT_END() }; const char * const top_usage[] = { @@ -1133,6 +1142,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) if (setup_sorting() < 0) usage_with_options(top_usage, options); + /* display thread wants entries to be collapsed in a different tree */ + sort__need_collapse = 1; + if (top.use_stdio) use_browser = 0; else if (top.use_tui) @@ -1200,15 +1212,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) if (symbol__init() < 0) return -1; - sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout); - sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout); - sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout); - - /* - * Avoid annotation data structures overhead when symbols aren't on the - * sort list. - */ - top.sort_has_symbols = sort_sym.list.next != NULL; + sort__setup_elide(stdout); get_term_dimensions(&top.winsize); if (top.print_entries == 0) { diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile new file mode 100644 index 000000000000..f139dcd2796e --- /dev/null +++ b/tools/perf/config/Makefile @@ -0,0 +1,477 @@ +uname_M := $(shell uname -m 2>/dev/null || echo not) + +ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ + -e s/arm.*/arm/ -e s/sa110/arm/ \ + -e s/s390x/s390/ -e s/parisc64/parisc/ \ + -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ + -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ ) +NO_PERF_REGS := 1 +CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS) + +# Additional ARCH settings for x86 +ifeq ($(ARCH),i386) + override ARCH := x86 + NO_PERF_REGS := 0 + LIBUNWIND_LIBS = -lunwind -lunwind-x86 +endif + +ifeq ($(ARCH),x86_64) + override ARCH := x86 + IS_X86_64 := 0 + ifeq (, $(findstring m32,$(CFLAGS))) + IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) + endif + ifeq (${IS_X86_64}, 1) + RAW_ARCH := x86_64 + CFLAGS += -DARCH_X86_64 + ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S + endif + NO_PERF_REGS := 0 + LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 +endif + +ifeq ($(NO_PERF_REGS),0) + CFLAGS += -DHAVE_PERF_REGS +endif + +ifeq ($(src-perf),) +src-perf := $(srctree)/tools/perf +endif + +ifeq ($(obj-perf),) +obj-perf := $(objtree) +endif + +ifneq ($(obj-perf),) +obj-perf := $(abspath $(obj-perf))/ +endif + +# include ARCH specific config +-include $(src-perf)/arch/$(ARCH)/Makefile + +include $(src-perf)/config/feature-tests.mak +include $(src-perf)/config/utilities.mak + +ifeq ($(call get-executable,$(FLEX)),) + dummy := $(error Error: $(FLEX) is missing on this system, please install it) +endif + +ifeq ($(call get-executable,$(BISON)),) + dummy := $(error Error: $(BISON) is missing on this system, please install it) +endif + +# Treat warnings as errors unless directed not to +ifneq ($(WERROR),0) + CFLAGS += -Werror +endif + +ifeq ("$(origin DEBUG)", "command line") + PERF_DEBUG = $(DEBUG) +endif +ifndef PERF_DEBUG + CFLAGS += -O6 +endif + +ifdef PARSER_DEBUG + PARSER_DEBUG_BISON := -t + PARSER_DEBUG_FLEX := -d + CFLAGS += -DPARSER_DEBUG +endif + +CFLAGS += -fno-omit-frame-pointer +CFLAGS += -ggdb3 +CFLAGS += -funwind-tables +CFLAGS += -Wall +CFLAGS += -Wextra +CFLAGS += -std=gnu99 + +EXTLIBS = -lpthread -lrt -lelf -lm + +ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y) + CFLAGS += -fstack-protector-all +endif + +ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wstack-protector,-Wstack-protector),y) + CFLAGS += -Wstack-protector +endif + +ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var,-Wvolatile-register-var),y) + CFLAGS += -Wvolatile-register-var +endif + +ifndef PERF_DEBUG + ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -D_FORTIFY_SOURCE=2,-D_FORTIFY_SOURCE=2),y) + CFLAGS += -D_FORTIFY_SOURCE=2 + endif +endif + +CFLAGS += -I$(src-perf)/util/include +CFLAGS += -I$(src-perf)/arch/$(ARCH)/include +CFLAGS += -I$(srctree)/arch/$(ARCH)/include/uapi +CFLAGS += -I$(srctree)/arch/$(ARCH)/include +CFLAGS += -I$(srctree)/include/uapi +CFLAGS += -I$(srctree)/include + +# $(obj-perf) for generated common-cmds.h +# $(obj-perf)/util for generated bison/flex headers +ifneq ($(OUTPUT),) +CFLAGS += -I$(obj-perf)/util +CFLAGS += -I$(obj-perf) +endif + +CFLAGS += -I$(src-perf)/util +CFLAGS += -I$(src-perf) +CFLAGS += -I$(TRACE_EVENT_DIR) +CFLAGS += -I$(srctree)/tools/lib/ + +CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE + +ifndef NO_BIONIC +ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y) + BIONIC := 1 + EXTLIBS := $(filter-out -lrt,$(EXTLIBS)) + EXTLIBS := $(filter-out -lpthread,$(EXTLIBS)) +endif +endif # NO_BIONIC + +ifdef NO_LIBELF + NO_DWARF := 1 + NO_DEMANGLE := 1 + NO_LIBUNWIND := 1 +else +FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) +ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF),libelf),y) + FLAGS_GLIBC=$(CFLAGS) $(LDFLAGS) + ifeq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC),glibc),y) + LIBC_SUPPORT := 1 + endif + ifeq ($(BIONIC),1) + LIBC_SUPPORT := 1 + endif + ifeq ($(LIBC_SUPPORT),1) + msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev); + + NO_LIBELF := 1 + NO_DWARF := 1 + NO_DEMANGLE := 1 + else + msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); + endif +else + # for linking with debug library, run like: + # make DEBUG=1 LIBDW_DIR=/opt/libdw/ + ifdef LIBDW_DIR + LIBDW_CFLAGS := -I$(LIBDW_DIR)/include + LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib + endif + + FLAGS_DWARF=$(CFLAGS) $(LIBDW_CFLAGS) -ldw -lelf $(LIBDW_LDFLAGS) $(LDFLAGS) $(EXTLIBS) + ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y) + msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); + NO_DWARF := 1 + endif # Dwarf support +endif # SOURCE_LIBELF +endif # NO_LIBELF + +ifndef NO_LIBELF +CFLAGS += -DLIBELF_SUPPORT +FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) +ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y) + CFLAGS += -DLIBELF_MMAP +endif + +# include ARCH specific config +-include $(src-perf)/arch/$(ARCH)/Makefile + +ifndef NO_DWARF +ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) + msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); + NO_DWARF := 1 +else + CFLAGS += -DDWARF_SUPPORT $(LIBDW_CFLAGS) + LDFLAGS += $(LIBDW_LDFLAGS) + EXTLIBS += -lelf -ldw +endif # PERF_HAVE_DWARF_REGS +endif # NO_DWARF + +endif # NO_LIBELF + +ifndef NO_LIBELF +CFLAGS += -DLIBELF_SUPPORT +FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) +ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y) + CFLAGS += -DLIBELF_MMAP +endif # try-cc +endif # NO_LIBELF + +# There's only x86 (both 32 and 64) support for CFI unwind so far +ifneq ($(ARCH),x86) + NO_LIBUNWIND := 1 +endif + +ifndef NO_LIBUNWIND +# for linking with debug library, run like: +# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ +ifdef LIBUNWIND_DIR + LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include + LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib +endif + +FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(CFLAGS) $(LIBUNWIND_LDFLAGS) $(LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS) +ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND),libunwind),y) + msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99); + NO_LIBUNWIND := 1 +endif # Libunwind support +endif # NO_LIBUNWIND + +ifndef NO_LIBUNWIND + CFLAGS += -DLIBUNWIND_SUPPORT + EXTLIBS += $(LIBUNWIND_LIBS) + CFLAGS += $(LIBUNWIND_CFLAGS) + LDFLAGS += $(LIBUNWIND_LDFLAGS) +endif # NO_LIBUNWIND + +ifndef NO_LIBAUDIT + FLAGS_LIBAUDIT = $(CFLAGS) $(LDFLAGS) -laudit + ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT),libaudit),y) + msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev); + NO_LIBAUDIT := 1 + else + CFLAGS += -DLIBAUDIT_SUPPORT + EXTLIBS += -laudit + endif +endif + +ifdef NO_NEWT + NO_SLANG=1 +endif + +ifndef NO_SLANG + FLAGS_SLANG=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -I/usr/include/slang -lslang + ifneq ($(call try-cc,$(SOURCE_SLANG),$(FLAGS_SLANG),libslang),y) + msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev); + NO_SLANG := 1 + else + # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h + CFLAGS += -I/usr/include/slang + CFLAGS += -DSLANG_SUPPORT + EXTLIBS += -lslang + endif +endif + +ifndef NO_GTK2 + FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) + ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2),gtk2),y) + msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); + NO_GTK2 := 1 + else + ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2),-DHAVE_GTK_INFO_BAR),y) + CFLAGS += -DHAVE_GTK_INFO_BAR + endif + CFLAGS += -DGTK2_SUPPORT + CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null) + EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null) + endif +endif + +grep-libs = $(filter -l%,$(1)) +strip-libs = $(filter-out -l%,$(1)) + +ifdef NO_LIBPERL + CFLAGS += -DNO_LIBPERL +else + PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null) + PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS)) + PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS)) + PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` + FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) + + ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED),perl),y) + CFLAGS += -DNO_LIBPERL + NO_LIBPERL := 1 + else + LDFLAGS += $(PERL_EMBED_LDFLAGS) + EXTLIBS += $(PERL_EMBED_LIBADD) + endif +endif + +disable-python = $(eval $(disable-python_code)) +define disable-python_code + CFLAGS += -DNO_LIBPYTHON + $(if $(1),$(warning No $(1) was found)) + $(warning Python support will not be built) + NO_LIBPYTHON := 1 +endef + +override PYTHON := \ + $(call get-executable-or-default,PYTHON,python) + +ifndef PYTHON + $(call disable-python,python interpreter) +else + + PYTHON_WORD := $(call shell-wordify,$(PYTHON)) + + ifdef NO_LIBPYTHON + $(call disable-python) + else + + override PYTHON_CONFIG := \ + $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON)-config) + + ifndef PYTHON_CONFIG + $(call disable-python,python-config tool) + else + + PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG)) + + PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null) + PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) + PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) + PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) + FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) + + ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED),python),y) + $(call disable-python,Python.h (for Python 2.x)) + else + + ifneq ($(call try-cc,$(SOURCE_PYTHON_VERSION),$(FLAGS_PYTHON_EMBED),python version),y) + $(warning Python 3 is not yet supported; please set) + $(warning PYTHON and/or PYTHON_CONFIG appropriately.) + $(warning If you also have Python 2 installed, then) + $(warning try something like:) + $(warning $(and ,)) + $(warning $(and ,) make PYTHON=python2) + $(warning $(and ,)) + $(warning Otherwise, disable Python support entirely:) + $(warning $(and ,)) + $(warning $(and ,) make NO_LIBPYTHON=1) + $(warning $(and ,)) + $(error $(and ,)) + else + LDFLAGS += $(PYTHON_EMBED_LDFLAGS) + EXTLIBS += $(PYTHON_EMBED_LIBADD) + LANG_BINDINGS += $(obj-perf)python/perf.so + endif + endif + endif + endif +endif + +ifdef NO_DEMANGLE + CFLAGS += -DNO_DEMANGLE +else + ifdef HAVE_CPLUS_DEMANGLE + EXTLIBS += -liberty + CFLAGS += -DHAVE_CPLUS_DEMANGLE + else + FLAGS_BFD=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -DPACKAGE='perf' -lbfd + has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD),libbfd) + ifeq ($(has_bfd),y) + EXTLIBS += -lbfd + else + FLAGS_BFD_IBERTY=$(FLAGS_BFD) -liberty + has_bfd_iberty := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY),liberty) + ifeq ($(has_bfd_iberty),y) + EXTLIBS += -lbfd -liberty + else + FLAGS_BFD_IBERTY_Z=$(FLAGS_BFD_IBERTY) -lz + has_bfd_iberty_z := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY_Z),libz) + ifeq ($(has_bfd_iberty_z),y) + EXTLIBS += -lbfd -liberty -lz + else + FLAGS_CPLUS_DEMANGLE=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -liberty + has_cplus_demangle := $(call try-cc,$(SOURCE_CPLUS_DEMANGLE),$(FLAGS_CPLUS_DEMANGLE),demangle) + ifeq ($(has_cplus_demangle),y) + EXTLIBS += -liberty + CFLAGS += -DHAVE_CPLUS_DEMANGLE + else + msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling) + CFLAGS += -DNO_DEMANGLE + endif + endif + endif + endif + endif +endif + +ifndef NO_STRLCPY + ifeq ($(call try-cc,$(SOURCE_STRLCPY),,-DHAVE_STRLCPY),y) + CFLAGS += -DHAVE_STRLCPY + endif +endif + +ifndef NO_ON_EXIT + ifeq ($(call try-cc,$(SOURCE_ON_EXIT),,-DHAVE_ON_EXIT),y) + CFLAGS += -DHAVE_ON_EXIT + endif +endif + +ifndef NO_BACKTRACE + ifeq ($(call try-cc,$(SOURCE_BACKTRACE),,-DBACKTRACE_SUPPORT),y) + CFLAGS += -DBACKTRACE_SUPPORT + endif +endif + +ifndef NO_LIBNUMA + FLAGS_LIBNUMA = $(CFLAGS) $(LDFLAGS) -lnuma + ifneq ($(call try-cc,$(SOURCE_LIBNUMA),$(FLAGS_LIBNUMA),libnuma),y) + msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev); + NO_LIBNUMA := 1 + else + CFLAGS += -DLIBNUMA_SUPPORT + EXTLIBS += -lnuma + endif +endif + +# Among the variables below, these: +# perfexecdir +# template_dir +# mandir +# infodir +# htmldir +# ETC_PERFCONFIG (but not sysconfdir) +# can be specified as a relative path some/where/else; +# this is interpreted as relative to $(prefix) and "perf" at +# runtime figures out where they are based on the path to the executable. +# This can help installing the suite in a relocatable way. + +# Make the path relative to DESTDIR, not to prefix +ifndef DESTDIR +prefix = $(HOME) +endif +bindir_relative = bin +bindir = $(prefix)/$(bindir_relative) +mandir = share/man +infodir = share/info +perfexecdir = libexec/perf-core +sharedir = $(prefix)/share +template_dir = share/perf-core/templates +htmldir = share/doc/perf-doc +ifeq ($(prefix),/usr) +sysconfdir = /etc +ETC_PERFCONFIG = $(sysconfdir)/perfconfig +else +sysconfdir = $(prefix)/etc +ETC_PERFCONFIG = etc/perfconfig +endif +lib = lib + +# Shell quote (do not use $(call) to accommodate ancient setups); +ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG)) +DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) +bindir_SQ = $(subst ','\'',$(bindir)) +mandir_SQ = $(subst ','\'',$(mandir)) +infodir_SQ = $(subst ','\'',$(infodir)) +perfexecdir_SQ = $(subst ','\'',$(perfexecdir)) +template_dir_SQ = $(subst ','\'',$(template_dir)) +htmldir_SQ = $(subst ','\'',$(htmldir)) +prefix_SQ = $(subst ','\'',$(prefix)) +sysconfdir_SQ = $(subst ','\'',$(sysconfdir)) + +ifneq ($(filter /%,$(firstword $(perfexecdir))),) +perfexec_instdir = $(perfexecdir) +else +perfexec_instdir = $(prefix)/$(perfexecdir) +endif +perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py index a4ffc9500023..b5740599aabd 100755 --- a/tools/perf/scripts/python/net_dropmonitor.py +++ b/tools/perf/scripts/python/net_dropmonitor.py @@ -15,35 +15,38 @@ kallsyms = [] def get_kallsyms_table(): global kallsyms + try: f = open("/proc/kallsyms", "r") - linecount = 0 - for line in f: - linecount = linecount+1 - f.seek(0) except: return - - j = 0 for line in f: loc = int(line.split()[0], 16) name = line.split()[2] - j = j +1 - if ((j % 100) == 0): - print "\r" + str(j) + "/" + str(linecount), - kallsyms.append({ 'loc': loc, 'name' : name}) - - print "\r" + str(j) + "/" + str(linecount) + kallsyms.append((loc, name)) kallsyms.sort() - return def get_sym(sloc): loc = int(sloc) - for i in kallsyms: - if (i['loc'] >= loc): - return (i['name'], i['loc']-loc) - return (None, 0) + + # Invariant: kallsyms[i][0] <= loc for all 0 <= i <= start + # kallsyms[i][0] > loc for all end <= i < len(kallsyms) + start, end = -1, len(kallsyms) + while end != start + 1: + pivot = (start + end) // 2 + if loc < kallsyms[pivot][0]: + end = pivot + else: + start = pivot + + # Now (start == -1 or kallsyms[start][0] <= loc) + # and (start == len(kallsyms) - 1 or loc < kallsyms[start + 1][0]) + if start >= 0: + symloc, name = kallsyms[start] + return (name, loc - symloc) + else: + return (None, 0) def print_drop_table(): print "%25s %25s %25s" % ("LOCATION", "OFFSET", "COUNT") @@ -64,7 +67,7 @@ def trace_end(): # called from perf, when it finds a correspoinding event def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, - skbaddr, protocol, location): + skbaddr, location, protocol): slocation = str(location) try: drop_log[slocation] = drop_log[slocation] + 1 diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record index b4fc835de607..e9bd6391f2ae 100644 --- a/tools/perf/tests/attr/base-record +++ b/tools/perf/tests/attr/base-record @@ -27,8 +27,8 @@ watermark=0 precise_ip=0 mmap_data=0 sample_id_all=1 -exclude_host=0 -exclude_guest=1 +exclude_host=0|1 +exclude_guest=0|1 exclude_callchain_kernel=0 exclude_callchain_user=0 wakeup_events=0 diff --git a/tools/perf/tests/attr/base-stat b/tools/perf/tests/attr/base-stat index 748ee949a204..91cd48b399f3 100644 --- a/tools/perf/tests/attr/base-stat +++ b/tools/perf/tests/attr/base-stat @@ -27,8 +27,8 @@ watermark=0 precise_ip=0 mmap_data=0 sample_id_all=0 -exclude_host=0 -exclude_guest=1 +exclude_host=0|1 +exclude_guest=0|1 exclude_callchain_kernel=0 exclude_callchain_user=0 wakeup_events=0 diff --git a/tools/perf/tests/attr/test-record-data b/tools/perf/tests/attr/test-record-data index 6627c3e7534a..716e143b5291 100644 --- a/tools/perf/tests/attr/test-record-data +++ b/tools/perf/tests/attr/test-record-data @@ -4,5 +4,8 @@ args = -d kill >/dev/null 2>&1 [event:base-record] sample_period=4000 -sample_type=271 + +# sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | +# PERF_SAMPLE_ADDR | PERF_SAMPLE_PERIOD | PERF_SAMPLE_DATA_SRC +sample_type=33039 mmap_data=1 diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c index 68daa289e94c..aba095489193 100644 --- a/tools/perf/tests/bp_signal.c +++ b/tools/perf/tests/bp_signal.c @@ -4,6 +4,12 @@ * (git://github.com/deater/perf_event_tests) */ +/* + * Powerpc needs __SANE_USERSPACE_TYPES__ before <linux/types.h> to select + * 'int-ll64.h' and avoid compile warnings when printing __u64 with %llu. + */ +#define __SANE_USERSPACE_TYPES__ + #include <stdlib.h> #include <stdio.h> #include <unistd.h> diff --git a/tools/perf/tests/bp_signal_overflow.c b/tools/perf/tests/bp_signal_overflow.c index fe7ed28815f8..44ac82179708 100644 --- a/tools/perf/tests/bp_signal_overflow.c +++ b/tools/perf/tests/bp_signal_overflow.c @@ -3,6 +3,12 @@ * perf_event_tests (git://github.com/deater/perf_event_tests) */ +/* + * Powerpc needs __SANE_USERSPACE_TYPES__ before <linux/types.h> to select + * 'int-ll64.h' and avoid compile warnings when printing __u64 with %llu. + */ +#define __SANE_USERSPACE_TYPES__ + #include <stdlib.h> #include <stdio.h> #include <unistd.h> diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 0918ada4cc41..35b45f1466b5 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -70,7 +70,7 @@ static struct test { .func = test__attr, }, { - .desc = "Test matching and linking mutliple hists", + .desc = "Test matching and linking multiple hists", .func = test__hists_link, }, { diff --git a/tools/perf/tests/make b/tools/perf/tests/make new file mode 100644 index 000000000000..c441a2875128 --- /dev/null +++ b/tools/perf/tests/make @@ -0,0 +1,138 @@ +PERF := . +MK := Makefile + +# standard single make variable specified +make_clean_all := clean all +make_python_perf_so := python/perf.so +make_debug := DEBUG=1 +make_no_libperl := NO_LIBPERL=1 +make_no_libpython := NO_LIBPYTHON=1 +make_no_scripts := NO_LIBPYTHON=1 NO_LIBPERL=1 +make_no_newt := NO_NEWT=1 +make_no_slang := NO_SLANG=1 +make_no_gtk2 := NO_GTK2=1 +make_no_ui := NO_NEWT=1 NO_SLANG=1 NO_GTK2=1 +make_no_demangle := NO_DEMANGLE=1 +make_no_libelf := NO_LIBELF=1 +make_no_libunwind := NO_LIBUNWIND=1 +make_no_backtrace := NO_BACKTRACE=1 +make_no_libnuma := NO_LIBNUMA=1 +make_no_libaudit := NO_LIBAUDIT=1 +make_no_libbionic := NO_LIBBIONIC=1 +make_tags := tags +make_cscope := cscope +make_help := help +make_doc := doc +make_perf_o := perf.o +make_util_map_o := util/map.o + +# all the NO_* variable combined +make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 +make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 +make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 + +# $(run) contains all available tests +run := make_pure +run += make_clean_all +run += make_python_perf_so +run += make_debug +run += make_no_libperl +run += make_no_libpython +run += make_no_scripts +run += make_no_newt +run += make_no_slang +run += make_no_gtk2 +run += make_no_ui +run += make_no_demangle +run += make_no_libelf +run += make_no_libunwind +run += make_no_backtrace +run += make_no_libnuma +run += make_no_libaudit +run += make_no_libbionic +run += make_tags +run += make_cscope +run += make_help +run += make_doc +run += make_perf_o +run += make_util_map_o +run += make_minimal + +# $(run_O) contains same portion of $(run) tests with '_O' attached +# to distinguish O=... tests +run_O := $(addsuffix _O,$(run)) + +# disable some tests for O=... +run_O := $(filter-out make_python_perf_so_O,$(run_O)) + +# define test for each compile as 'test_NAME' variable +# with the test itself as a value +test_make_tags = test -f tags +test_make_cscope = test -f cscope.out + +test_make_tags_O := $(test_make_tags) +test_make_cscope_O := $(test_make_cscope) + +test_ok := true +test_make_help := $(test_ok) +test_make_doc := $(test_ok) +test_make_help_O := $(test_ok) +test_make_doc_O := $(test_ok) + +test_make_python_perf_so := test -f $(PERF)/python/perf.so + +test_make_perf_o := test -f $(PERF)/perf.o +test_make_util_map_o := test -f $(PERF)/util/map.o + +# Kbuild tests only +#test_make_python_perf_so_O := test -f $$TMP/tools/perf/python/perf.so +#test_make_perf_o_O := test -f $$TMP/tools/perf/perf.o +#test_make_util_map_o_O := test -f $$TMP/tools/perf/util/map.o + +test_make_perf_o_O := true +test_make_util_map_o_O := true + +test_default = test -x $(PERF)/perf +test = $(if $(test_$1),$(test_$1),$(test_default)) + +test_default_O = test -x $$TMP/perf +test_O = $(if $(test_$1),$(test_$1),$(test_default_O)) + +all: + +ifdef DEBUG +d := $(info run $(run)) +d := $(info run_O $(run_O)) +endif + +MAKEFLAGS := --no-print-directory + +clean := @(cd $(PERF); make -s -f $(MK) clean >/dev/null) + +$(run): + $(call clean) + @cmd="cd $(PERF) && make -f $(MK) $($@)"; \ + echo "- $@: $$cmd" && echo $$cmd > $@ && \ + ( eval $$cmd ) >> $@ 2>&1; \ + echo " test: $(call test,$@)"; \ + $(call test,$@) && \ + rm -f $@ + +$(run_O): + $(call clean) + @TMP=$$(mktemp -d); \ + cmd="cd $(PERF) && make -f $(MK) $($(patsubst %_O,%,$@)) O=$$TMP"; \ + echo "- $@: $$cmd" && echo $$cmd > $@ && \ + ( eval $$cmd ) >> $@ 2>&1 && \ + echo " test: $(call test_O,$@)"; \ + $(call test_O,$@) && \ + rm -f $@ && \ + rm -rf $$TMP + +all: $(run) $(run_O) + @echo OK + +out: $(run_O) + @echo OK + +.PHONY: all $(run) $(run_O) clean diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index d88a2d0acb6d..fc0bd3843d34 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -25,7 +25,8 @@ struct hist_browser { struct map_symbol *selection; int print_seq; bool show_dso; - bool has_symbols; + float min_pcnt; + u64 nr_pcnt_entries; }; extern void hist_browser__init_hpp(void); @@ -309,6 +310,8 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser) "Or reduce the sampling frequency."); } +static void hist_browser__update_pcnt_entries(struct hist_browser *hb); + static int hist_browser__run(struct hist_browser *browser, const char *ev_name, struct hist_browser_timer *hbt) { @@ -318,6 +321,8 @@ static int hist_browser__run(struct hist_browser *browser, const char *ev_name, browser->b.entries = &browser->hists->entries; browser->b.nr_entries = browser->hists->nr_entries; + if (browser->min_pcnt) + browser->b.nr_entries = browser->nr_pcnt_entries; hist_browser__refresh_dimensions(browser); hists__browser_title(browser->hists, title, sizeof(title), ev_name); @@ -330,9 +335,18 @@ static int hist_browser__run(struct hist_browser *browser, const char *ev_name, key = ui_browser__run(&browser->b, delay_secs); switch (key) { - case K_TIMER: + case K_TIMER: { + u64 nr_entries; hbt->timer(hbt->arg); - ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries); + + if (browser->min_pcnt) { + hist_browser__update_pcnt_entries(browser); + nr_entries = browser->nr_pcnt_entries; + } else { + nr_entries = browser->hists->nr_entries; + } + + ui_browser__update_nr_entries(&browser->b, nr_entries); if (browser->hists->stats.nr_lost_warned != browser->hists->stats.nr_events[PERF_RECORD_LOST]) { @@ -344,6 +358,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *ev_name, hists__browser_title(browser->hists, title, sizeof(title), ev_name); ui_browser__show_title(&browser->b, title); continue; + } case 'D': { /* Debug */ static int seq; struct hist_entry *h = rb_entry(browser->b.top, @@ -796,10 +811,15 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser) for (nd = browser->top; nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); + float percent = h->stat.period * 100.0 / + hb->hists->stats.total_period; if (h->filtered) continue; + if (percent < hb->min_pcnt) + continue; + row += hist_browser__show_entry(hb, h, row); if (row == browser->height) break; @@ -808,10 +828,18 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser) return row; } -static struct rb_node *hists__filter_entries(struct rb_node *nd) +static struct rb_node *hists__filter_entries(struct rb_node *nd, + struct hists *hists, + float min_pcnt) { while (nd != NULL) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); + float percent = h->stat.period * 100.0 / + hists->stats.total_period; + + if (percent < min_pcnt) + return NULL; + if (!h->filtered) return nd; @@ -821,11 +849,16 @@ static struct rb_node *hists__filter_entries(struct rb_node *nd) return NULL; } -static struct rb_node *hists__filter_prev_entries(struct rb_node *nd) +static struct rb_node *hists__filter_prev_entries(struct rb_node *nd, + struct hists *hists, + float min_pcnt) { while (nd != NULL) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); - if (!h->filtered) + float percent = h->stat.period * 100.0 / + hists->stats.total_period; + + if (!h->filtered && percent >= min_pcnt) return nd; nd = rb_prev(nd); @@ -840,6 +873,9 @@ static void ui_browser__hists_seek(struct ui_browser *browser, struct hist_entry *h; struct rb_node *nd; bool first = true; + struct hist_browser *hb; + + hb = container_of(browser, struct hist_browser, b); if (browser->nr_entries == 0) return; @@ -848,13 +884,15 @@ static void ui_browser__hists_seek(struct ui_browser *browser, switch (whence) { case SEEK_SET: - nd = hists__filter_entries(rb_first(browser->entries)); + nd = hists__filter_entries(rb_first(browser->entries), + hb->hists, hb->min_pcnt); break; case SEEK_CUR: nd = browser->top; goto do_offset; case SEEK_END: - nd = hists__filter_prev_entries(rb_last(browser->entries)); + nd = hists__filter_prev_entries(rb_last(browser->entries), + hb->hists, hb->min_pcnt); first = false; break; default: @@ -897,7 +935,8 @@ do_offset: break; } } - nd = hists__filter_entries(rb_next(nd)); + nd = hists__filter_entries(rb_next(nd), hb->hists, + hb->min_pcnt); if (nd == NULL) break; --offset; @@ -930,7 +969,8 @@ do_offset: } } - nd = hists__filter_prev_entries(rb_prev(nd)); + nd = hists__filter_prev_entries(rb_prev(nd), hb->hists, + hb->min_pcnt); if (nd == NULL) break; ++offset; @@ -1099,14 +1139,17 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, static int hist_browser__fprintf(struct hist_browser *browser, FILE *fp) { - struct rb_node *nd = hists__filter_entries(rb_first(browser->b.entries)); + struct rb_node *nd = hists__filter_entries(rb_first(browser->b.entries), + browser->hists, + browser->min_pcnt); int printed = 0; while (nd) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); printed += hist_browser__fprintf_entry(browser, h, fp); - nd = hists__filter_entries(rb_next(nd)); + nd = hists__filter_entries(rb_next(nd), browser->hists, + browser->min_pcnt); } return printed; @@ -1155,10 +1198,6 @@ static struct hist_browser *hist_browser__new(struct hists *hists) browser->b.refresh = hist_browser__refresh; browser->b.seek = ui_browser__hists_seek; browser->b.use_navkeypressed = true; - if (sort__branch_mode == 1) - browser->has_symbols = sort_sym_from.list.next != NULL; - else - browser->has_symbols = sort_sym.list.next != NULL; } return browser; @@ -1329,11 +1368,25 @@ close_file_and_continue: return ret; } +static void hist_browser__update_pcnt_entries(struct hist_browser *hb) +{ + u64 nr_entries = 0; + struct rb_node *nd = rb_first(&hb->hists->entries); + + while (nd) { + nr_entries++; + nd = hists__filter_entries(rb_next(nd), hb->hists, + hb->min_pcnt); + } + + hb->nr_pcnt_entries = nr_entries; +} static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, const char *helpline, const char *ev_name, bool left_exits, struct hist_browser_timer *hbt, + float min_pcnt, struct perf_session_env *env) { struct hists *hists = &evsel->hists; @@ -1350,6 +1403,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, if (browser == NULL) return -1; + if (min_pcnt) { + browser->min_pcnt = min_pcnt; + hist_browser__update_pcnt_entries(browser); + } + fstack = pstack__new(2); if (fstack == NULL) goto out; @@ -1386,7 +1444,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, */ goto out_free_stack; case 'a': - if (!browser->has_symbols) { + if (!sort__has_sym) { ui_browser__warning(&browser->b, delay_secs * 2, "Annotation is only available for symbolic views, " "include \"sym*\" in --sort to use it."); @@ -1485,10 +1543,10 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, continue; } - if (!browser->has_symbols) + if (!sort__has_sym) goto add_exit_option; - if (sort__branch_mode == 1) { + if (sort__mode == SORT_MODE__BRANCH) { bi = browser->he_selection->branch_info; if (browser->selection != NULL && bi && @@ -1689,6 +1747,7 @@ struct perf_evsel_menu { struct ui_browser b; struct perf_evsel *selection; bool lost_events, lost_events_warned; + float min_pcnt; struct perf_session_env *env; }; @@ -1782,6 +1841,7 @@ browse_hists: ev_name = perf_evsel__name(pos); key = perf_evsel__hists_browse(pos, nr_events, help, ev_name, true, hbt, + menu->min_pcnt, menu->env); ui_browser__show_title(&menu->b, title); switch (key) { @@ -1843,6 +1903,7 @@ static bool filter_group_entries(struct ui_browser *self __maybe_unused, static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, int nr_entries, const char *help, struct hist_browser_timer *hbt, + float min_pcnt, struct perf_session_env *env) { struct perf_evsel *pos; @@ -1856,6 +1917,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, .nr_entries = nr_entries, .priv = evlist, }, + .min_pcnt = min_pcnt, .env = env, }; @@ -1874,6 +1936,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, struct hist_browser_timer *hbt, + float min_pcnt, struct perf_session_env *env) { int nr_entries = evlist->nr_entries; @@ -1885,7 +1948,8 @@ single_entry: const char *ev_name = perf_evsel__name(first); return perf_evsel__hists_browse(first, nr_entries, help, - ev_name, false, hbt, env); + ev_name, false, hbt, min_pcnt, + env); } if (symbol_conf.event_group) { @@ -1901,5 +1965,5 @@ single_entry: } return __perf_evlist__tui_browse_hists(evlist, nr_entries, help, - hbt, env); + hbt, min_pcnt, env); } diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 6f259b3d14e2..9708dd5fb8f3 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -124,7 +124,8 @@ void perf_gtk__init_hpp(void) perf_gtk__hpp_color_overhead_guest_us; } -static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) +static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, + float min_pcnt) { struct perf_hpp_fmt *fmt; GType col_types[MAX_COLUMNS]; @@ -189,10 +190,15 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); GtkTreeIter iter; + float percent = h->stat.period * 100.0 / + hists->stats.total_period; if (h->filtered) continue; + if (percent < min_pcnt) + continue; + gtk_list_store_append(store, &iter); col_idx = 0; @@ -222,7 +228,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help, - struct hist_browser_timer *hbt __maybe_unused) + struct hist_browser_timer *hbt __maybe_unused, + float min_pcnt) { struct perf_evsel *pos; GtkWidget *vbox; @@ -286,7 +293,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - perf_gtk__show_hists(scrolled_window, hists); + perf_gtk__show_hists(scrolled_window, hists, min_pcnt); tab_label = gtk_label_new(evname); diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index ff1f60cf442e..ae7a75432249 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -334,7 +334,7 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, } size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, - int max_cols, FILE *fp) + int max_cols, float min_pcnt, FILE *fp) { struct perf_hpp_fmt *fmt; struct sort_entry *se; @@ -440,10 +440,15 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, print_entries: for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); + float percent = h->stat.period * 100.0 / + hists->stats.total_period; if (h->filtered) continue; + if (percent < min_pcnt) + continue; + ret += hist_entry__fprintf(h, max_cols, hists, fp); if (max_rows && ++nr_rows >= max_rows) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index f7c727801aab..99b43dd18c57 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -776,6 +776,8 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, if (pipe_output) dup2(2, 1); + signal(SIGTERM, SIG_DFL); + close(child_ready_pipe[0]); close(go_pipe[1]); fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 07b1a3ad3e24..63b6f8c8edf2 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1514,7 +1514,7 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, switch (err) { case EPERM: case EACCES: - return scnprintf(msg, size, "%s", + return scnprintf(msg, size, "You may not have permission to collect %sstats.\n" "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" " -1 - Not paranoid at all\n" diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 326068a593a5..738d3b8d9745 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2391,7 +2391,6 @@ out_err_write: } lseek(fd, header->data_offset + header->data_size, SEEK_SET); - header->frozen = 1; return 0; } @@ -2871,7 +2870,6 @@ int perf_session__read_header(struct perf_session *session, int fd) session->pevent)) goto out_delete_evlist; - header->frozen = 1; return 0; out_errno: return -errno; diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index c9fc55cada6d..16a3e83c584e 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -84,7 +84,6 @@ struct perf_session_env { }; struct perf_header { - int frozen; bool needs_swap; s64 attr_offset; u64 data_offset; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 6b32721f829a..b11a6cfdb414 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -70,9 +70,17 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) int symlen; u16 len; - if (h->ms.sym) - hists__new_col_len(hists, HISTC_SYMBOL, h->ms.sym->namelen + 4); - else { + /* + * +4 accounts for '[x] ' priv level info + * +2 accounts for 0x prefix on raw addresses + * +3 accounts for ' y ' symtab origin info + */ + if (h->ms.sym) { + symlen = h->ms.sym->namelen + 4; + if (verbose) + symlen += BITS_PER_LONG / 4 + 2 + 3; + hists__new_col_len(hists, HISTC_SYMBOL, symlen); + } else { symlen = unresolved_col_width + 4 + 2; hists__new_col_len(hists, HISTC_SYMBOL, symlen); hists__set_unres_dso_col_len(hists, HISTC_DSO); @@ -91,12 +99,10 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) hists__new_col_len(hists, HISTC_PARENT, h->parent->namelen); if (h->branch_info) { - /* - * +4 accounts for '[x] ' priv level info - * +2 account of 0x prefix on raw addresses - */ if (h->branch_info->from.sym) { symlen = (int)h->branch_info->from.sym->namelen + 4; + if (verbose) + symlen += BITS_PER_LONG / 4 + 2 + 3; hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen); symlen = dso__name_len(h->branch_info->from.map->dso); @@ -109,6 +115,8 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) if (h->branch_info->to.sym) { symlen = (int)h->branch_info->to.sym->namelen + 4; + if (verbose) + symlen += BITS_PER_LONG / 4 + 2 + 3; hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen); symlen = dso__name_len(h->branch_info->to.map->dso); @@ -121,10 +129,6 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) } if (h->mem_info) { - /* - * +4 accounts for '[x] ' priv level info - * +2 account of 0x prefix on raw addresses - */ if (h->mem_info->daddr.sym) { symlen = (int)h->mem_info->daddr.sym->namelen + 4 + unresolved_col_width + 2; @@ -236,8 +240,7 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) return he->stat.period == 0; } -static void __hists__decay_entries(struct hists *hists, bool zap_user, - bool zap_kernel, bool threaded) +void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel) { struct rb_node *next = rb_first(&hists->entries); struct hist_entry *n; @@ -256,7 +259,7 @@ static void __hists__decay_entries(struct hists *hists, bool zap_user, !n->used) { rb_erase(&n->rb_node, &hists->entries); - if (sort__need_collapse || threaded) + if (sort__need_collapse) rb_erase(&n->rb_node_in, &hists->entries_collapsed); hist_entry__free(n); @@ -265,17 +268,6 @@ static void __hists__decay_entries(struct hists *hists, bool zap_user, } } -void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel) -{ - return __hists__decay_entries(hists, zap_user, zap_kernel, false); -} - -void hists__decay_entries_threaded(struct hists *hists, - bool zap_user, bool zap_kernel) -{ - return __hists__decay_entries(hists, zap_user, zap_kernel, true); -} - /* * histogram, sorted on item, collects periods */ @@ -292,6 +284,20 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) he->ms.map->referenced = true; if (he->branch_info) { + /* + * This branch info is (a part of) allocated from + * machine__resolve_bstack() and will be freed after + * adding new entries. So we need to save a copy. + */ + he->branch_info = malloc(sizeof(*he->branch_info)); + if (he->branch_info == NULL) { + free(he); + return NULL; + } + + memcpy(he->branch_info, template->branch_info, + sizeof(*he->branch_info)); + if (he->branch_info->from.map) he->branch_info->from.map->referenced = true; if (he->branch_info->to.map) @@ -341,8 +347,6 @@ static struct hist_entry *add_hist_entry(struct hists *hists, struct hist_entry *he; int cmp; - pthread_mutex_lock(&hists->lock); - p = &hists->entries_in->rb_node; while (*p != NULL) { @@ -360,6 +364,12 @@ static struct hist_entry *add_hist_entry(struct hists *hists, if (!cmp) { he_stat__add_period(&he->stat, period, weight); + /* + * This mem info was allocated from machine__resolve_mem + * and will not be used anymore. + */ + free(entry->mem_info); + /* If the map of an existing hist_entry has * become out-of-date due to an exec() or * similar, update it. Otherwise we will @@ -382,14 +392,12 @@ static struct hist_entry *add_hist_entry(struct hists *hists, he = hist_entry__new(entry); if (!he) - goto out_unlock; + return NULL; rb_link_node(&he->rb_node_in, parent, p); rb_insert_color(&he->rb_node_in, hists->entries_in); out: hist_entry__add_cpumode_period(he, al->cpumode, period); -out_unlock: - pthread_mutex_unlock(&hists->lock); return he; } @@ -589,13 +597,13 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he) hists__filter_entry_by_symbol(hists, he); } -static void __hists__collapse_resort(struct hists *hists, bool threaded) +void hists__collapse_resort(struct hists *hists) { struct rb_root *root; struct rb_node *next; struct hist_entry *n; - if (!sort__need_collapse && !threaded) + if (!sort__need_collapse) return; root = hists__get_rotate_entries_in(hists); @@ -617,16 +625,6 @@ static void __hists__collapse_resort(struct hists *hists, bool threaded) } } -void hists__collapse_resort(struct hists *hists) -{ - return __hists__collapse_resort(hists, false); -} - -void hists__collapse_resort_threaded(struct hists *hists) -{ - return __hists__collapse_resort(hists, true); -} - /* * reverse the map, sort on period. */ @@ -713,7 +711,7 @@ static void __hists__insert_output_entry(struct rb_root *entries, rb_insert_color(&he->rb_node, entries); } -static void __hists__output_resort(struct hists *hists, bool threaded) +void hists__output_resort(struct hists *hists) { struct rb_root *root; struct rb_node *next; @@ -722,7 +720,7 @@ static void __hists__output_resort(struct hists *hists, bool threaded) min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100); - if (sort__need_collapse || threaded) + if (sort__need_collapse) root = &hists->entries_collapsed; else root = hists->entries_in; @@ -743,16 +741,6 @@ static void __hists__output_resort(struct hists *hists, bool threaded) } } -void hists__output_resort(struct hists *hists) -{ - return __hists__output_resort(hists, false); -} - -void hists__output_resort_threaded(struct hists *hists) -{ - return __hists__output_resort(hists, true); -} - static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h, enum hist_filter filter) { diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 14c2fe20aa62..2d3790fd99bb 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -43,12 +43,12 @@ enum hist_column { HISTC_COMM, HISTC_PARENT, HISTC_CPU, + HISTC_SRCLINE, HISTC_MISPREDICT, HISTC_SYMBOL_FROM, HISTC_SYMBOL_TO, HISTC_DSO_FROM, HISTC_DSO_TO, - HISTC_SRCLINE, HISTC_LOCAL_WEIGHT, HISTC_GLOBAL_WEIGHT, HISTC_MEM_DADDR_SYMBOL, @@ -104,13 +104,9 @@ struct hist_entry *__hists__add_mem_entry(struct hists *self, u64 weight); void hists__output_resort(struct hists *self); -void hists__output_resort_threaded(struct hists *hists); void hists__collapse_resort(struct hists *self); -void hists__collapse_resort_threaded(struct hists *hists); void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); -void hists__decay_entries_threaded(struct hists *hists, bool zap_user, - bool zap_kernel); void hists__output_recalc_col_len(struct hists *hists, int max_rows); void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h); @@ -119,7 +115,7 @@ void events_stats__inc(struct events_stats *stats, u32 type); size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); size_t hists__fprintf(struct hists *self, bool show_header, int max_rows, - int max_cols, FILE *fp); + int max_cols, float min_pcnt, FILE *fp); int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr); int hist_entry__annotate(struct hist_entry *self, size_t privsize); @@ -199,6 +195,7 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, struct hist_browser_timer *hbt, + float min_pcnt, struct perf_session_env *env); int script_browse(const char *script_opt); #else @@ -206,6 +203,7 @@ static inline int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, const char *help __maybe_unused, struct hist_browser_timer *hbt __maybe_unused, + float min_pcnt __maybe_unused, struct perf_session_env *env __maybe_unused) { return 0; @@ -233,12 +231,14 @@ static inline int script_browse(const char *script_opt __maybe_unused) #ifdef GTK2_SUPPORT int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help, - struct hist_browser_timer *hbt __maybe_unused); + struct hist_browser_timer *hbt __maybe_unused, + float min_pcnt); #else static inline int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, const char *help __maybe_unused, - struct hist_browser_timer *hbt __maybe_unused) + struct hist_browser_timer *hbt __maybe_unused, + float min_pcnt __maybe_unused) { return 0; } diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 6fcb9de62340..8bcdf9e54089 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -21,6 +21,7 @@ const char *map_type__name[MAP__NR_TYPES] = { static inline int is_anon_memory(const char *filename) { return !strcmp(filename, "//anon") || + !strcmp(filename, "/dev/zero (deleted)") || !strcmp(filename, "/anon_hugepage (deleted)"); } diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 6b51d47acdba..f3b235ec7bf4 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -37,7 +37,6 @@ struct perf_session { int fd; bool fd_pipe; bool repipe; - int cwdlen; char *cwd; struct ordered_samples ordered_samples; char filename[1]; diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index 6b0ed322907e..58ea5ca6c255 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py @@ -18,8 +18,9 @@ class install_lib(_install_lib): self.build_dir = build_lib -cflags = ['-fno-strict-aliasing', '-Wno-write-strings'] -cflags += getenv('CFLAGS', '').split() +cflags = getenv('CFLAGS', '').split() +# switch off several checks (need to be at the end of cflags list) +cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ] build_lib = getenv('PYTHON_EXTBUILD_LIB') build_tmp = getenv('PYTHON_EXTBUILD_TMP') diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 5f52d492590c..313a5a730112 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1,5 +1,6 @@ #include "sort.h" #include "hist.h" +#include "symbol.h" regex_t parent_regex; const char default_parent_pattern[] = "^sys_|^do_page_fault"; @@ -9,7 +10,7 @@ const char *sort_order = default_sort_order; int sort__need_collapse = 0; int sort__has_parent = 0; int sort__has_sym = 0; -int sort__branch_mode = -1; /* -1 = means not set */ +enum sort_mode sort__mode = SORT_MODE__NORMAL; enum sort_type sort__first_dimension; @@ -194,7 +195,7 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, if (verbose) { char o = map ? dso__symtab_origin(map->dso) : '!'; ret += repsep_snprintf(bf, size, "%-#*llx %c ", - BITS_PER_LONG / 4, ip, o); + BITS_PER_LONG / 4 + 2, ip, o); } ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level); @@ -871,14 +872,6 @@ static struct sort_dimension common_sort_dimensions[] = { DIM(SORT_PARENT, "parent", sort_parent), DIM(SORT_CPU, "cpu", sort_cpu), DIM(SORT_SRCLINE, "srcline", sort_srcline), - DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), - DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), - DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym), - DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso), - DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked), - DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb), - DIM(SORT_MEM_LVL, "mem", sort_mem_lvl), - DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop), }; #undef DIM @@ -895,6 +888,36 @@ static struct sort_dimension bstack_sort_dimensions[] = { #undef DIM +#define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) } + +static struct sort_dimension memory_sort_dimensions[] = { + DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), + DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), + DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym), + DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso), + DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked), + DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb), + DIM(SORT_MEM_LVL, "mem", sort_mem_lvl), + DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop), +}; + +#undef DIM + +static void __sort_dimension__add(struct sort_dimension *sd, enum sort_type idx) +{ + if (sd->taken) + return; + + if (sd->entry->se_collapse) + sort__need_collapse = 1; + + if (list_empty(&hist_entry__sort_list)) + sort__first_dimension = idx; + + list_add_tail(&sd->entry->list, &hist_entry__sort_list); + sd->taken = 1; +} + int sort_dimension__add(const char *tok) { unsigned int i; @@ -915,25 +938,11 @@ int sort_dimension__add(const char *tok) return -EINVAL; } sort__has_parent = 1; - } else if (sd->entry == &sort_sym || - sd->entry == &sort_sym_from || - sd->entry == &sort_sym_to || - sd->entry == &sort_mem_daddr_sym) { + } else if (sd->entry == &sort_sym) { sort__has_sym = 1; } - if (sd->taken) - return 0; - - if (sd->entry->se_collapse) - sort__need_collapse = 1; - - if (list_empty(&hist_entry__sort_list)) - sort__first_dimension = i; - - list_add_tail(&sd->entry->list, &hist_entry__sort_list); - sd->taken = 1; - + __sort_dimension__add(sd, i); return 0; } @@ -943,24 +952,29 @@ int sort_dimension__add(const char *tok) if (strncasecmp(tok, sd->name, strlen(tok))) continue; - if (sort__branch_mode != 1) + if (sort__mode != SORT_MODE__BRANCH) return -EINVAL; if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to) sort__has_sym = 1; - if (sd->taken) - return 0; + __sort_dimension__add(sd, i + __SORT_BRANCH_STACK); + return 0; + } - if (sd->entry->se_collapse) - sort__need_collapse = 1; + for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) { + struct sort_dimension *sd = &memory_sort_dimensions[i]; - if (list_empty(&hist_entry__sort_list)) - sort__first_dimension = i + __SORT_BRANCH_STACK; + if (strncasecmp(tok, sd->name, strlen(tok))) + continue; - list_add_tail(&sd->entry->list, &hist_entry__sort_list); - sd->taken = 1; + if (sort__mode != SORT_MODE__MEMORY) + return -EINVAL; + + if (sd->entry == &sort_mem_daddr_sym) + sort__has_sym = 1; + __sort_dimension__add(sd, i + __SORT_MEMORY_MODE); return 0; } @@ -993,8 +1007,9 @@ int setup_sorting(void) return ret; } -void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list, - const char *list_name, FILE *fp) +static void sort_entry__setup_elide(struct sort_entry *self, + struct strlist *list, + const char *list_name, FILE *fp) { if (list && strlist__nr_entries(list) == 1) { if (fp != NULL) @@ -1003,3 +1018,42 @@ void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list, self->elide = true; } } + +void sort__setup_elide(FILE *output) +{ + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, + "dso", output); + sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, + "comm", output); + sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, + "symbol", output); + + if (sort__mode == SORT_MODE__BRANCH) { + sort_entry__setup_elide(&sort_dso_from, + symbol_conf.dso_from_list, + "dso_from", output); + sort_entry__setup_elide(&sort_dso_to, + symbol_conf.dso_to_list, + "dso_to", output); + sort_entry__setup_elide(&sort_sym_from, + symbol_conf.sym_from_list, + "sym_from", output); + sort_entry__setup_elide(&sort_sym_to, + symbol_conf.sym_to_list, + "sym_to", output); + } else if (sort__mode == SORT_MODE__MEMORY) { + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, + "symbol_daddr", output); + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, + "dso_daddr", output); + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, + "mem", output); + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, + "local_weight", output); + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, + "tlb", output); + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, + "snoop", output); + } + +} diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index f24bdf64238c..45ac84c1e037 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -32,7 +32,7 @@ extern const char default_sort_order[]; extern int sort__need_collapse; extern int sort__has_parent; extern int sort__has_sym; -extern int sort__branch_mode; +extern enum sort_mode sort__mode; extern struct sort_entry sort_comm; extern struct sort_entry sort_dso; extern struct sort_entry sort_sym; @@ -117,12 +117,18 @@ static inline struct hist_entry *hist_entry__next_pair(struct hist_entry *he) return NULL; } -static inline void hist_entry__add_pair(struct hist_entry *he, - struct hist_entry *pair) +static inline void hist_entry__add_pair(struct hist_entry *pair, + struct hist_entry *he) { - list_add_tail(&he->pairs.head, &pair->pairs.node); + list_add_tail(&pair->pairs.node, &he->pairs.head); } +enum sort_mode { + SORT_MODE__NORMAL, + SORT_MODE__BRANCH, + SORT_MODE__MEMORY, +}; + enum sort_type { /* common sort keys */ SORT_PID, @@ -132,14 +138,6 @@ enum sort_type { SORT_PARENT, SORT_CPU, SORT_SRCLINE, - SORT_LOCAL_WEIGHT, - SORT_GLOBAL_WEIGHT, - SORT_MEM_DADDR_SYMBOL, - SORT_MEM_DADDR_DSO, - SORT_MEM_LOCKED, - SORT_MEM_TLB, - SORT_MEM_LVL, - SORT_MEM_SNOOP, /* branch stack specific sort keys */ __SORT_BRANCH_STACK, @@ -148,6 +146,17 @@ enum sort_type { SORT_SYM_FROM, SORT_SYM_TO, SORT_MISPREDICT, + + /* memory mode specific sort keys */ + __SORT_MEMORY_MODE, + SORT_LOCAL_WEIGHT = __SORT_MEMORY_MODE, + SORT_GLOBAL_WEIGHT, + SORT_MEM_DADDR_SYMBOL, + SORT_MEM_DADDR_DSO, + SORT_MEM_LOCKED, + SORT_MEM_TLB, + SORT_MEM_LVL, + SORT_MEM_SNOOP, }; /* @@ -172,7 +181,6 @@ extern struct list_head hist_entry__sort_list; int setup_sorting(void); extern int sort_dimension__add(const char *); -void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list, - const char *list_name, FILE *fp); +void sort__setup_elide(FILE *fp); #endif /* __PERF_SORT_H */ diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 23742126f47c..7c59c28afcc5 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -37,7 +37,7 @@ double stddev_stats(struct stats *stats) { double variance, variance_mean; - if (!stats->n) + if (stats->n < 2) return 0.0; variance = stats->M2 / (stats->n - 1); diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 632e40e5ceca..40399cbcca77 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -14,6 +14,7 @@ struct thread *thread__new(pid_t pid) if (self != NULL) { map_groups__init(&self->mg); self->pid = pid; + self->ppid = -1; self->comm = malloc(32); if (self->comm) snprintf(self->comm, 32, ":%d", self->pid); @@ -82,5 +83,8 @@ int thread__fork(struct thread *self, struct thread *parent) for (i = 0; i < MAP__NR_TYPES; ++i) if (map_groups__clone(&self->mg, &parent->mg, i) < 0) return -ENOMEM; + + self->ppid = parent->pid; + return 0; } diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 5ad266403098..eeb7ac62b9e3 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -13,6 +13,7 @@ struct thread { }; struct map_groups mg; pid_t pid; + pid_t ppid; char shortname[3]; bool comm_set; char *comm; diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c index 54d37a4753c5..f857b51b6bde 100644 --- a/tools/perf/util/top.c +++ b/tools/perf/util/top.c @@ -23,20 +23,31 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) { - float samples_per_sec = top->samples / top->delay_secs; - float ksamples_per_sec = top->kernel_samples / top->delay_secs; - float esamples_percent = (100.0 * top->exact_samples) / top->samples; + float samples_per_sec; + float ksamples_per_sec; + float esamples_percent; struct perf_record_opts *opts = &top->record_opts; struct perf_target *target = &opts->target; size_t ret = 0; + if (top->samples) { + samples_per_sec = top->samples / top->delay_secs; + ksamples_per_sec = top->kernel_samples / top->delay_secs; + esamples_percent = (100.0 * top->exact_samples) / top->samples; + } else { + samples_per_sec = ksamples_per_sec = esamples_percent = 0.0; + } + if (!perf_guest) { + float ksamples_percent = 0.0; + + if (samples_per_sec) + ksamples_percent = (100.0 * ksamples_per_sec) / + samples_per_sec; ret = SNPRINTF(bf, size, " PerfTop:%8.0f irqs/sec kernel:%4.1f%%" " exact: %4.1f%% [", samples_per_sec, - 100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) / - samples_per_sec)), - esamples_percent); + ksamples_percent, esamples_percent); } else { float us_samples_per_sec = top->us_samples / top->delay_secs; float guest_kernel_samples_per_sec = top->guest_kernel_samples / top->delay_secs; diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h index 7ebf357dc9e1..df46be93d902 100644 --- a/tools/perf/util/top.h +++ b/tools/perf/util/top.h @@ -26,7 +26,6 @@ struct perf_top { int print_entries, count_filter, delay_secs; bool hide_kernel_symbols, hide_user_symbols, zero; bool use_tui, use_stdio; - bool sort_has_symbols; bool kptr_restrict_warned; bool vmlinux_warned; bool dump_symtab; @@ -37,6 +36,7 @@ struct perf_top { int realtime_prio; int sym_pcnt_filter; const char *sym_filter; + float min_percent; }; size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index a45710b70a55..7a484c97e500 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -221,8 +221,8 @@ extern unsigned char sane_ctype[256]; #define isalpha(x) sane_istest(x,GIT_ALPHA) #define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) #define isprint(x) sane_istest(x,GIT_PRINT) -#define islower(x) (sane_istest(x,GIT_ALPHA) && sane_istest(x,0x20)) -#define isupper(x) (sane_istest(x,GIT_ALPHA) && !sane_istest(x,0x20)) +#define islower(x) (sane_istest(x,GIT_ALPHA) && (x & 0x20)) +#define isupper(x) (sane_istest(x,GIT_ALPHA) && !(x & 0x20)) #define tolower(x) sane_case((unsigned char)(x), 0x20) #define toupper(x) sane_case((unsigned char)(x), 0) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 9e9d34871195..fe702076ca46 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -2191,7 +2191,7 @@ int initialize_counters(int cpu_id) void allocate_output_buffer() { - output_buffer = calloc(1, (1 + topo.num_cpus) * 128); + output_buffer = calloc(1, (1 + topo.num_cpus) * 256); outp = output_buffer; if (outp == NULL) { perror("calloc"); diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 0d7fd8b51544..999eab1bc64f 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1796,7 +1796,7 @@ sub monitor { # We already booted into the kernel we are testing, # but now we booted into another kernel? # Consider this a triple fault. - doprint "Aleady booted in Linux kernel $version, but now\n"; + doprint "Already booted in Linux kernel $version, but now\n"; doprint "we booted into Linux kernel $1.\n"; doprint "Assuming that this is a triple fault.\n"; doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index d4abc59ce1d9..4cb14cae3791 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -6,7 +6,7 @@ TARGETS += memory-hotplug TARGETS += mqueue TARGETS += net TARGETS += ptrace -TARGETS += soft-dirty +TARGETS += timers TARGETS += vm all: diff --git a/tools/testing/selftests/cpu-hotplug/Makefile b/tools/testing/selftests/cpu-hotplug/Makefile index 12657a5e4bf9..ae5faf9aade2 100644 --- a/tools/testing/selftests/cpu-hotplug/Makefile +++ b/tools/testing/selftests/cpu-hotplug/Makefile @@ -1,6 +1,6 @@ all: run_tests: - @./on-off-test.sh || echo "cpu-hotplug selftests: [FAIL]" + @/bin/sh ./on-off-test.sh || echo "cpu-hotplug selftests: [FAIL]" clean: diff --git a/tools/testing/selftests/kcmp/.gitignore b/tools/testing/selftests/kcmp/.gitignore new file mode 100644 index 000000000000..5a9b3732b2de --- /dev/null +++ b/tools/testing/selftests/kcmp/.gitignore @@ -0,0 +1,2 @@ +kcmp_test +kcmp-test-file diff --git a/tools/testing/selftests/kcmp/Makefile b/tools/testing/selftests/kcmp/Makefile index 56eb5523dbb8..d7d6bbeeff2f 100644 --- a/tools/testing/selftests/kcmp/Makefile +++ b/tools/testing/selftests/kcmp/Makefile @@ -25,5 +25,4 @@ run_tests: all @./kcmp_test || echo "kcmp_test: [FAIL]" clean: - rm -fr ./run_test - rm -fr ./test-file + $(RM) kcmp_test kcmp-test-file diff --git a/tools/testing/selftests/memory-hotplug/Makefile b/tools/testing/selftests/memory-hotplug/Makefile index 0f49c3f5f58d..350bfeda3aa8 100644 --- a/tools/testing/selftests/memory-hotplug/Makefile +++ b/tools/testing/selftests/memory-hotplug/Makefile @@ -1,6 +1,6 @@ all: run_tests: - @./on-off-test.sh || echo "memory-hotplug selftests: [FAIL]" + @/bin/sh ./on-off-test.sh || echo "memory-hotplug selftests: [FAIL]" clean: diff --git a/tools/testing/selftests/net/psock_tpacket.c b/tools/testing/selftests/net/psock_tpacket.c index c41b58640a05..24adf709bd9d 100644 --- a/tools/testing/selftests/net/psock_tpacket.c +++ b/tools/testing/selftests/net/psock_tpacket.c @@ -1,6 +1,7 @@ /* * Copyright 2013 Red Hat, Inc. * Author: Daniel Borkmann <dborkman@redhat.com> + * Chetan Loke <loke.chetan@gmail.com> (TPACKET_V3 usage example) * * A basic test of packet socket's TPACKET_V1/TPACKET_V2/TPACKET_V3 behavior. * @@ -71,18 +72,8 @@ # define __align_tpacket(x) __attribute__((aligned(TPACKET_ALIGN(x)))) #endif -#define BLOCK_STATUS(x) ((x)->h1.block_status) -#define BLOCK_NUM_PKTS(x) ((x)->h1.num_pkts) -#define BLOCK_O2FP(x) ((x)->h1.offset_to_first_pkt) -#define BLOCK_LEN(x) ((x)->h1.blk_len) -#define BLOCK_SNUM(x) ((x)->h1.seq_num) -#define BLOCK_O2PRIV(x) ((x)->offset_to_priv) -#define BLOCK_PRIV(x) ((void *) ((uint8_t *) (x) + BLOCK_O2PRIV(x))) -#define BLOCK_HDR_LEN (ALIGN_8(sizeof(struct block_desc))) -#define ALIGN_8(x) (((x) + 8 - 1) & ~(8 - 1)) -#define BLOCK_PLUS_PRIV(sz_pri) (BLOCK_HDR_LEN + ALIGN_8((sz_pri))) - #define NUM_PACKETS 100 +#define ALIGN_8(x) (((x) + 8 - 1) & ~(8 - 1)) struct ring { struct iovec *rd; @@ -476,41 +467,30 @@ static uint64_t __v3_prev_block_seq_num = 0; void __v3_test_block_seq_num(struct block_desc *pbd) { - if (__v3_prev_block_seq_num + 1 != BLOCK_SNUM(pbd)) { + if (__v3_prev_block_seq_num + 1 != pbd->h1.seq_num) { fprintf(stderr, "\nprev_block_seq_num:%"PRIu64", expected " "seq:%"PRIu64" != actual seq:%"PRIu64"\n", __v3_prev_block_seq_num, __v3_prev_block_seq_num + 1, - (uint64_t) BLOCK_SNUM(pbd)); + (uint64_t) pbd->h1.seq_num); exit(1); } - __v3_prev_block_seq_num = BLOCK_SNUM(pbd); + __v3_prev_block_seq_num = pbd->h1.seq_num; } static void __v3_test_block_len(struct block_desc *pbd, uint32_t bytes, int block_num) { - if (BLOCK_NUM_PKTS(pbd)) { - if (bytes != BLOCK_LEN(pbd)) { - fprintf(stderr, "\nblock:%u with %upackets, expected " - "len:%u != actual len:%u\n", block_num, - BLOCK_NUM_PKTS(pbd), bytes, BLOCK_LEN(pbd)); - exit(1); - } - } else { - if (BLOCK_LEN(pbd) != BLOCK_PLUS_PRIV(13)) { - fprintf(stderr, "\nblock:%u, expected len:%lu != " - "actual len:%u\n", block_num, BLOCK_HDR_LEN, - BLOCK_LEN(pbd)); - exit(1); - } + if (pbd->h1.num_pkts && bytes != pbd->h1.blk_len) { + fprintf(stderr, "\nblock:%u with %upackets, expected " + "len:%u != actual len:%u\n", block_num, + pbd->h1.num_pkts, bytes, pbd->h1.blk_len); + exit(1); } } static void __v3_test_block_header(struct block_desc *pbd, const int block_num) { - uint32_t block_status = BLOCK_STATUS(pbd); - - if ((block_status & TP_STATUS_USER) == 0) { + if ((pbd->h1.block_status & TP_STATUS_USER) == 0) { fprintf(stderr, "\nblock %u: not in TP_STATUS_USER\n", block_num); exit(1); } @@ -520,14 +500,15 @@ static void __v3_test_block_header(struct block_desc *pbd, const int block_num) static void __v3_walk_block(struct block_desc *pbd, const int block_num) { - int num_pkts = BLOCK_NUM_PKTS(pbd), i; - unsigned long bytes = 0; - unsigned long bytes_with_padding = BLOCK_PLUS_PRIV(13); + int num_pkts = pbd->h1.num_pkts, i; + unsigned long bytes = 0, bytes_with_padding = ALIGN_8(sizeof(*pbd)); struct tpacket3_hdr *ppd; __v3_test_block_header(pbd, block_num); - ppd = (struct tpacket3_hdr *) ((uint8_t *) pbd + BLOCK_O2FP(pbd)); + ppd = (struct tpacket3_hdr *) ((uint8_t *) pbd + + pbd->h1.offset_to_first_pkt); + for (i = 0; i < num_pkts; ++i) { bytes += ppd->tp_snaplen; @@ -551,7 +532,7 @@ static void __v3_walk_block(struct block_desc *pbd, const int block_num) void __v3_flush_block(struct block_desc *pbd) { - BLOCK_STATUS(pbd) = TP_STATUS_KERNEL; + pbd->h1.block_status = TP_STATUS_KERNEL; __sync_synchronize(); } @@ -577,7 +558,7 @@ static void walk_v3_rx(int sock, struct ring *ring) while (total_packets < NUM_PACKETS * 2) { pbd = (struct block_desc *) ring->rd[block_num].iov_base; - while ((BLOCK_STATUS(pbd) & TP_STATUS_USER) == 0) + while ((pbd->h1.block_status & TP_STATUS_USER) == 0) poll(&pfd, 1, 1); __v3_walk_block(pbd, block_num); @@ -624,8 +605,8 @@ static void __v1_v2_fill(struct ring *ring, unsigned int blocks) static void __v3_fill(struct ring *ring, unsigned int blocks) { ring->req3.tp_retire_blk_tov = 64; - ring->req3.tp_sizeof_priv = 13; - ring->req3.tp_feature_req_word |= TP_FT_REQ_FILL_RXHASH; + ring->req3.tp_sizeof_priv = 0; + ring->req3.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH; ring->req3.tp_block_size = getpagesize() << 2; ring->req3.tp_frame_size = TPACKET_ALIGNMENT << 7; diff --git a/tools/testing/selftests/soft-dirty/Makefile b/tools/testing/selftests/soft-dirty/Makefile deleted file mode 100644 index a9cdc823d6e0..000000000000 --- a/tools/testing/selftests/soft-dirty/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -CFLAGS += -iquote../../../../include/uapi -Wall -soft-dirty: soft-dirty.c - -all: soft-dirty - -clean: - rm -f soft-dirty - -run_tests: all - @./soft-dirty || echo "soft-dirty selftests: [FAIL]" diff --git a/tools/testing/selftests/soft-dirty/soft-dirty.c b/tools/testing/selftests/soft-dirty/soft-dirty.c deleted file mode 100644 index aba4f87f87f0..000000000000 --- a/tools/testing/selftests/soft-dirty/soft-dirty.c +++ /dev/null @@ -1,114 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <sys/mman.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/types.h> - -typedef unsigned long long u64; - -#define PME_PRESENT (1ULL << 63) -#define PME_SOFT_DIRTY (1Ull << 55) - -#define PAGES_TO_TEST 3 -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif - -static void get_pagemap2(char *mem, u64 *map) -{ - int fd; - - fd = open("/proc/self/pagemap2", O_RDONLY); - if (fd < 0) { - perror("Can't open pagemap2"); - exit(1); - } - - lseek(fd, (unsigned long)mem / PAGE_SIZE * sizeof(u64), SEEK_SET); - read(fd, map, sizeof(u64) * PAGES_TO_TEST); - close(fd); -} - -static inline char map_p(u64 map) -{ - return map & PME_PRESENT ? 'p' : '-'; -} - -static inline char map_sd(u64 map) -{ - return map & PME_SOFT_DIRTY ? 'd' : '-'; -} - -static int check_pte(int step, int page, u64 *map, u64 want) -{ - if ((map[page] & want) != want) { - printf("Step %d Page %d has %c%c, want %c%c\n", - step, page, - map_p(map[page]), map_sd(map[page]), - map_p(want), map_sd(want)); - return 1; - } - - return 0; -} - -static void clear_refs(void) -{ - int fd; - char *v = "4"; - - fd = open("/proc/self/clear_refs", O_WRONLY); - if (write(fd, v, 3) < 3) { - perror("Can't clear soft-dirty bit"); - exit(1); - } - close(fd); -} - -int main(void) -{ - char *mem, x; - u64 map[PAGES_TO_TEST]; - - mem = mmap(NULL, PAGES_TO_TEST * PAGE_SIZE, - PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0); - - x = mem[0]; - mem[2 * PAGE_SIZE] = 'c'; - get_pagemap2(mem, map); - - if (check_pte(1, 0, map, PME_PRESENT)) - return 1; - if (check_pte(1, 1, map, 0)) - return 1; - if (check_pte(1, 2, map, PME_PRESENT | PME_SOFT_DIRTY)) - return 1; - - clear_refs(); - get_pagemap2(mem, map); - - if (check_pte(2, 0, map, PME_PRESENT)) - return 1; - if (check_pte(2, 1, map, 0)) - return 1; - if (check_pte(2, 2, map, PME_PRESENT)) - return 1; - - mem[0] = 'a'; - mem[PAGE_SIZE] = 'b'; - x = mem[2 * PAGE_SIZE]; - get_pagemap2(mem, map); - - if (check_pte(3, 0, map, PME_PRESENT | PME_SOFT_DIRTY)) - return 1; - if (check_pte(3, 1, map, PME_PRESENT | PME_SOFT_DIRTY)) - return 1; - if (check_pte(3, 2, map, PME_PRESENT)) - return 1; - - (void)x; /* gcc warn */ - - printf("PASS\n"); - return 0; -} diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile new file mode 100644 index 000000000000..eb2859f4ad21 --- /dev/null +++ b/tools/testing/selftests/timers/Makefile @@ -0,0 +1,8 @@ +all: + gcc posix_timers.c -o posix_timers -lrt + +run_tests: all + ./posix_timers + +clean: + rm -f ./posix_timers diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c new file mode 100644 index 000000000000..4fa655d68a81 --- /dev/null +++ b/tools/testing/selftests/timers/posix_timers.c @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2013 Red Hat, Inc., Frederic Weisbecker <fweisbec@redhat.com> + * + * Licensed under the terms of the GNU GPL License version 2 + * + * Selftests for a few posix timers interface. + * + * Kernel loop code stolen from Steven Rostedt <srostedt@redhat.com> + */ + +#include <sys/time.h> +#include <stdio.h> +#include <signal.h> +#include <unistd.h> +#include <time.h> +#include <pthread.h> + +#define DELAY 2 +#define USECS_PER_SEC 1000000 + +static volatile int done; + +/* Busy loop in userspace to elapse ITIMER_VIRTUAL */ +static void user_loop(void) +{ + while (!done); +} + +/* + * Try to spend as much time as possible in kernelspace + * to elapse ITIMER_PROF. + */ +static void kernel_loop(void) +{ + void *addr = sbrk(0); + + while (!done) { + brk(addr + 4096); + brk(addr); + } +} + +/* + * Sleep until ITIMER_REAL expiration. + */ +static void idle_loop(void) +{ + pause(); +} + +static void sig_handler(int nr) +{ + done = 1; +} + +/* + * Check the expected timer expiration matches the GTOD elapsed delta since + * we armed the timer. Keep a 0.5 sec error margin due to various jitter. + */ +static int check_diff(struct timeval start, struct timeval end) +{ + long long diff; + + diff = end.tv_usec - start.tv_usec; + diff += (end.tv_sec - start.tv_sec) * USECS_PER_SEC; + + if (abs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) { + printf("Diff too high: %lld..", diff); + return -1; + } + + return 0; +} + +static int check_itimer(int which) +{ + int err; + struct timeval start, end; + struct itimerval val = { + .it_value.tv_sec = DELAY, + }; + + printf("Check itimer "); + + if (which == ITIMER_VIRTUAL) + printf("virtual... "); + else if (which == ITIMER_PROF) + printf("prof... "); + else if (which == ITIMER_REAL) + printf("real... "); + + fflush(stdout); + + done = 0; + + if (which == ITIMER_VIRTUAL) + signal(SIGVTALRM, sig_handler); + else if (which == ITIMER_PROF) + signal(SIGPROF, sig_handler); + else if (which == ITIMER_REAL) + signal(SIGALRM, sig_handler); + + err = gettimeofday(&start, NULL); + if (err < 0) { + perror("Can't call gettimeofday()\n"); + return -1; + } + + err = setitimer(which, &val, NULL); + if (err < 0) { + perror("Can't set timer\n"); + return -1; + } + + if (which == ITIMER_VIRTUAL) + user_loop(); + else if (which == ITIMER_PROF) + kernel_loop(); + else if (which == ITIMER_REAL) + idle_loop(); + + gettimeofday(&end, NULL); + if (err < 0) { + perror("Can't call gettimeofday()\n"); + return -1; + } + + if (!check_diff(start, end)) + printf("[OK]\n"); + else + printf("[FAIL]\n"); + + return 0; +} + +static int check_timer_create(int which) +{ + int err; + timer_t id; + struct timeval start, end; + struct itimerspec val = { + .it_value.tv_sec = DELAY, + }; + + printf("Check timer_create() "); + if (which == CLOCK_THREAD_CPUTIME_ID) { + printf("per thread... "); + } else if (which == CLOCK_PROCESS_CPUTIME_ID) { + printf("per process... "); + } + fflush(stdout); + + done = 0; + timer_create(which, NULL, &id); + if (err < 0) { + perror("Can't create timer\n"); + return -1; + } + signal(SIGALRM, sig_handler); + + err = gettimeofday(&start, NULL); + if (err < 0) { + perror("Can't call gettimeofday()\n"); + return -1; + } + + err = timer_settime(id, 0, &val, NULL); + if (err < 0) { + perror("Can't set timer\n"); + return -1; + } + + user_loop(); + + gettimeofday(&end, NULL); + if (err < 0) { + perror("Can't call gettimeofday()\n"); + return -1; + } + + if (!check_diff(start, end)) + printf("[OK]\n"); + else + printf("[FAIL]\n"); + + return 0; +} + +int main(int argc, char **argv) +{ + int err; + + printf("Testing posix timers. False negative may happen on CPU execution \n"); + printf("based timers if other threads run on the CPU...\n"); + + if (check_itimer(ITIMER_VIRTUAL) < 0) + return -1; + + if (check_itimer(ITIMER_PROF) < 0) + return -1; + + if (check_itimer(ITIMER_REAL) < 0) + return -1; + + if (check_timer_create(CLOCK_THREAD_CPUTIME_ID) < 0) + return -1; + + /* + * It's unfortunately hard to reliably test a timer expiration + * on parallel multithread cputime. We could arm it to expire + * on DELAY * nr_threads, with nr_threads busy looping, then wait + * the normal DELAY since the time is elapsing nr_threads faster. + * But for that we need to ensure we have real physical free CPUs + * to ensure true parallelism. So test only one thread until we + * find a better solution. + */ + if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0) + return -1; + + return 0; +} diff --git a/tools/testing/selftests/vm/.gitignore b/tools/testing/selftests/vm/.gitignore new file mode 100644 index 000000000000..ff1bb16cec4f --- /dev/null +++ b/tools/testing/selftests/vm/.gitignore @@ -0,0 +1,4 @@ +hugepage-mmap +hugepage-shm +map_hugetlb +thuge-gen diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile index 436d2e81868b..3f94e1afd6cf 100644 --- a/tools/testing/selftests/vm/Makefile +++ b/tools/testing/selftests/vm/Makefile @@ -2,13 +2,14 @@ CC = $(CROSS_COMPILE)gcc CFLAGS = -Wall +BINARIES = hugepage-mmap hugepage-shm map_hugetlb thuge-gen hugetlbfstest -all: hugepage-mmap hugepage-shm map_hugetlb thuge-gen +all: $(BINARIES) %: %.c $(CC) $(CFLAGS) -o $@ $^ run_tests: all - @/bin/sh ./run_vmtests || echo "vmtests: [FAIL]" + @/bin/sh ./run_vmtests || (echo "vmtests: [FAIL]"; exit 1) clean: - $(RM) hugepage-mmap hugepage-shm map_hugetlb + $(RM) $(BINARIES) diff --git a/tools/testing/selftests/vm/hugetlbfstest.c b/tools/testing/selftests/vm/hugetlbfstest.c new file mode 100644 index 000000000000..ea40ff8c2391 --- /dev/null +++ b/tools/testing/selftests/vm/hugetlbfstest.c @@ -0,0 +1,84 @@ +#define _GNU_SOURCE +#include <assert.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +typedef unsigned long long u64; + +static size_t length = 1 << 24; + +static u64 read_rss(void) +{ + char buf[4096], *s = buf; + int i, fd; + u64 rss; + + fd = open("/proc/self/statm", O_RDONLY); + assert(fd > 2); + memset(buf, 0, sizeof(buf)); + read(fd, buf, sizeof(buf) - 1); + for (i = 0; i < 1; i++) + s = strchr(s, ' ') + 1; + rss = strtoull(s, NULL, 10); + return rss << 12; /* assumes 4k pagesize */ +} + +static void do_mmap(int fd, int extra_flags, int unmap) +{ + int *p; + int flags = MAP_PRIVATE | MAP_POPULATE | extra_flags; + u64 before, after; + + before = read_rss(); + p = mmap(NULL, length, PROT_READ | PROT_WRITE, flags, fd, 0); + assert(p != MAP_FAILED || + !"mmap returned an unexpected error"); + after = read_rss(); + assert(llabs(after - before - length) < 0x40000 || + !"rss didn't grow as expected"); + if (!unmap) + return; + munmap(p, length); + after = read_rss(); + assert(llabs(after - before) < 0x40000 || + !"rss didn't shrink as expected"); +} + +static int open_file(const char *path) +{ + int fd, err; + + unlink(path); + fd = open(path, O_CREAT | O_RDWR | O_TRUNC | O_EXCL + | O_LARGEFILE | O_CLOEXEC, 0600); + assert(fd > 2); + unlink(path); + err = ftruncate(fd, length); + assert(!err); + return fd; +} + +int main(void) +{ + int hugefd, fd; + + fd = open_file("/dev/shm/hugetlbhog"); + hugefd = open_file("/hugepages/hugetlbhog"); + + system("echo 100 > /proc/sys/vm/nr_hugepages"); + do_mmap(-1, MAP_ANONYMOUS, 1); + do_mmap(fd, 0, 1); + do_mmap(-1, MAP_ANONYMOUS | MAP_HUGETLB, 1); + do_mmap(hugefd, 0, 1); + do_mmap(hugefd, MAP_HUGETLB, 1); + /* Leak the last one to test do_exit() */ + do_mmap(-1, MAP_ANONYMOUS | MAP_HUGETLB, 0); + printf("oll korrekt.\n"); + return 0; +} diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests index 4c53cae6c273..c87b6812300d 100644 --- a/tools/testing/selftests/vm/run_vmtests +++ b/tools/testing/selftests/vm/run_vmtests @@ -4,6 +4,7 @@ #we need 256M, below is the size in kB needmem=262144 mnt=./huge +exitcode=0 #get pagesize and freepages from /proc/meminfo while read name size unit; do @@ -41,6 +42,7 @@ echo "--------------------" ./hugepage-mmap if [ $? -ne 0 ]; then echo "[FAIL]" + exitcode=1 else echo "[PASS]" fi @@ -55,6 +57,7 @@ echo "--------------------" ./hugepage-shm if [ $? -ne 0 ]; then echo "[FAIL]" + exitcode=1 else echo "[PASS]" fi @@ -67,6 +70,18 @@ echo "--------------------" ./map_hugetlb if [ $? -ne 0 ]; then echo "[FAIL]" + exitcode=1 +else + echo "[PASS]" +fi + +echo "--------------------" +echo "running hugetlbfstest" +echo "--------------------" +./hugetlbfstest +if [ $? -ne 0 ]; then + echo "[FAIL]" + exitcode=1 else echo "[PASS]" fi @@ -75,3 +90,4 @@ fi umount $mnt rm -rf $mnt echo $nr_hugepgs > /proc/sys/vm/nr_hugepages +exit $exitcode diff --git a/tools/virtio/linux/module.h b/tools/virtio/linux/module.h index 3039a7e972b6..28ce95a05997 100644 --- a/tools/virtio/linux/module.h +++ b/tools/virtio/linux/module.h @@ -1 +1,6 @@ #include <linux/export.h> + +#define MODULE_LICENSE(__MODULE_LICENSE_value) \ + static __attribute__((unused)) const char *__MODULE_LICENSE_name = \ + __MODULE_LICENSE_value + diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h index cd801838156f..844783040703 100644 --- a/tools/virtio/linux/virtio.h +++ b/tools/virtio/linux/virtio.h @@ -45,9 +45,6 @@ struct virtqueue { void *priv; }; -#define MODULE_LICENSE(__MODULE_LICENSE_value) \ - const char *__MODULE_LICENSE_name = __MODULE_LICENSE_value - /* Interfaces exported by virtio_ring. */ int virtqueue_add_sgs(struct virtqueue *vq, struct scatterlist *sgs[], |