perf/core improvements and fixes:
User visible: - The mmap address range for the ring buffer now is calculated using the contents of /proc/sys/kernel/perf_event_mlock_kb. This fixes an -EPERM case where 'trace' was trying to use more than what is configured on perf_event_mlock_kb. (Arnaldo Carvalho de Melo) Infrastructure: - Move bitops definitions so that they match the header file hierarchy in the kernel sources where that code came from. (Arnaldo Carvalho de Melo) - Adopt round{down,up}_pow_of_two from the kernel and use it instead of equivalent code, so that we reuse more kernel code and make tools/ look more like kernel source code, to encourage further contributions from kernel hackers (Arnaldo Carvalho de Melo) - Fix use after free in filename__read_build_id (Mitchell Krome) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJUkZsbAAoJEBpxZoYYoA71kRMIALWRoHarn5glw7/hQkLvYLzc rGnOp1MN07Fn/O7CagNDzIotYIzz0n/kGz4YaxFGS6ssmZqgQ8CraQM/XnyCpkyu PWB1HSTAONEyqAnO8/mm/KvQw4daMn82mYGx25X4E9XXtUvH4+al6xU7Om93omxT Mt/4Zgzrf5RL5fUvIs7CT+sk5CF67T5SDI7VuH55pbDeJkgGiHWbSwF+Jr5yafPd vRkHU5xYy+z8oSqb8NTo+ofDh0vJ1pifhvNncKtOBD3446D00XwUUwILy7HPLXFR MHT0+DiCPGRUnFnhT2gJl7oJMntp4DMAJvfJ3KC09e7yZ5BuU2R4mfNPg0INsfg= =6IJe -----END PGP SIGNATURE----- Merge tag 'perf-core-for-mingo-2' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: - The mmap address range for the ring buffer now is calculated using the contents of /proc/sys/kernel/perf_event_mlock_kb. This fixes an -EPERM case where 'trace' was trying to use more than what is configured on perf_event_mlock_kb. (Arnaldo Carvalho de Melo) Infrastructure changes: - Move bitops definitions so that they match the header file hierarchy in the kernel sources where that code came from. (Arnaldo Carvalho de Melo) - Adopt round{down,up}_pow_of_two from the kernel and use it instead of equivalent code, so that we reuse more kernel code and make tools/ look more like kernel source code, to encourage further contributions from kernel hackers (Arnaldo Carvalho de Melo) - Fix use after free in filename__read_build_id (Mitchell Krome) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Коммит
6aaba7c901
|
@ -0,0 +1,27 @@
|
|||
#ifndef __TOOLS_ASM_GENERIC_BITOPS_H
|
||||
#define __TOOLS_ASM_GENERIC_BITOPS_H
|
||||
|
||||
/*
|
||||
* tools/ copied this from include/asm-generic/bitops.h, bit by bit as it needed
|
||||
* some functions.
|
||||
*
|
||||
* For the benefit of those who are trying to port Linux to another
|
||||
* architecture, here are some C-language equivalents. You should
|
||||
* recode these in the native assembly language, if at all possible.
|
||||
*
|
||||
* C language equivalents written by Theodore Ts'o, 9/26/92
|
||||
*/
|
||||
|
||||
#include <asm-generic/bitops/__ffs.h>
|
||||
#include <asm-generic/bitops/fls.h>
|
||||
#include <asm-generic/bitops/__fls.h>
|
||||
#include <asm-generic/bitops/fls64.h>
|
||||
#include <asm-generic/bitops/find.h>
|
||||
|
||||
#ifndef _TOOLS_LINUX_BITOPS_H_
|
||||
#error only <linux/bitops.h> can be included directly
|
||||
#endif
|
||||
|
||||
#include <asm-generic/bitops/atomic.h>
|
||||
|
||||
#endif /* __TOOLS_ASM_GENERIC_BITOPS_H */
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_
|
||||
#define _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
/**
|
||||
* __ffs - find first bit in word.
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no bit exists, so code should check against 0 first.
|
||||
*/
|
||||
static __always_inline unsigned long __ffs(unsigned long word)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
#if __BITS_PER_LONG == 64
|
||||
if ((word & 0xffffffff) == 0) {
|
||||
num += 32;
|
||||
word >>= 32;
|
||||
}
|
||||
#endif
|
||||
if ((word & 0xffff) == 0) {
|
||||
num += 16;
|
||||
word >>= 16;
|
||||
}
|
||||
if ((word & 0xff) == 0) {
|
||||
num += 8;
|
||||
word >>= 8;
|
||||
}
|
||||
if ((word & 0xf) == 0) {
|
||||
num += 4;
|
||||
word >>= 4;
|
||||
}
|
||||
if ((word & 0x3) == 0) {
|
||||
num += 2;
|
||||
word >>= 2;
|
||||
}
|
||||
if ((word & 0x1) == 0)
|
||||
num += 1;
|
||||
return num;
|
||||
}
|
||||
|
||||
#endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_ */
|
|
@ -0,0 +1 @@
|
|||
#include <../../../../include/asm-generic/bitops/__fls.h>
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_
|
||||
#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
static inline void set_bit(int nr, unsigned long *addr)
|
||||
{
|
||||
addr[nr / __BITS_PER_LONG] |= 1UL << (nr % __BITS_PER_LONG);
|
||||
}
|
||||
|
||||
static inline void clear_bit(int nr, unsigned long *addr)
|
||||
{
|
||||
addr[nr / __BITS_PER_LONG] &= ~(1UL << (nr % __BITS_PER_LONG));
|
||||
}
|
||||
|
||||
static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
|
||||
{
|
||||
return ((1UL << (nr % __BITS_PER_LONG)) &
|
||||
(((unsigned long *)addr)[nr / __BITS_PER_LONG])) != 0;
|
||||
}
|
||||
|
||||
#endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_ */
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_
|
||||
#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_
|
||||
|
||||
#ifndef find_next_bit
|
||||
/**
|
||||
* find_next_bit - find the next set bit in a memory region
|
||||
* @addr: The address to base the search on
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The bitmap size in bits
|
||||
*
|
||||
* Returns the bit number for the next set bit
|
||||
* If no bits are set, returns @size.
|
||||
*/
|
||||
extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
|
||||
size, unsigned long offset);
|
||||
#endif
|
||||
|
||||
#ifndef find_first_bit
|
||||
|
||||
/**
|
||||
* find_first_bit - find the first set bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum number of bits to search
|
||||
*
|
||||
* Returns the bit number of the first set bit.
|
||||
* If no bits are set, returns @size.
|
||||
*/
|
||||
extern unsigned long find_first_bit(const unsigned long *addr,
|
||||
unsigned long size);
|
||||
|
||||
#endif /* find_first_bit */
|
||||
|
||||
#endif /*_TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ */
|
|
@ -0,0 +1 @@
|
|||
#include <../../../../include/asm-generic/bitops/fls.h>
|
|
@ -0,0 +1 @@
|
|||
#include <../../../../include/asm-generic/bitops/fls64.h>
|
|
@ -0,0 +1,53 @@
|
|||
#ifndef _TOOLS_LINUX_BITOPS_H_
|
||||
#define _TOOLS_LINUX_BITOPS_H_
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/hweight.h>
|
||||
|
||||
#ifndef __WORDSIZE
|
||||
#define __WORDSIZE (__SIZEOF_LONG__ * 8)
|
||||
#endif
|
||||
|
||||
#define BITS_PER_LONG __WORDSIZE
|
||||
|
||||
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||
#define BITS_PER_BYTE 8
|
||||
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
|
||||
#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
|
||||
#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
|
||||
#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE)
|
||||
|
||||
/*
|
||||
* Include this here because some architectures need generic_ffs/fls in
|
||||
* scope
|
||||
*
|
||||
* XXX: this needs to be asm/bitops.h, when we get to per arch optimizations
|
||||
*/
|
||||
#include <asm-generic/bitops.h>
|
||||
|
||||
#define for_each_set_bit(bit, addr, size) \
|
||||
for ((bit) = find_first_bit((addr), (size)); \
|
||||
(bit) < (size); \
|
||||
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
||||
|
||||
/* same as for_each_set_bit() but use bit as value to start with */
|
||||
#define for_each_set_bit_from(bit, addr, size) \
|
||||
for ((bit) = find_next_bit((addr), (size), (bit)); \
|
||||
(bit) < (size); \
|
||||
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
||||
|
||||
static inline unsigned long hweight_long(unsigned long w)
|
||||
{
|
||||
return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
|
||||
}
|
||||
|
||||
static inline unsigned fls_long(unsigned long l)
|
||||
{
|
||||
if (sizeof(l) == 4)
|
||||
return fls(l);
|
||||
return fls64(l);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,185 @@
|
|||
/* Integer base 2 logarithm calculation
|
||||
*
|
||||
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _TOOLS_LINUX_LOG2_H
|
||||
#define _TOOLS_LINUX_LOG2_H
|
||||
|
||||
/*
|
||||
* deal with unrepresentable constant logarithms
|
||||
*/
|
||||
extern __attribute__((const, noreturn))
|
||||
int ____ilog2_NaN(void);
|
||||
|
||||
/*
|
||||
* non-constant log of base 2 calculators
|
||||
* - the arch may override these in asm/bitops.h if they can be implemented
|
||||
* more efficiently than using fls() and fls64()
|
||||
* - the arch is not required to handle n==0 if implementing the fallback
|
||||
*/
|
||||
static inline __attribute__((const))
|
||||
int __ilog2_u32(u32 n)
|
||||
{
|
||||
return fls(n) - 1;
|
||||
}
|
||||
|
||||
static inline __attribute__((const))
|
||||
int __ilog2_u64(u64 n)
|
||||
{
|
||||
return fls64(n) - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether some value is a power of two, where zero is
|
||||
* *not* considered a power of two.
|
||||
*/
|
||||
|
||||
static inline __attribute__((const))
|
||||
bool is_power_of_2(unsigned long n)
|
||||
{
|
||||
return (n != 0 && ((n & (n - 1)) == 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* round up to nearest power of two
|
||||
*/
|
||||
static inline __attribute__((const))
|
||||
unsigned long __roundup_pow_of_two(unsigned long n)
|
||||
{
|
||||
return 1UL << fls_long(n - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* round down to nearest power of two
|
||||
*/
|
||||
static inline __attribute__((const))
|
||||
unsigned long __rounddown_pow_of_two(unsigned long n)
|
||||
{
|
||||
return 1UL << (fls_long(n) - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
|
||||
* @n - parameter
|
||||
*
|
||||
* constant-capable log of base 2 calculation
|
||||
* - this can be used to initialise global variables from constant data, hence
|
||||
* the massive ternary operator construction
|
||||
*
|
||||
* selects the appropriately-sized optimised version depending on sizeof(n)
|
||||
*/
|
||||
#define ilog2(n) \
|
||||
( \
|
||||
__builtin_constant_p(n) ? ( \
|
||||
(n) < 1 ? ____ilog2_NaN() : \
|
||||
(n) & (1ULL << 63) ? 63 : \
|
||||
(n) & (1ULL << 62) ? 62 : \
|
||||
(n) & (1ULL << 61) ? 61 : \
|
||||
(n) & (1ULL << 60) ? 60 : \
|
||||
(n) & (1ULL << 59) ? 59 : \
|
||||
(n) & (1ULL << 58) ? 58 : \
|
||||
(n) & (1ULL << 57) ? 57 : \
|
||||
(n) & (1ULL << 56) ? 56 : \
|
||||
(n) & (1ULL << 55) ? 55 : \
|
||||
(n) & (1ULL << 54) ? 54 : \
|
||||
(n) & (1ULL << 53) ? 53 : \
|
||||
(n) & (1ULL << 52) ? 52 : \
|
||||
(n) & (1ULL << 51) ? 51 : \
|
||||
(n) & (1ULL << 50) ? 50 : \
|
||||
(n) & (1ULL << 49) ? 49 : \
|
||||
(n) & (1ULL << 48) ? 48 : \
|
||||
(n) & (1ULL << 47) ? 47 : \
|
||||
(n) & (1ULL << 46) ? 46 : \
|
||||
(n) & (1ULL << 45) ? 45 : \
|
||||
(n) & (1ULL << 44) ? 44 : \
|
||||
(n) & (1ULL << 43) ? 43 : \
|
||||
(n) & (1ULL << 42) ? 42 : \
|
||||
(n) & (1ULL << 41) ? 41 : \
|
||||
(n) & (1ULL << 40) ? 40 : \
|
||||
(n) & (1ULL << 39) ? 39 : \
|
||||
(n) & (1ULL << 38) ? 38 : \
|
||||
(n) & (1ULL << 37) ? 37 : \
|
||||
(n) & (1ULL << 36) ? 36 : \
|
||||
(n) & (1ULL << 35) ? 35 : \
|
||||
(n) & (1ULL << 34) ? 34 : \
|
||||
(n) & (1ULL << 33) ? 33 : \
|
||||
(n) & (1ULL << 32) ? 32 : \
|
||||
(n) & (1ULL << 31) ? 31 : \
|
||||
(n) & (1ULL << 30) ? 30 : \
|
||||
(n) & (1ULL << 29) ? 29 : \
|
||||
(n) & (1ULL << 28) ? 28 : \
|
||||
(n) & (1ULL << 27) ? 27 : \
|
||||
(n) & (1ULL << 26) ? 26 : \
|
||||
(n) & (1ULL << 25) ? 25 : \
|
||||
(n) & (1ULL << 24) ? 24 : \
|
||||
(n) & (1ULL << 23) ? 23 : \
|
||||
(n) & (1ULL << 22) ? 22 : \
|
||||
(n) & (1ULL << 21) ? 21 : \
|
||||
(n) & (1ULL << 20) ? 20 : \
|
||||
(n) & (1ULL << 19) ? 19 : \
|
||||
(n) & (1ULL << 18) ? 18 : \
|
||||
(n) & (1ULL << 17) ? 17 : \
|
||||
(n) & (1ULL << 16) ? 16 : \
|
||||
(n) & (1ULL << 15) ? 15 : \
|
||||
(n) & (1ULL << 14) ? 14 : \
|
||||
(n) & (1ULL << 13) ? 13 : \
|
||||
(n) & (1ULL << 12) ? 12 : \
|
||||
(n) & (1ULL << 11) ? 11 : \
|
||||
(n) & (1ULL << 10) ? 10 : \
|
||||
(n) & (1ULL << 9) ? 9 : \
|
||||
(n) & (1ULL << 8) ? 8 : \
|
||||
(n) & (1ULL << 7) ? 7 : \
|
||||
(n) & (1ULL << 6) ? 6 : \
|
||||
(n) & (1ULL << 5) ? 5 : \
|
||||
(n) & (1ULL << 4) ? 4 : \
|
||||
(n) & (1ULL << 3) ? 3 : \
|
||||
(n) & (1ULL << 2) ? 2 : \
|
||||
(n) & (1ULL << 1) ? 1 : \
|
||||
(n) & (1ULL << 0) ? 0 : \
|
||||
____ilog2_NaN() \
|
||||
) : \
|
||||
(sizeof(n) <= 4) ? \
|
||||
__ilog2_u32(n) : \
|
||||
__ilog2_u64(n) \
|
||||
)
|
||||
|
||||
/**
|
||||
* roundup_pow_of_two - round the given value up to nearest power of two
|
||||
* @n - parameter
|
||||
*
|
||||
* round the given value up to the nearest power of two
|
||||
* - the result is undefined when n == 0
|
||||
* - this can be used to initialise global variables from constant data
|
||||
*/
|
||||
#define roundup_pow_of_two(n) \
|
||||
( \
|
||||
__builtin_constant_p(n) ? ( \
|
||||
(n == 1) ? 1 : \
|
||||
(1UL << (ilog2((n) - 1) + 1)) \
|
||||
) : \
|
||||
__roundup_pow_of_two(n) \
|
||||
)
|
||||
|
||||
/**
|
||||
* rounddown_pow_of_two - round the given value down to nearest power of two
|
||||
* @n - parameter
|
||||
*
|
||||
* round the given value down to the nearest power of two
|
||||
* - the result is undefined when n == 0
|
||||
* - this can be used to initialise global variables from constant data
|
||||
*/
|
||||
#define rounddown_pow_of_two(n) \
|
||||
( \
|
||||
__builtin_constant_p(n) ? ( \
|
||||
(1UL << ilog2(n))) : \
|
||||
__rounddown_pow_of_two(n) \
|
||||
)
|
||||
|
||||
#endif /* _TOOLS_LINUX_LOG2_H */
|
|
@ -0,0 +1,89 @@
|
|||
/* find_next_bit.c: fallback find next bit implementation
|
||||
*
|
||||
* Copied from lib/find_next_bit.c to tools/lib/next_bit.c
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||
|
||||
#ifndef find_next_bit
|
||||
/*
|
||||
* Find the next set bit in a memory region.
|
||||
*/
|
||||
unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
|
||||
unsigned long offset)
|
||||
{
|
||||
const unsigned long *p = addr + BITOP_WORD(offset);
|
||||
unsigned long result = offset & ~(BITS_PER_LONG-1);
|
||||
unsigned long tmp;
|
||||
|
||||
if (offset >= size)
|
||||
return size;
|
||||
size -= result;
|
||||
offset %= BITS_PER_LONG;
|
||||
if (offset) {
|
||||
tmp = *(p++);
|
||||
tmp &= (~0UL << offset);
|
||||
if (size < BITS_PER_LONG)
|
||||
goto found_first;
|
||||
if (tmp)
|
||||
goto found_middle;
|
||||
size -= BITS_PER_LONG;
|
||||
result += BITS_PER_LONG;
|
||||
}
|
||||
while (size & ~(BITS_PER_LONG-1)) {
|
||||
if ((tmp = *(p++)))
|
||||
goto found_middle;
|
||||
result += BITS_PER_LONG;
|
||||
size -= BITS_PER_LONG;
|
||||
}
|
||||
if (!size)
|
||||
return result;
|
||||
tmp = *p;
|
||||
|
||||
found_first:
|
||||
tmp &= (~0UL >> (BITS_PER_LONG - size));
|
||||
if (tmp == 0UL) /* Are any bits set? */
|
||||
return result + size; /* Nope. */
|
||||
found_middle:
|
||||
return result + __ffs(tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef find_first_bit
|
||||
/*
|
||||
* Find the first set bit in a memory region.
|
||||
*/
|
||||
unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
|
||||
{
|
||||
const unsigned long *p = addr;
|
||||
unsigned long result = 0;
|
||||
unsigned long tmp;
|
||||
|
||||
while (size & ~(BITS_PER_LONG-1)) {
|
||||
if ((tmp = *(p++)))
|
||||
goto found;
|
||||
result += BITS_PER_LONG;
|
||||
size -= BITS_PER_LONG;
|
||||
}
|
||||
if (!size)
|
||||
return result;
|
||||
|
||||
tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
|
||||
if (tmp == 0UL) /* Are any bits set? */
|
||||
return result + size; /* Nope. */
|
||||
found:
|
||||
return result + __ffs(tmp);
|
||||
}
|
||||
#endif
|
|
@ -4,17 +4,31 @@ tools/lib/traceevent
|
|||
tools/lib/api
|
||||
tools/lib/symbol/kallsyms.c
|
||||
tools/lib/symbol/kallsyms.h
|
||||
tools/lib/util/find_next_bit.c
|
||||
tools/include/asm/bug.h
|
||||
tools/include/asm-generic/bitops/atomic.h
|
||||
tools/include/asm-generic/bitops/__ffs.h
|
||||
tools/include/asm-generic/bitops/__fls.h
|
||||
tools/include/asm-generic/bitops/find.h
|
||||
tools/include/asm-generic/bitops/fls64.h
|
||||
tools/include/asm-generic/bitops/fls.h
|
||||
tools/include/asm-generic/bitops.h
|
||||
tools/include/linux/bitops.h
|
||||
tools/include/linux/compiler.h
|
||||
tools/include/linux/hash.h
|
||||
tools/include/linux/export.h
|
||||
tools/include/linux/hash.h
|
||||
tools/include/linux/log2.h
|
||||
tools/include/linux/types.h
|
||||
include/asm-generic/bitops/fls64.h
|
||||
include/asm-generic/bitops/__fls.h
|
||||
include/asm-generic/bitops/fls.h
|
||||
include/linux/const.h
|
||||
include/linux/perf_event.h
|
||||
include/linux/rbtree.h
|
||||
include/linux/list.h
|
||||
include/linux/hash.h
|
||||
include/linux/stringify.h
|
||||
lib/find_next_bit.c
|
||||
lib/rbtree.c
|
||||
include/linux/swab.h
|
||||
arch/*/include/asm/unistd*.h
|
||||
|
|
|
@ -231,8 +231,16 @@ LIB_H += ../../include/uapi/linux/const.h
|
|||
LIB_H += ../include/linux/hash.h
|
||||
LIB_H += ../../include/linux/stringify.h
|
||||
LIB_H += util/include/linux/bitmap.h
|
||||
LIB_H += util/include/linux/bitops.h
|
||||
LIB_H += ../include/linux/bitops.h
|
||||
LIB_H += ../include/asm-generic/bitops/atomic.h
|
||||
LIB_H += ../include/asm-generic/bitops/find.h
|
||||
LIB_H += ../include/asm-generic/bitops/fls64.h
|
||||
LIB_H += ../include/asm-generic/bitops/fls.h
|
||||
LIB_H += ../include/asm-generic/bitops/__ffs.h
|
||||
LIB_H += ../include/asm-generic/bitops/__fls.h
|
||||
LIB_H += ../include/asm-generic/bitops.h
|
||||
LIB_H += ../include/linux/compiler.h
|
||||
LIB_H += ../include/linux/log2.h
|
||||
LIB_H += util/include/linux/const.h
|
||||
LIB_H += util/include/linux/ctype.h
|
||||
LIB_H += util/include/linux/kernel.h
|
||||
|
@ -335,6 +343,7 @@ LIB_OBJS += $(OUTPUT)util/event.o
|
|||
LIB_OBJS += $(OUTPUT)util/evlist.o
|
||||
LIB_OBJS += $(OUTPUT)util/evsel.o
|
||||
LIB_OBJS += $(OUTPUT)util/exec_cmd.o
|
||||
LIB_OBJS += $(OUTPUT)util/find_next_bit.o
|
||||
LIB_OBJS += $(OUTPUT)util/help.o
|
||||
LIB_OBJS += $(OUTPUT)util/kallsyms.o
|
||||
LIB_OBJS += $(OUTPUT)util/levenshtein.o
|
||||
|
@ -734,6 +743,9 @@ $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS
|
|||
$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
|
||||
$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS
|
||||
$(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 $(CFLAGS) -Wno-redundant-decls $<
|
||||
|
||||
|
|
|
@ -2485,7 +2485,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||
.user_freq = UINT_MAX,
|
||||
.user_interval = ULLONG_MAX,
|
||||
.no_buffering = true,
|
||||
.mmap_pages = 1024,
|
||||
.mmap_pages = UINT_MAX,
|
||||
},
|
||||
.output = stdout,
|
||||
.show_comm = true,
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/hash.h>
|
||||
#include <linux/log2.h>
|
||||
|
||||
static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
|
||||
static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
|
||||
|
@ -893,10 +894,24 @@ out_unmap:
|
|||
|
||||
static size_t perf_evlist__mmap_size(unsigned long pages)
|
||||
{
|
||||
/* 512 kiB: default amount of unprivileged mlocked memory */
|
||||
if (pages == UINT_MAX)
|
||||
pages = (512 * 1024) / page_size;
|
||||
else if (!is_power_of_2(pages))
|
||||
if (pages == UINT_MAX) {
|
||||
int max;
|
||||
|
||||
if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) {
|
||||
/*
|
||||
* Pick a once upon a time good value, i.e. things look
|
||||
* strange since we can't read a sysctl value, but lets not
|
||||
* die yet...
|
||||
*/
|
||||
max = 512;
|
||||
} else {
|
||||
max -= (page_size / 1024);
|
||||
}
|
||||
|
||||
pages = (max * 1024) / page_size;
|
||||
if (!is_power_of_2(pages))
|
||||
pages = rounddown_pow_of_two(pages);
|
||||
} else if (!is_power_of_2(pages))
|
||||
return 0;
|
||||
|
||||
return (pages + 1) * page_size;
|
||||
|
@ -933,7 +948,7 @@ static long parse_pages_arg(const char *str, unsigned long min,
|
|||
/* leave number of pages at 0 */
|
||||
} else if (!is_power_of_2(pages)) {
|
||||
/* round pages up to next power of 2 */
|
||||
pages = next_pow2_l(pages);
|
||||
pages = roundup_pow_of_two(pages);
|
||||
if (!pages)
|
||||
return -EINVAL;
|
||||
pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n",
|
||||
|
@ -1487,16 +1502,25 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
|
|||
int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size)
|
||||
{
|
||||
char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
|
||||
int value;
|
||||
int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0;
|
||||
|
||||
switch (err) {
|
||||
case EPERM:
|
||||
sysctl__read_int("kernel/perf_event_mlock_kb", &value);
|
||||
scnprintf(buf, size, "Error:\t%s.\n"
|
||||
sysctl__read_int("kernel/perf_event_mlock_kb", &pages_max_per_user);
|
||||
printed += scnprintf(buf + printed, size - printed,
|
||||
"Error:\t%s.\n"
|
||||
"Hint:\tCheck /proc/sys/kernel/perf_event_mlock_kb (%d kB) setting.\n"
|
||||
"Hint:\tTried using %zd kB.\n"
|
||||
"Hint:\tTry using a bigger -m/--mmap-pages value.",
|
||||
emsg, value, evlist->mmap_len / 1024);
|
||||
"Hint:\tTried using %zd kB.\n",
|
||||
emsg, pages_max_per_user, pages_attempted);
|
||||
|
||||
if (pages_attempted >= pages_max_per_user) {
|
||||
printed += scnprintf(buf + printed, size - printed,
|
||||
"Hint:\tTry 'sudo sh -c \"echo %d > /proc/sys/kernel/perf_event_mlock_kb\"', or\n",
|
||||
pages_max_per_user + pages_attempted);
|
||||
}
|
||||
|
||||
printed += scnprintf(buf + printed, size - printed,
|
||||
"Hint:\tTry using a smaller -m/--mmap-pages value.");
|
||||
break;
|
||||
default:
|
||||
scnprintf(buf, size, "%s", emsg);
|
||||
|
|
|
@ -1,162 +0,0 @@
|
|||
#ifndef _PERF_LINUX_BITOPS_H_
|
||||
#define _PERF_LINUX_BITOPS_H_
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/hweight.h>
|
||||
|
||||
#ifndef __WORDSIZE
|
||||
#define __WORDSIZE (__SIZEOF_LONG__ * 8)
|
||||
#endif
|
||||
|
||||
#define BITS_PER_LONG __WORDSIZE
|
||||
#define BITS_PER_BYTE 8
|
||||
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
|
||||
#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
|
||||
#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
|
||||
#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE)
|
||||
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||
|
||||
#define for_each_set_bit(bit, addr, size) \
|
||||
for ((bit) = find_first_bit((addr), (size)); \
|
||||
(bit) < (size); \
|
||||
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
||||
|
||||
/* same as for_each_set_bit() but use bit as value to start with */
|
||||
#define for_each_set_bit_from(bit, addr, size) \
|
||||
for ((bit) = find_next_bit((addr), (size), (bit)); \
|
||||
(bit) < (size); \
|
||||
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
||||
|
||||
static inline void set_bit(int nr, unsigned long *addr)
|
||||
{
|
||||
addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
|
||||
}
|
||||
|
||||
static inline void clear_bit(int nr, unsigned long *addr)
|
||||
{
|
||||
addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG));
|
||||
}
|
||||
|
||||
static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
|
||||
{
|
||||
return ((1UL << (nr % BITS_PER_LONG)) &
|
||||
(((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
|
||||
}
|
||||
|
||||
static inline unsigned long hweight_long(unsigned long w)
|
||||
{
|
||||
return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
|
||||
}
|
||||
|
||||
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||
|
||||
/**
|
||||
* __ffs - find first bit in word.
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no bit exists, so code should check against 0 first.
|
||||
*/
|
||||
static __always_inline unsigned long __ffs(unsigned long word)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
if ((word & 0xffffffff) == 0) {
|
||||
num += 32;
|
||||
word >>= 32;
|
||||
}
|
||||
#endif
|
||||
if ((word & 0xffff) == 0) {
|
||||
num += 16;
|
||||
word >>= 16;
|
||||
}
|
||||
if ((word & 0xff) == 0) {
|
||||
num += 8;
|
||||
word >>= 8;
|
||||
}
|
||||
if ((word & 0xf) == 0) {
|
||||
num += 4;
|
||||
word >>= 4;
|
||||
}
|
||||
if ((word & 0x3) == 0) {
|
||||
num += 2;
|
||||
word >>= 2;
|
||||
}
|
||||
if ((word & 0x1) == 0)
|
||||
num += 1;
|
||||
return num;
|
||||
}
|
||||
|
||||
typedef const unsigned long __attribute__((__may_alias__)) long_alias_t;
|
||||
|
||||
/*
|
||||
* Find the first set bit in a memory region.
|
||||
*/
|
||||
static inline unsigned long
|
||||
find_first_bit(const unsigned long *addr, unsigned long size)
|
||||
{
|
||||
long_alias_t *p = (long_alias_t *) addr;
|
||||
unsigned long result = 0;
|
||||
unsigned long tmp;
|
||||
|
||||
while (size & ~(BITS_PER_LONG-1)) {
|
||||
if ((tmp = *(p++)))
|
||||
goto found;
|
||||
result += BITS_PER_LONG;
|
||||
size -= BITS_PER_LONG;
|
||||
}
|
||||
if (!size)
|
||||
return result;
|
||||
|
||||
tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
|
||||
if (tmp == 0UL) /* Are any bits set? */
|
||||
return result + size; /* Nope. */
|
||||
found:
|
||||
return result + __ffs(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the next set bit in a memory region.
|
||||
*/
|
||||
static inline unsigned long
|
||||
find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset)
|
||||
{
|
||||
const unsigned long *p = addr + BITOP_WORD(offset);
|
||||
unsigned long result = offset & ~(BITS_PER_LONG-1);
|
||||
unsigned long tmp;
|
||||
|
||||
if (offset >= size)
|
||||
return size;
|
||||
size -= result;
|
||||
offset %= BITS_PER_LONG;
|
||||
if (offset) {
|
||||
tmp = *(p++);
|
||||
tmp &= (~0UL << offset);
|
||||
if (size < BITS_PER_LONG)
|
||||
goto found_first;
|
||||
if (tmp)
|
||||
goto found_middle;
|
||||
size -= BITS_PER_LONG;
|
||||
result += BITS_PER_LONG;
|
||||
}
|
||||
while (size & ~(BITS_PER_LONG-1)) {
|
||||
if ((tmp = *(p++)))
|
||||
goto found_middle;
|
||||
result += BITS_PER_LONG;
|
||||
size -= BITS_PER_LONG;
|
||||
}
|
||||
if (!size)
|
||||
return result;
|
||||
tmp = *p;
|
||||
|
||||
found_first:
|
||||
tmp &= (~0UL >> (BITS_PER_LONG - size));
|
||||
if (tmp == 0UL) /* Are any bits set? */
|
||||
return result + size; /* Nope. */
|
||||
found_middle:
|
||||
return result + __ffs(tmp);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -129,6 +129,7 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
|
|||
|
||||
for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
|
||||
void *tmp;
|
||||
long offset;
|
||||
|
||||
if (need_swap) {
|
||||
phdr->p_type = bswap_32(phdr->p_type);
|
||||
|
@ -140,12 +141,13 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
|
|||
continue;
|
||||
|
||||
buf_size = phdr->p_filesz;
|
||||
offset = phdr->p_offset;
|
||||
tmp = realloc(buf, buf_size);
|
||||
if (tmp == NULL)
|
||||
goto out_free;
|
||||
|
||||
buf = tmp;
|
||||
fseek(fp, phdr->p_offset, SEEK_SET);
|
||||
fseek(fp, offset, SEEK_SET);
|
||||
if (fread(buf, buf_size, 1, fp) != 1)
|
||||
goto out_free;
|
||||
|
||||
|
@ -178,6 +180,7 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
|
|||
|
||||
for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
|
||||
void *tmp;
|
||||
long offset;
|
||||
|
||||
if (need_swap) {
|
||||
phdr->p_type = bswap_32(phdr->p_type);
|
||||
|
@ -189,12 +192,13 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
|
|||
continue;
|
||||
|
||||
buf_size = phdr->p_filesz;
|
||||
offset = phdr->p_offset;
|
||||
tmp = realloc(buf, buf_size);
|
||||
if (tmp == NULL)
|
||||
goto out_free;
|
||||
|
||||
buf = tmp;
|
||||
fseek(fp, phdr->p_offset, SEEK_SET);
|
||||
fseek(fp, offset, SEEK_SET);
|
||||
if (fread(buf, buf_size, 1, fp) != 1)
|
||||
goto out_free;
|
||||
|
||||
|
|
|
@ -269,35 +269,6 @@ void event_attr_init(struct perf_event_attr *attr);
|
|||
#define _STR(x) #x
|
||||
#define STR(x) _STR(x)
|
||||
|
||||
/*
|
||||
* Determine whether some value is a power of two, where zero is
|
||||
* *not* considered a power of two.
|
||||
*/
|
||||
|
||||
static inline __attribute__((const))
|
||||
bool is_power_of_2(unsigned long n)
|
||||
{
|
||||
return (n != 0 && ((n & (n - 1)) == 0));
|
||||
}
|
||||
|
||||
static inline unsigned next_pow2(unsigned x)
|
||||
{
|
||||
if (!x)
|
||||
return 1;
|
||||
return 1ULL << (32 - __builtin_clz(x - 1));
|
||||
}
|
||||
|
||||
static inline unsigned long next_pow2_l(unsigned long x)
|
||||
{
|
||||
#if BITS_PER_LONG == 64
|
||||
if (x <= (1UL << 31))
|
||||
return next_pow2(x);
|
||||
return (unsigned long)next_pow2(x >> 32) << 32;
|
||||
#else
|
||||
return next_pow2(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t hex_width(u64 v);
|
||||
int hex2u64(const char *ptr, u64 *val);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче