You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (50 commits) perf report: Add "Fractal" mode output - support callchains with relative overhead rate perf_counter tools: callchains: Manage the cumul hits on the fly perf report: Change default callchain parameters perf report: Use a modifiable string for default callchain options perf report: Warn on callchain output request from non-callchain file x86: atomic64: Inline atomic64_read() again x86: atomic64: Clean up atomic64_sub_and_test() and atomic64_add_negative() x86: atomic64: Improve atomic64_xchg() x86: atomic64: Export APIs to modules x86: atomic64: Improve atomic64_read() x86: atomic64: Code atomic(64)_read and atomic(64)_set in C not CPP x86: atomic64: Fix unclean type use in atomic64_xchg() x86: atomic64: Make atomic_read() type-safe x86: atomic64: Reduce size of functions x86: atomic64: Improve atomic64_add_return() x86: atomic64: Improve cmpxchg8b() x86: atomic64: Improve atomic64_read() x86: atomic64: Move the 32-bit atomic64_t implementation to a .c file x86: atomic64: The atomic64_t data type should be 8 bytes aligned on 32-bit too perf report: Annotate variable initialization ...
This commit is contained in:
@@ -358,6 +358,7 @@ static struct power_pmu power7_pmu = {
|
||||
.get_constraint = power7_get_constraint,
|
||||
.get_alternatives = power7_get_alternatives,
|
||||
.disable_pmc = power7_disable_pmc,
|
||||
.flags = PPMU_ALT_SIPR,
|
||||
.n_generic = ARRAY_SIZE(power7_generic_events),
|
||||
.generic_events = power7_generic_events,
|
||||
.cache_events = &power7_cache_events,
|
||||
|
||||
@@ -19,7 +19,10 @@
|
||||
*
|
||||
* Atomically reads the value of @v.
|
||||
*/
|
||||
#define atomic_read(v) ((v)->counter)
|
||||
static inline int atomic_read(const atomic_t *v)
|
||||
{
|
||||
return v->counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_set - set atomic variable
|
||||
@@ -28,7 +31,10 @@
|
||||
*
|
||||
* Atomically sets the value of @v to @i.
|
||||
*/
|
||||
#define atomic_set(v, i) (((v)->counter) = (i))
|
||||
static inline void atomic_set(atomic_t *v, int i)
|
||||
{
|
||||
v->counter = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_add - add integer to atomic variable
|
||||
@@ -200,8 +206,15 @@ static inline int atomic_sub_return(int i, atomic_t *v)
|
||||
return atomic_add_return(-i, v);
|
||||
}
|
||||
|
||||
#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
|
||||
#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
|
||||
static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
|
||||
{
|
||||
return cmpxchg(&v->counter, old, new);
|
||||
}
|
||||
|
||||
static inline int atomic_xchg(atomic_t *v, int new)
|
||||
{
|
||||
return xchg(&v->counter, new);
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_add_unless - add unless the number is already a given value
|
||||
@@ -250,45 +263,12 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
|
||||
/* An 64bit atomic type */
|
||||
|
||||
typedef struct {
|
||||
unsigned long long counter;
|
||||
u64 __aligned(8) counter;
|
||||
} atomic64_t;
|
||||
|
||||
#define ATOMIC64_INIT(val) { (val) }
|
||||
|
||||
/**
|
||||
* atomic64_read - read atomic64 variable
|
||||
* @ptr: pointer of type atomic64_t
|
||||
*
|
||||
* Atomically reads the value of @v.
|
||||
* Doesn't imply a read memory barrier.
|
||||
*/
|
||||
#define __atomic64_read(ptr) ((ptr)->counter)
|
||||
|
||||
static inline unsigned long long
|
||||
cmpxchg8b(unsigned long long *ptr, unsigned long long old, unsigned long long new)
|
||||
{
|
||||
asm volatile(
|
||||
|
||||
LOCK_PREFIX "cmpxchg8b (%[ptr])\n"
|
||||
|
||||
: "=A" (old)
|
||||
|
||||
: [ptr] "D" (ptr),
|
||||
"A" (old),
|
||||
"b" (ll_low(new)),
|
||||
"c" (ll_high(new))
|
||||
|
||||
: "memory");
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline unsigned long long
|
||||
atomic64_cmpxchg(atomic64_t *ptr, unsigned long long old_val,
|
||||
unsigned long long new_val)
|
||||
{
|
||||
return cmpxchg8b(&ptr->counter, old_val, new_val);
|
||||
}
|
||||
extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val);
|
||||
|
||||
/**
|
||||
* atomic64_xchg - xchg atomic64 variable
|
||||
@@ -298,18 +278,7 @@ atomic64_cmpxchg(atomic64_t *ptr, unsigned long long old_val,
|
||||
* Atomically xchgs the value of @ptr to @new_val and returns
|
||||
* the old value.
|
||||
*/
|
||||
|
||||
static inline unsigned long long
|
||||
atomic64_xchg(atomic64_t *ptr, unsigned long long new_val)
|
||||
{
|
||||
unsigned long long old_val;
|
||||
|
||||
do {
|
||||
old_val = atomic_read(ptr);
|
||||
} while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val);
|
||||
|
||||
return old_val;
|
||||
}
|
||||
extern u64 atomic64_xchg(atomic64_t *ptr, u64 new_val);
|
||||
|
||||
/**
|
||||
* atomic64_set - set atomic64 variable
|
||||
@@ -318,10 +287,7 @@ atomic64_xchg(atomic64_t *ptr, unsigned long long new_val)
|
||||
*
|
||||
* Atomically sets the value of @ptr to @new_val.
|
||||
*/
|
||||
static inline void atomic64_set(atomic64_t *ptr, unsigned long long new_val)
|
||||
{
|
||||
atomic64_xchg(ptr, new_val);
|
||||
}
|
||||
extern void atomic64_set(atomic64_t *ptr, u64 new_val);
|
||||
|
||||
/**
|
||||
* atomic64_read - read atomic64 variable
|
||||
@@ -329,17 +295,30 @@ static inline void atomic64_set(atomic64_t *ptr, unsigned long long new_val)
|
||||
*
|
||||
* Atomically reads the value of @ptr and returns it.
|
||||
*/
|
||||
static inline unsigned long long atomic64_read(atomic64_t *ptr)
|
||||
static inline u64 atomic64_read(atomic64_t *ptr)
|
||||
{
|
||||
unsigned long long curr_val;
|
||||
u64 res;
|
||||
|
||||
do {
|
||||
curr_val = __atomic64_read(ptr);
|
||||
} while (atomic64_cmpxchg(ptr, curr_val, curr_val) != curr_val);
|
||||
/*
|
||||
* Note, we inline this atomic64_t primitive because
|
||||
* it only clobbers EAX/EDX and leaves the others
|
||||
* untouched. We also (somewhat subtly) rely on the
|
||||
* fact that cmpxchg8b returns the current 64-bit value
|
||||
* of the memory location we are touching:
|
||||
*/
|
||||
asm volatile(
|
||||
"mov %%ebx, %%eax\n\t"
|
||||
"mov %%ecx, %%edx\n\t"
|
||||
LOCK_PREFIX "cmpxchg8b %1\n"
|
||||
: "=&A" (res)
|
||||
: "m" (*ptr)
|
||||
);
|
||||
|
||||
return curr_val;
|
||||
return res;
|
||||
}
|
||||
|
||||
extern u64 atomic64_read(atomic64_t *ptr);
|
||||
|
||||
/**
|
||||
* atomic64_add_return - add and return
|
||||
* @delta: integer value to add
|
||||
@@ -347,34 +326,14 @@ static inline unsigned long long atomic64_read(atomic64_t *ptr)
|
||||
*
|
||||
* Atomically adds @delta to @ptr and returns @delta + *@ptr
|
||||
*/
|
||||
static inline unsigned long long
|
||||
atomic64_add_return(unsigned long long delta, atomic64_t *ptr)
|
||||
{
|
||||
unsigned long long old_val, new_val;
|
||||
extern u64 atomic64_add_return(u64 delta, atomic64_t *ptr);
|
||||
|
||||
do {
|
||||
old_val = atomic_read(ptr);
|
||||
new_val = old_val + delta;
|
||||
|
||||
} while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val);
|
||||
|
||||
return new_val;
|
||||
}
|
||||
|
||||
static inline long atomic64_sub_return(unsigned long long delta, atomic64_t *ptr)
|
||||
{
|
||||
return atomic64_add_return(-delta, ptr);
|
||||
}
|
||||
|
||||
static inline long atomic64_inc_return(atomic64_t *ptr)
|
||||
{
|
||||
return atomic64_add_return(1, ptr);
|
||||
}
|
||||
|
||||
static inline long atomic64_dec_return(atomic64_t *ptr)
|
||||
{
|
||||
return atomic64_sub_return(1, ptr);
|
||||
}
|
||||
/*
|
||||
* Other variants with different arithmetic operators:
|
||||
*/
|
||||
extern u64 atomic64_sub_return(u64 delta, atomic64_t *ptr);
|
||||
extern u64 atomic64_inc_return(atomic64_t *ptr);
|
||||
extern u64 atomic64_dec_return(atomic64_t *ptr);
|
||||
|
||||
/**
|
||||
* atomic64_add - add integer to atomic64 variable
|
||||
@@ -383,10 +342,7 @@ static inline long atomic64_dec_return(atomic64_t *ptr)
|
||||
*
|
||||
* Atomically adds @delta to @ptr.
|
||||
*/
|
||||
static inline void atomic64_add(unsigned long long delta, atomic64_t *ptr)
|
||||
{
|
||||
atomic64_add_return(delta, ptr);
|
||||
}
|
||||
extern void atomic64_add(u64 delta, atomic64_t *ptr);
|
||||
|
||||
/**
|
||||
* atomic64_sub - subtract the atomic64 variable
|
||||
@@ -395,10 +351,7 @@ static inline void atomic64_add(unsigned long long delta, atomic64_t *ptr)
|
||||
*
|
||||
* Atomically subtracts @delta from @ptr.
|
||||
*/
|
||||
static inline void atomic64_sub(unsigned long long delta, atomic64_t *ptr)
|
||||
{
|
||||
atomic64_add(-delta, ptr);
|
||||
}
|
||||
extern void atomic64_sub(u64 delta, atomic64_t *ptr);
|
||||
|
||||
/**
|
||||
* atomic64_sub_and_test - subtract value from variable and test result
|
||||
@@ -409,13 +362,7 @@ static inline void atomic64_sub(unsigned long long delta, atomic64_t *ptr)
|
||||
* true if the result is zero, or false for all
|
||||
* other cases.
|
||||
*/
|
||||
static inline int
|
||||
atomic64_sub_and_test(unsigned long long delta, atomic64_t *ptr)
|
||||
{
|
||||
unsigned long long old_val = atomic64_sub_return(delta, ptr);
|
||||
|
||||
return old_val == 0;
|
||||
}
|
||||
extern int atomic64_sub_and_test(u64 delta, atomic64_t *ptr);
|
||||
|
||||
/**
|
||||
* atomic64_inc - increment atomic64 variable
|
||||
@@ -423,10 +370,7 @@ atomic64_sub_and_test(unsigned long long delta, atomic64_t *ptr)
|
||||
*
|
||||
* Atomically increments @ptr by 1.
|
||||
*/
|
||||
static inline void atomic64_inc(atomic64_t *ptr)
|
||||
{
|
||||
atomic64_add(1, ptr);
|
||||
}
|
||||
extern void atomic64_inc(atomic64_t *ptr);
|
||||
|
||||
/**
|
||||
* atomic64_dec - decrement atomic64 variable
|
||||
@@ -434,10 +378,7 @@ static inline void atomic64_inc(atomic64_t *ptr)
|
||||
*
|
||||
* Atomically decrements @ptr by 1.
|
||||
*/
|
||||
static inline void atomic64_dec(atomic64_t *ptr)
|
||||
{
|
||||
atomic64_sub(1, ptr);
|
||||
}
|
||||
extern void atomic64_dec(atomic64_t *ptr);
|
||||
|
||||
/**
|
||||
* atomic64_dec_and_test - decrement and test
|
||||
@@ -447,10 +388,7 @@ static inline void atomic64_dec(atomic64_t *ptr)
|
||||
* returns true if the result is 0, or false for all other
|
||||
* cases.
|
||||
*/
|
||||
static inline int atomic64_dec_and_test(atomic64_t *ptr)
|
||||
{
|
||||
return atomic64_sub_and_test(1, ptr);
|
||||
}
|
||||
extern int atomic64_dec_and_test(atomic64_t *ptr);
|
||||
|
||||
/**
|
||||
* atomic64_inc_and_test - increment and test
|
||||
@@ -460,10 +398,7 @@ static inline int atomic64_dec_and_test(atomic64_t *ptr)
|
||||
* and returns true if the result is zero, or false for all
|
||||
* other cases.
|
||||
*/
|
||||
static inline int atomic64_inc_and_test(atomic64_t *ptr)
|
||||
{
|
||||
return atomic64_sub_and_test(-1, ptr);
|
||||
}
|
||||
extern int atomic64_inc_and_test(atomic64_t *ptr);
|
||||
|
||||
/**
|
||||
* atomic64_add_negative - add and test if negative
|
||||
@@ -474,13 +409,7 @@ static inline int atomic64_inc_and_test(atomic64_t *ptr)
|
||||
* if the result is negative, or false when
|
||||
* result is greater than or equal to zero.
|
||||
*/
|
||||
static inline int
|
||||
atomic64_add_negative(unsigned long long delta, atomic64_t *ptr)
|
||||
{
|
||||
long long old_val = atomic64_add_return(delta, ptr);
|
||||
|
||||
return old_val < 0;
|
||||
}
|
||||
extern int atomic64_add_negative(u64 delta, atomic64_t *ptr);
|
||||
|
||||
#include <asm-generic/atomic-long.h>
|
||||
#endif /* _ASM_X86_ATOMIC_32_H */
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
*
|
||||
* Atomically reads the value of @v.
|
||||
*/
|
||||
#define atomic_read(v) ((v)->counter)
|
||||
static inline int atomic_read(const atomic_t *v)
|
||||
{
|
||||
return v->counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_set - set atomic variable
|
||||
@@ -27,7 +30,10 @@
|
||||
*
|
||||
* Atomically sets the value of @v to @i.
|
||||
*/
|
||||
#define atomic_set(v, i) (((v)->counter) = (i))
|
||||
static inline void atomic_set(atomic_t *v, int i)
|
||||
{
|
||||
v->counter = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_add - add integer to atomic variable
|
||||
@@ -192,7 +198,10 @@ static inline int atomic_sub_return(int i, atomic_t *v)
|
||||
* Atomically reads the value of @v.
|
||||
* Doesn't imply a read memory barrier.
|
||||
*/
|
||||
#define atomic64_read(v) ((v)->counter)
|
||||
static inline long atomic64_read(const atomic64_t *v)
|
||||
{
|
||||
return v->counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic64_set - set atomic64 variable
|
||||
@@ -201,7 +210,10 @@ static inline int atomic_sub_return(int i, atomic_t *v)
|
||||
*
|
||||
* Atomically sets the value of @v to @i.
|
||||
*/
|
||||
#define atomic64_set(v, i) (((v)->counter) = (i))
|
||||
static inline void atomic64_set(atomic64_t *v, long i)
|
||||
{
|
||||
v->counter = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic64_add - add integer to atomic64 variable
|
||||
@@ -355,11 +367,25 @@ static inline long atomic64_sub_return(long i, atomic64_t *v)
|
||||
#define atomic64_inc_return(v) (atomic64_add_return(1, (v)))
|
||||
#define atomic64_dec_return(v) (atomic64_sub_return(1, (v)))
|
||||
|
||||
#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
|
||||
#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
|
||||
static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new)
|
||||
{
|
||||
return cmpxchg(&v->counter, old, new);
|
||||
}
|
||||
|
||||
#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
|
||||
#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
|
||||
static inline long atomic64_xchg(atomic64_t *v, long new)
|
||||
{
|
||||
return xchg(&v->counter, new);
|
||||
}
|
||||
|
||||
static inline long atomic_cmpxchg(atomic_t *v, int old, int new)
|
||||
{
|
||||
return cmpxchg(&v->counter, old, new);
|
||||
}
|
||||
|
||||
static inline long atomic_xchg(atomic_t *v, int new)
|
||||
{
|
||||
return xchg(&v->counter, new);
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_add_unless - add unless the number is a given value
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
extern int kstack_depth_to_print;
|
||||
|
||||
int x86_is_stack_id(int id, char *name);
|
||||
|
||||
/* Generic stack tracer with callbacks */
|
||||
|
||||
struct stacktrace_ops {
|
||||
|
||||
@@ -1561,6 +1561,7 @@ void callchain_store(struct perf_callchain_entry *entry, u64 ip)
|
||||
|
||||
static DEFINE_PER_CPU(struct perf_callchain_entry, irq_entry);
|
||||
static DEFINE_PER_CPU(struct perf_callchain_entry, nmi_entry);
|
||||
static DEFINE_PER_CPU(int, in_nmi_frame);
|
||||
|
||||
|
||||
static void
|
||||
@@ -1576,7 +1577,9 @@ static void backtrace_warning(void *data, char *msg)
|
||||
|
||||
static int backtrace_stack(void *data, char *name)
|
||||
{
|
||||
/* Process all stacks: */
|
||||
per_cpu(in_nmi_frame, smp_processor_id()) =
|
||||
x86_is_stack_id(NMI_STACK, name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1584,6 +1587,9 @@ static void backtrace_address(void *data, unsigned long addr, int reliable)
|
||||
{
|
||||
struct perf_callchain_entry *entry = data;
|
||||
|
||||
if (per_cpu(in_nmi_frame, smp_processor_id()))
|
||||
return;
|
||||
|
||||
if (reliable)
|
||||
callchain_store(entry, addr);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,12 @@
|
||||
|
||||
#include "dumpstack.h"
|
||||
|
||||
/* Just a stub for now */
|
||||
int x86_is_stack_id(int id, char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dump_trace(struct task_struct *task, struct pt_regs *regs,
|
||||
unsigned long *stack, unsigned long bp,
|
||||
const struct stacktrace_ops *ops, void *data)
|
||||
|
||||
@@ -19,10 +19,8 @@
|
||||
|
||||
#include "dumpstack.h"
|
||||
|
||||
static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
|
||||
unsigned *usedp, char **idp)
|
||||
{
|
||||
static char ids[][8] = {
|
||||
|
||||
static char x86_stack_ids[][8] = {
|
||||
[DEBUG_STACK - 1] = "#DB",
|
||||
[NMI_STACK - 1] = "NMI",
|
||||
[DOUBLEFAULT_STACK - 1] = "#DF",
|
||||
@@ -33,6 +31,15 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
|
||||
N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]"
|
||||
#endif
|
||||
};
|
||||
|
||||
int x86_is_stack_id(int id, char *name)
|
||||
{
|
||||
return x86_stack_ids[id - 1] == name;
|
||||
}
|
||||
|
||||
static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
|
||||
unsigned *usedp, char **idp)
|
||||
{
|
||||
unsigned k;
|
||||
|
||||
/*
|
||||
@@ -61,7 +68,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
|
||||
if (*usedp & (1U << k))
|
||||
break;
|
||||
*usedp |= 1U << k;
|
||||
*idp = ids[k];
|
||||
*idp = x86_stack_ids[k];
|
||||
return (unsigned long *)end;
|
||||
}
|
||||
/*
|
||||
@@ -81,12 +88,13 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
|
||||
do {
|
||||
++j;
|
||||
end -= EXCEPTION_STKSZ;
|
||||
ids[j][4] = '1' + (j - N_EXCEPTION_STACKS);
|
||||
x86_stack_ids[j][4] = '1' +
|
||||
(j - N_EXCEPTION_STACKS);
|
||||
} while (stack < end - EXCEPTION_STKSZ);
|
||||
if (*usedp & (1U << j))
|
||||
break;
|
||||
*usedp |= 1U << j;
|
||||
*idp = ids[j];
|
||||
*idp = x86_stack_ids[j];
|
||||
return (unsigned long *)end;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,7 @@ lib-y += usercopy_$(BITS).o getuser.o putuser.o
|
||||
lib-y += memcpy_$(BITS).o
|
||||
|
||||
ifeq ($(CONFIG_X86_32),y)
|
||||
obj-y += atomic64_32.o
|
||||
lib-y += checksum_32.o
|
||||
lib-y += strstr_32.o
|
||||
lib-y += semaphore_32.o string_32.o
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/cmpxchg.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
static noinline u64 cmpxchg8b(u64 *ptr, u64 old, u64 new)
|
||||
{
|
||||
u32 low = new;
|
||||
u32 high = new >> 32;
|
||||
|
||||
asm volatile(
|
||||
LOCK_PREFIX "cmpxchg8b %1\n"
|
||||
: "+A" (old), "+m" (*ptr)
|
||||
: "b" (low), "c" (high)
|
||||
);
|
||||
return old;
|
||||
}
|
||||
|
||||
u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val)
|
||||
{
|
||||
return cmpxchg8b(&ptr->counter, old_val, new_val);
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_cmpxchg);
|
||||
|
||||
/**
|
||||
* atomic64_xchg - xchg atomic64 variable
|
||||
* @ptr: pointer to type atomic64_t
|
||||
* @new_val: value to assign
|
||||
*
|
||||
* Atomically xchgs the value of @ptr to @new_val and returns
|
||||
* the old value.
|
||||
*/
|
||||
u64 atomic64_xchg(atomic64_t *ptr, u64 new_val)
|
||||
{
|
||||
/*
|
||||
* Try first with a (possibly incorrect) assumption about
|
||||
* what we have there. We'll do two loops most likely,
|
||||
* but we'll get an ownership MESI transaction straight away
|
||||
* instead of a read transaction followed by a
|
||||
* flush-for-ownership transaction:
|
||||
*/
|
||||
u64 old_val, real_val = 0;
|
||||
|
||||
do {
|
||||
old_val = real_val;
|
||||
|
||||
real_val = atomic64_cmpxchg(ptr, old_val, new_val);
|
||||
|
||||
} while (real_val != old_val);
|
||||
|
||||
return old_val;
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_xchg);
|
||||
|
||||
/**
|
||||
* atomic64_set - set atomic64 variable
|
||||
* @ptr: pointer to type atomic64_t
|
||||
* @new_val: value to assign
|
||||
*
|
||||
* Atomically sets the value of @ptr to @new_val.
|
||||
*/
|
||||
void atomic64_set(atomic64_t *ptr, u64 new_val)
|
||||
{
|
||||
atomic64_xchg(ptr, new_val);
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_set);
|
||||
|
||||
/**
|
||||
EXPORT_SYMBOL(atomic64_read);
|
||||
* atomic64_add_return - add and return
|
||||
* @delta: integer value to add
|
||||
* @ptr: pointer to type atomic64_t
|
||||
*
|
||||
* Atomically adds @delta to @ptr and returns @delta + *@ptr
|
||||
*/
|
||||
noinline u64 atomic64_add_return(u64 delta, atomic64_t *ptr)
|
||||
{
|
||||
/*
|
||||
* Try first with a (possibly incorrect) assumption about
|
||||
* what we have there. We'll do two loops most likely,
|
||||
* but we'll get an ownership MESI transaction straight away
|
||||
* instead of a read transaction followed by a
|
||||
* flush-for-ownership transaction:
|
||||
*/
|
||||
u64 old_val, new_val, real_val = 0;
|
||||
|
||||
do {
|
||||
old_val = real_val;
|
||||
new_val = old_val + delta;
|
||||
|
||||
real_val = atomic64_cmpxchg(ptr, old_val, new_val);
|
||||
|
||||
} while (real_val != old_val);
|
||||
|
||||
return new_val;
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_add_return);
|
||||
|
||||
u64 atomic64_sub_return(u64 delta, atomic64_t *ptr)
|
||||
{
|
||||
return atomic64_add_return(-delta, ptr);
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_sub_return);
|
||||
|
||||
u64 atomic64_inc_return(atomic64_t *ptr)
|
||||
{
|
||||
return atomic64_add_return(1, ptr);
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_inc_return);
|
||||
|
||||
u64 atomic64_dec_return(atomic64_t *ptr)
|
||||
{
|
||||
return atomic64_sub_return(1, ptr);
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_dec_return);
|
||||
|
||||
/**
|
||||
* atomic64_add - add integer to atomic64 variable
|
||||
* @delta: integer value to add
|
||||
* @ptr: pointer to type atomic64_t
|
||||
*
|
||||
* Atomically adds @delta to @ptr.
|
||||
*/
|
||||
void atomic64_add(u64 delta, atomic64_t *ptr)
|
||||
{
|
||||
atomic64_add_return(delta, ptr);
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_add);
|
||||
|
||||
/**
|
||||
* atomic64_sub - subtract the atomic64 variable
|
||||
* @delta: integer value to subtract
|
||||
* @ptr: pointer to type atomic64_t
|
||||
*
|
||||
* Atomically subtracts @delta from @ptr.
|
||||
*/
|
||||
void atomic64_sub(u64 delta, atomic64_t *ptr)
|
||||
{
|
||||
atomic64_add(-delta, ptr);
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_sub);
|
||||
|
||||
/**
|
||||
* atomic64_sub_and_test - subtract value from variable and test result
|
||||
* @delta: integer value to subtract
|
||||
* @ptr: pointer to type atomic64_t
|
||||
*
|
||||
* Atomically subtracts @delta from @ptr and returns
|
||||
* true if the result is zero, or false for all
|
||||
* other cases.
|
||||
*/
|
||||
int atomic64_sub_and_test(u64 delta, atomic64_t *ptr)
|
||||
{
|
||||
u64 new_val = atomic64_sub_return(delta, ptr);
|
||||
|
||||
return new_val == 0;
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_sub_and_test);
|
||||
|
||||
/**
|
||||
* atomic64_inc - increment atomic64 variable
|
||||
* @ptr: pointer to type atomic64_t
|
||||
*
|
||||
* Atomically increments @ptr by 1.
|
||||
*/
|
||||
void atomic64_inc(atomic64_t *ptr)
|
||||
{
|
||||
atomic64_add(1, ptr);
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_inc);
|
||||
|
||||
/**
|
||||
* atomic64_dec - decrement atomic64 variable
|
||||
* @ptr: pointer to type atomic64_t
|
||||
*
|
||||
* Atomically decrements @ptr by 1.
|
||||
*/
|
||||
void atomic64_dec(atomic64_t *ptr)
|
||||
{
|
||||
atomic64_sub(1, ptr);
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_dec);
|
||||
|
||||
/**
|
||||
* atomic64_dec_and_test - decrement and test
|
||||
* @ptr: pointer to type atomic64_t
|
||||
*
|
||||
* Atomically decrements @ptr by 1 and
|
||||
* returns true if the result is 0, or false for all other
|
||||
* cases.
|
||||
*/
|
||||
int atomic64_dec_and_test(atomic64_t *ptr)
|
||||
{
|
||||
return atomic64_sub_and_test(1, ptr);
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_dec_and_test);
|
||||
|
||||
/**
|
||||
* atomic64_inc_and_test - increment and test
|
||||
* @ptr: pointer to type atomic64_t
|
||||
*
|
||||
* Atomically increments @ptr by 1
|
||||
* and returns true if the result is zero, or false for all
|
||||
* other cases.
|
||||
*/
|
||||
int atomic64_inc_and_test(atomic64_t *ptr)
|
||||
{
|
||||
return atomic64_sub_and_test(-1, ptr);
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_inc_and_test);
|
||||
|
||||
/**
|
||||
* atomic64_add_negative - add and test if negative
|
||||
* @delta: integer value to add
|
||||
* @ptr: pointer to type atomic64_t
|
||||
*
|
||||
* Atomically adds @delta to @ptr and returns true
|
||||
* if the result is negative, or false when
|
||||
* result is greater than or equal to zero.
|
||||
*/
|
||||
int atomic64_add_negative(u64 delta, atomic64_t *ptr)
|
||||
{
|
||||
s64 new_val = atomic64_add_return(delta, ptr);
|
||||
|
||||
return new_val < 0;
|
||||
}
|
||||
EXPORT_SYMBOL(atomic64_add_negative);
|
||||
+10
-10
@@ -164,7 +164,7 @@ endif
|
||||
|
||||
# CFLAGS and LDFLAGS are for the users to override from the command line.
|
||||
|
||||
CFLAGS = $(M64) -ggdb3 -Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6
|
||||
CFLAGS = $(M64) -ggdb3 -Wall -Wextra -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6
|
||||
LDFLAGS = -lpthread -lrt -lelf -lm
|
||||
ALL_CFLAGS = $(CFLAGS)
|
||||
ALL_LDFLAGS = $(LDFLAGS)
|
||||
@@ -223,7 +223,7 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
|
||||
# Those must not be GNU-specific; they are shared with perl/ which may
|
||||
# be built by a different compiler. (Note that this is an artifact now
|
||||
# but it still might be nice to keep that distinction.)
|
||||
BASIC_CFLAGS =
|
||||
BASIC_CFLAGS = -Iutil/include
|
||||
BASIC_LDFLAGS =
|
||||
|
||||
# Guard against environment variables
|
||||
@@ -289,10 +289,11 @@ export PERL_PATH
|
||||
LIB_FILE=libperf.a
|
||||
|
||||
LIB_H += ../../include/linux/perf_counter.h
|
||||
LIB_H += ../../include/linux/rbtree.h
|
||||
LIB_H += ../../include/linux/list.h
|
||||
LIB_H += util/include/linux/list.h
|
||||
LIB_H += perf.h
|
||||
LIB_H += util/types.h
|
||||
LIB_H += util/list.h
|
||||
LIB_H += util/rbtree.h
|
||||
LIB_H += util/levenshtein.h
|
||||
LIB_H += util/parse-options.h
|
||||
LIB_H += util/parse-events.h
|
||||
@@ -305,6 +306,7 @@ LIB_H += util/strlist.h
|
||||
LIB_H += util/run-command.h
|
||||
LIB_H += util/sigchain.h
|
||||
LIB_H += util/symbol.h
|
||||
LIB_H += util/module.h
|
||||
LIB_H += util/color.h
|
||||
|
||||
LIB_OBJS += util/abspath.o
|
||||
@@ -328,6 +330,7 @@ LIB_OBJS += util/usage.o
|
||||
LIB_OBJS += util/wrapper.o
|
||||
LIB_OBJS += util/sigchain.o
|
||||
LIB_OBJS += util/symbol.o
|
||||
LIB_OBJS += util/module.o
|
||||
LIB_OBJS += util/color.o
|
||||
LIB_OBJS += util/pager.o
|
||||
LIB_OBJS += util/header.o
|
||||
@@ -381,12 +384,6 @@ ifndef CC_LD_DYNPATH
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef ZLIB_PATH
|
||||
BASIC_CFLAGS += -I$(ZLIB_PATH)/include
|
||||
EXTLIBS += -L$(ZLIB_PATH)/$(lib) $(CC_LD_DYNPATH)$(ZLIB_PATH)/$(lib)
|
||||
endif
|
||||
EXTLIBS += -lz
|
||||
|
||||
ifdef NEEDS_SOCKET
|
||||
EXTLIBS += -lsocket
|
||||
endif
|
||||
@@ -697,6 +694,9 @@ builtin-init-db.o: builtin-init-db.c PERF-CFLAGS
|
||||
util/config.o: util/config.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
|
||||
util/rbtree.o: ../../lib/rbtree.c PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o util/rbtree.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
|
||||
|
||||
perf-%$X: %.o $(PERFLIBS)
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
#include "util/util.h"
|
||||
|
||||
#include "util/color.h"
|
||||
#include "util/list.h"
|
||||
#include <linux/list.h>
|
||||
#include "util/cache.h"
|
||||
#include "util/rbtree.h"
|
||||
#include <linux/rbtree.h>
|
||||
#include "util/symbol.h"
|
||||
#include "util/string.h"
|
||||
|
||||
@@ -25,10 +25,6 @@
|
||||
#define SHOW_USER 2
|
||||
#define SHOW_HV 4
|
||||
|
||||
#define MIN_GREEN 0.5
|
||||
#define MIN_RED 5.0
|
||||
|
||||
|
||||
static char const *input_name = "perf.data";
|
||||
static char *vmlinux = "vmlinux";
|
||||
|
||||
@@ -43,6 +39,10 @@ static int dump_trace = 0;
|
||||
|
||||
static int verbose;
|
||||
|
||||
static int modules;
|
||||
|
||||
static int full_paths;
|
||||
|
||||
static int print_line;
|
||||
|
||||
static unsigned long page_size;
|
||||
@@ -160,7 +160,7 @@ static void dsos__fprintf(FILE *fp)
|
||||
|
||||
static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
|
||||
{
|
||||
return dso__find_symbol(kernel_dso, ip);
|
||||
return dso__find_symbol(dso, ip);
|
||||
}
|
||||
|
||||
static int load_kernel(void)
|
||||
@@ -171,8 +171,8 @@ static int load_kernel(void)
|
||||
if (!kernel_dso)
|
||||
return -1;
|
||||
|
||||
err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose);
|
||||
if (err) {
|
||||
err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules);
|
||||
if (err <= 0) {
|
||||
dso__delete(kernel_dso);
|
||||
kernel_dso = NULL;
|
||||
} else
|
||||
@@ -203,7 +203,7 @@ static u64 map__map_ip(struct map *map, u64 ip)
|
||||
return ip - map->start + map->pgoff;
|
||||
}
|
||||
|
||||
static u64 vdso__map_ip(struct map *map, u64 ip)
|
||||
static u64 vdso__map_ip(struct map *map __used, u64 ip)
|
||||
{
|
||||
return ip;
|
||||
}
|
||||
@@ -600,7 +600,7 @@ static LIST_HEAD(hist_entry__sort_list);
|
||||
|
||||
static int sort_dimension__add(char *tok)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
|
||||
struct sort_dimension *sd = &sort_dimensions[i];
|
||||
@@ -1043,24 +1043,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *get_color(double percent)
|
||||
{
|
||||
char *color = PERF_COLOR_NORMAL;
|
||||
|
||||
/*
|
||||
* We color high-overhead entries in red, mid-overhead
|
||||
* entries in green - and keep the low overhead places
|
||||
* normal:
|
||||
*/
|
||||
if (percent >= MIN_RED)
|
||||
color = PERF_COLOR_RED;
|
||||
else {
|
||||
if (percent > MIN_GREEN)
|
||||
color = PERF_COLOR_GREEN;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
|
||||
{
|
||||
@@ -1069,7 +1051,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
|
||||
static const char *prev_color;
|
||||
unsigned int offset;
|
||||
size_t line_len;
|
||||
u64 line_ip;
|
||||
s64 line_ip;
|
||||
int ret;
|
||||
char *c;
|
||||
|
||||
@@ -1122,7 +1104,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
|
||||
} else if (sym->hist_sum)
|
||||
percent = 100.0 * hits / sym->hist_sum;
|
||||
|
||||
color = get_color(percent);
|
||||
color = get_percent_color(percent);
|
||||
|
||||
/*
|
||||
* Also color the filename and line if needed, with
|
||||
@@ -1258,7 +1240,7 @@ static void print_summary(char *filename)
|
||||
|
||||
sym_ext = rb_entry(node, struct sym_ext, node);
|
||||
percent = sym_ext->percent;
|
||||
color = get_color(percent);
|
||||
color = get_percent_color(percent);
|
||||
path = sym_ext->path;
|
||||
|
||||
color_fprintf(stdout, color, " %7.2f %s", percent, path);
|
||||
@@ -1268,19 +1250,25 @@ static void print_summary(char *filename)
|
||||
|
||||
static void annotate_sym(struct dso *dso, struct symbol *sym)
|
||||
{
|
||||
char *filename = dso->name;
|
||||
char *filename = dso->name, *d_filename;
|
||||
u64 start, end, len;
|
||||
char command[PATH_MAX*2];
|
||||
FILE *file;
|
||||
|
||||
if (!filename)
|
||||
return;
|
||||
if (dso == kernel_dso)
|
||||
if (sym->module)
|
||||
filename = sym->module->path;
|
||||
else if (dso == kernel_dso)
|
||||
filename = vmlinux;
|
||||
|
||||
start = sym->obj_start;
|
||||
if (!start)
|
||||
start = sym->start;
|
||||
if (full_paths)
|
||||
d_filename = filename;
|
||||
else
|
||||
d_filename = basename(filename);
|
||||
|
||||
end = start + sym->end - sym->start + 1;
|
||||
len = sym->end - sym->start;
|
||||
@@ -1291,13 +1279,14 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
|
||||
}
|
||||
|
||||
printf("\n\n------------------------------------------------\n");
|
||||
printf(" Percent | Source code & Disassembly of %s\n", filename);
|
||||
printf(" Percent | Source code & Disassembly of %s\n", d_filename);
|
||||
printf("------------------------------------------------\n");
|
||||
|
||||
if (verbose >= 2)
|
||||
printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);
|
||||
|
||||
sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (u64)start, (u64)end, filename);
|
||||
sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
|
||||
(u64)start, (u64)end, filename, filename);
|
||||
|
||||
if (verbose >= 3)
|
||||
printf("doing: %s\n", command);
|
||||
@@ -1428,7 +1417,7 @@ more:
|
||||
|
||||
head += size;
|
||||
|
||||
if (offset + head < stat.st_size)
|
||||
if (offset + head < (unsigned long)stat.st_size)
|
||||
goto more;
|
||||
|
||||
rc = EXIT_SUCCESS;
|
||||
@@ -1472,8 +1461,12 @@ static const struct option options[] = {
|
||||
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
|
||||
"dump raw trace in ASCII"),
|
||||
OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
|
||||
OPT_BOOLEAN('m', "modules", &modules,
|
||||
"load module symbols - WARNING: use only with -k and LIVE kernel"),
|
||||
OPT_BOOLEAN('l', "print-line", &print_line,
|
||||
"print matching source lines (may be slow)"),
|
||||
OPT_BOOLEAN('P', "full-paths", &full_paths,
|
||||
"Don't shorten the displayed pathnames"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
@@ -1492,7 +1485,7 @@ static void setup_sorting(void)
|
||||
free(str);
|
||||
}
|
||||
|
||||
int cmd_annotate(int argc, const char **argv, const char *prefix)
|
||||
int cmd_annotate(int argc, const char **argv, const char *prefix __used)
|
||||
{
|
||||
symbol__init();
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* Builtin help command
|
||||
*/
|
||||
#include "perf.h"
|
||||
#include "util/cache.h"
|
||||
#include "builtin.h"
|
||||
#include "util/exec_cmd.h"
|
||||
@@ -277,7 +278,7 @@ static struct cmdnames main_cmds, other_cmds;
|
||||
|
||||
void list_common_cmds_help(void)
|
||||
{
|
||||
int i, longest = 0;
|
||||
unsigned int i, longest = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
|
||||
if (longest < strlen(common_cmds[i].name))
|
||||
@@ -415,9 +416,10 @@ static void show_html_page(const char *perf_cmd)
|
||||
open_html(page_path.buf);
|
||||
}
|
||||
|
||||
int cmd_help(int argc, const char **argv, const char *prefix)
|
||||
int cmd_help(int argc, const char **argv, const char *prefix __used)
|
||||
{
|
||||
const char *alias;
|
||||
|
||||
load_command_list("perf-", &main_cmds, &other_cmds);
|
||||
|
||||
perf_config(perf_help_config, NULL);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "util/parse-options.h"
|
||||
#include "util/parse-events.h"
|
||||
|
||||
int cmd_list(int argc, const char **argv, const char *prefix)
|
||||
int cmd_list(int argc __used, const char **argv __used, const char *prefix __used)
|
||||
{
|
||||
print_events();
|
||||
return 0;
|
||||
|
||||
@@ -294,7 +294,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
|
||||
while (1) {
|
||||
char bf[BUFSIZ], *pbf = bf;
|
||||
struct mmap_event mmap_ev = {
|
||||
.header.type = PERF_EVENT_MMAP,
|
||||
.header = { .type = PERF_EVENT_MMAP },
|
||||
};
|
||||
int n;
|
||||
size_t size;
|
||||
@@ -650,7 +650,7 @@ static const struct option options[] = {
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
int cmd_record(int argc, const char **argv, const char *prefix)
|
||||
int cmd_record(int argc, const char **argv, const char *prefix __used)
|
||||
{
|
||||
int counter;
|
||||
|
||||
|
||||
+303
-80
File diff suppressed because it is too large
Load Diff
+24
-27
@@ -64,7 +64,7 @@ static struct perf_counter_attr default_attrs[] = {
|
||||
|
||||
static int system_wide = 0;
|
||||
static int verbose = 0;
|
||||
static int nr_cpus = 0;
|
||||
static unsigned int nr_cpus = 0;
|
||||
static int run_idx = 0;
|
||||
|
||||
static int run_count = 1;
|
||||
@@ -96,6 +96,10 @@ static u64 walltime_nsecs_noise;
|
||||
static u64 runtime_cycles_avg;
|
||||
static u64 runtime_cycles_noise;
|
||||
|
||||
#define MATCH_EVENT(t, c, counter) \
|
||||
(attrs[counter].type == PERF_TYPE_##t && \
|
||||
attrs[counter].config == PERF_COUNT_##c)
|
||||
|
||||
#define ERR_PERF_OPEN \
|
||||
"Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n"
|
||||
|
||||
@@ -108,7 +112,8 @@ static void create_perf_stat_counter(int counter, int pid)
|
||||
PERF_FORMAT_TOTAL_TIME_RUNNING;
|
||||
|
||||
if (system_wide) {
|
||||
int cpu;
|
||||
unsigned int cpu;
|
||||
|
||||
for (cpu = 0; cpu < nr_cpus; cpu++) {
|
||||
fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0);
|
||||
if (fd[cpu][counter] < 0 && verbose)
|
||||
@@ -132,13 +137,8 @@ static void create_perf_stat_counter(int counter, int pid)
|
||||
*/
|
||||
static inline int nsec_counter(int counter)
|
||||
{
|
||||
if (attrs[counter].type != PERF_TYPE_SOFTWARE)
|
||||
return 0;
|
||||
|
||||
if (attrs[counter].config == PERF_COUNT_SW_CPU_CLOCK)
|
||||
return 1;
|
||||
|
||||
if (attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
|
||||
if (MATCH_EVENT(SOFTWARE, SW_CPU_CLOCK, counter) ||
|
||||
MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -150,8 +150,8 @@ static inline int nsec_counter(int counter)
|
||||
static void read_counter(int counter)
|
||||
{
|
||||
u64 *count, single_count[3];
|
||||
ssize_t res;
|
||||
int cpu, nv;
|
||||
unsigned int cpu;
|
||||
size_t res, nv;
|
||||
int scaled;
|
||||
|
||||
count = event_res[run_idx][counter];
|
||||
@@ -165,6 +165,7 @@ static void read_counter(int counter)
|
||||
|
||||
res = read(fd[cpu][counter], single_count, nv * sizeof(u64));
|
||||
assert(res == nv * sizeof(u64));
|
||||
|
||||
close(fd[cpu][counter]);
|
||||
fd[cpu][counter] = -1;
|
||||
|
||||
@@ -192,15 +193,13 @@ static void read_counter(int counter)
|
||||
/*
|
||||
* Save the full runtime - to allow normalization during printout:
|
||||
*/
|
||||
if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
|
||||
attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
|
||||
if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
|
||||
runtime_nsecs[run_idx] = count[0];
|
||||
if (attrs[counter].type == PERF_TYPE_HARDWARE &&
|
||||
attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES)
|
||||
if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter))
|
||||
runtime_cycles[run_idx] = count[0];
|
||||
}
|
||||
|
||||
static int run_perf_stat(int argc, const char **argv)
|
||||
static int run_perf_stat(int argc __used, const char **argv)
|
||||
{
|
||||
unsigned long long t0, t1;
|
||||
int status = 0;
|
||||
@@ -240,7 +239,8 @@ static int run_perf_stat(int argc, const char **argv)
|
||||
/*
|
||||
* Wait until the parent tells us to go.
|
||||
*/
|
||||
read(go_pipe[0], &buf, 1);
|
||||
if (read(go_pipe[0], &buf, 1) == -1)
|
||||
perror("unable to read pipe");
|
||||
|
||||
execvp(argv[0], (char **)argv);
|
||||
|
||||
@@ -253,7 +253,8 @@ static int run_perf_stat(int argc, const char **argv)
|
||||
*/
|
||||
close(child_ready_pipe[1]);
|
||||
close(go_pipe[0]);
|
||||
read(child_ready_pipe[0], &buf, 1);
|
||||
if (read(child_ready_pipe[0], &buf, 1) == -1)
|
||||
perror("unable to read pipe");
|
||||
close(child_ready_pipe[0]);
|
||||
|
||||
for (counter = 0; counter < nr_counters; counter++)
|
||||
@@ -290,9 +291,7 @@ static void nsec_printout(int counter, u64 *count, u64 *noise)
|
||||
|
||||
fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter));
|
||||
|
||||
if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
|
||||
attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) {
|
||||
|
||||
if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) {
|
||||
if (walltime_nsecs_avg)
|
||||
fprintf(stderr, " # %10.3f CPUs ",
|
||||
(double)count[0] / (double)walltime_nsecs_avg);
|
||||
@@ -305,9 +304,7 @@ static void abs_printout(int counter, u64 *count, u64 *noise)
|
||||
fprintf(stderr, " %14Ld %-24s", count[0], event_name(counter));
|
||||
|
||||
if (runtime_cycles_avg &&
|
||||
attrs[counter].type == PERF_TYPE_HARDWARE &&
|
||||
attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) {
|
||||
|
||||
MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) {
|
||||
fprintf(stderr, " # %10.3f IPC ",
|
||||
(double)count[0] / (double)runtime_cycles_avg);
|
||||
} else {
|
||||
@@ -390,7 +387,7 @@ static void calc_avg(void)
|
||||
event_res_avg[j]+1, event_res[i][j]+1);
|
||||
update_avg("counter/2", j,
|
||||
event_res_avg[j]+2, event_res[i][j]+2);
|
||||
if (event_scaled[i][j] != -1)
|
||||
if (event_scaled[i][j] != (u64)-1)
|
||||
update_avg("scaled", j,
|
||||
event_scaled_avg + j, event_scaled[i]+j);
|
||||
else
|
||||
@@ -510,7 +507,7 @@ static const struct option options[] = {
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
int cmd_stat(int argc, const char **argv, const char *prefix)
|
||||
int cmd_stat(int argc, const char **argv, const char *prefix __used)
|
||||
{
|
||||
int status;
|
||||
|
||||
@@ -528,7 +525,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix)
|
||||
|
||||
nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
assert(nr_cpus <= MAX_NR_CPUS);
|
||||
assert(nr_cpus >= 0);
|
||||
assert((int)nr_cpus >= 0);
|
||||
|
||||
/*
|
||||
* We dont want to block the signals - that would cause
|
||||
|
||||
+42
-28
@@ -23,7 +23,7 @@
|
||||
#include "util/symbol.h"
|
||||
#include "util/color.h"
|
||||
#include "util/util.h"
|
||||
#include "util/rbtree.h"
|
||||
#include <linux/rbtree.h>
|
||||
#include "util/parse-options.h"
|
||||
#include "util/parse-events.h"
|
||||
|
||||
@@ -66,6 +66,7 @@ static unsigned int page_size;
|
||||
static unsigned int mmap_pages = 16;
|
||||
static int freq = 0;
|
||||
static int verbose = 0;
|
||||
static char *vmlinux = NULL;
|
||||
|
||||
static char *sym_filter;
|
||||
static unsigned long filter_start;
|
||||
@@ -238,7 +239,6 @@ static void print_sym_table(void)
|
||||
for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
|
||||
struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node);
|
||||
struct symbol *sym = (struct symbol *)(syme + 1);
|
||||
char *color = PERF_COLOR_NORMAL;
|
||||
double pcnt;
|
||||
|
||||
if (++printed > print_entries || syme->snap_count < count_filter)
|
||||
@@ -247,29 +247,20 @@ static void print_sym_table(void)
|
||||
pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
|
||||
sum_ksamples));
|
||||
|
||||
/*
|
||||
* We color high-overhead entries in red, mid-overhead
|
||||
* entries in green - and keep the low overhead places
|
||||
* normal:
|
||||
*/
|
||||
if (pcnt >= 5.0) {
|
||||
color = PERF_COLOR_RED;
|
||||
} else {
|
||||
if (pcnt >= 0.5)
|
||||
color = PERF_COLOR_GREEN;
|
||||
}
|
||||
|
||||
if (nr_counters == 1)
|
||||
printf("%20.2f - ", syme->weight);
|
||||
else
|
||||
printf("%9.1f %10ld - ", syme->weight, syme->snap_count);
|
||||
|
||||
color_fprintf(stdout, color, "%4.1f%%", pcnt);
|
||||
printf(" - %016llx : %s\n", sym->start, sym->name);
|
||||
percent_color_fprintf(stdout, "%4.1f%%", pcnt);
|
||||
printf(" - %016llx : %s", sym->start, sym->name);
|
||||
if (sym->module)
|
||||
printf("\t[%s]", sym->module->name);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void *display_thread(void *arg)
|
||||
static void *display_thread(void *arg __used)
|
||||
{
|
||||
struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
|
||||
int delay_msecs = delay_secs * 1000;
|
||||
@@ -286,11 +277,31 @@ static void *display_thread(void *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Tag samples to be skipped. */
|
||||
static const char *skip_symbols[] = {
|
||||
"default_idle",
|
||||
"cpu_idle",
|
||||
"enter_idle",
|
||||
"exit_idle",
|
||||
"mwait_idle",
|
||||
"ppc64_runlatch_off",
|
||||
"pseries_dedicated_idle_sleep",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int symbol_filter(struct dso *self, struct symbol *sym)
|
||||
{
|
||||
static int filter_match;
|
||||
struct sym_entry *syme;
|
||||
const char *name = sym->name;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* ppc64 uses function descriptors and appends a '.' to the
|
||||
* start of every instruction address. Remove it.
|
||||
*/
|
||||
if (name[0] == '.')
|
||||
name++;
|
||||
|
||||
if (!strcmp(name, "_text") ||
|
||||
!strcmp(name, "_etext") ||
|
||||
@@ -302,13 +313,12 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
|
||||
return 1;
|
||||
|
||||
syme = dso__sym_priv(self, sym);
|
||||
/* Tag samples to be skipped. */
|
||||
if (!strcmp("default_idle", name) ||
|
||||
!strcmp("cpu_idle", name) ||
|
||||
!strcmp("enter_idle", name) ||
|
||||
!strcmp("exit_idle", name) ||
|
||||
!strcmp("mwait_idle", name))
|
||||
syme->skip = 1;
|
||||
for (i = 0; skip_symbols[i]; i++) {
|
||||
if (!strcmp(skip_symbols[i], name)) {
|
||||
syme->skip = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (filter_match == 1) {
|
||||
filter_end = sym->start;
|
||||
@@ -340,12 +350,13 @@ static int parse_symbols(void)
|
||||
{
|
||||
struct rb_node *node;
|
||||
struct symbol *sym;
|
||||
int modules = vmlinux ? 1 : 0;
|
||||
|
||||
kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry));
|
||||
if (kernel_dso == NULL)
|
||||
return -1;
|
||||
|
||||
if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1) != 0)
|
||||
if (dso__load_kernel(kernel_dso, vmlinux, symbol_filter, verbose, modules) <= 0)
|
||||
goto out_delete_dso;
|
||||
|
||||
node = rb_first(&kernel_dso->syms);
|
||||
@@ -407,7 +418,7 @@ static void process_event(u64 ip, int counter, int user)
|
||||
struct mmap_data {
|
||||
int counter;
|
||||
void *base;
|
||||
unsigned int mask;
|
||||
int mask;
|
||||
unsigned int prev;
|
||||
};
|
||||
|
||||
@@ -661,6 +672,7 @@ static const struct option options[] = {
|
||||
"system-wide collection from all CPUs"),
|
||||
OPT_INTEGER('C', "CPU", &profile_cpu,
|
||||
"CPU to profile on"),
|
||||
OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
|
||||
OPT_INTEGER('m', "mmap-pages", &mmap_pages,
|
||||
"number of mmap data pages"),
|
||||
OPT_INTEGER('r', "realtime", &realtime_prio,
|
||||
@@ -675,7 +687,7 @@ static const struct option options[] = {
|
||||
"put the counters into a counter group"),
|
||||
OPT_STRING('s', "sym-filter", &sym_filter, "pattern",
|
||||
"only display symbols matchig this pattern"),
|
||||
OPT_BOOLEAN('z', "zero", &group,
|
||||
OPT_BOOLEAN('z', "zero", &zero,
|
||||
"zero history across updates"),
|
||||
OPT_INTEGER('F', "freq", &freq,
|
||||
"profile at this frequency"),
|
||||
@@ -686,10 +698,12 @@ static const struct option options[] = {
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
int cmd_top(int argc, const char **argv, const char *prefix)
|
||||
int cmd_top(int argc, const char **argv, const char *prefix __used)
|
||||
{
|
||||
int counter;
|
||||
|
||||
symbol__init();
|
||||
|
||||
page_size = sysconf(_SC_PAGE_SIZE);
|
||||
|
||||
argc = parse_options(argc, argv, options, top_usage, 0);
|
||||
|
||||
+1
-4
@@ -229,9 +229,6 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
|
||||
use_pager = 1;
|
||||
commit_pager_choice();
|
||||
|
||||
if (p->option & NEED_WORK_TREE)
|
||||
/* setup_work_tree() */;
|
||||
|
||||
status = p->fn(argc, argv, prefix);
|
||||
if (status)
|
||||
return status & 0xff;
|
||||
@@ -266,7 +263,7 @@ static void handle_internal_command(int argc, const char **argv)
|
||||
{ "annotate", cmd_annotate, 0 },
|
||||
{ "version", cmd_version, 0 },
|
||||
};
|
||||
int i;
|
||||
unsigned int i;
|
||||
static const char ext[] = STRIP_EXTENSION;
|
||||
|
||||
if (sizeof(ext) > 1) {
|
||||
|
||||
@@ -68,6 +68,8 @@ static inline unsigned long long rdclock(void)
|
||||
#define __user
|
||||
#define asmlinkage
|
||||
|
||||
#define __used __attribute__((__unused__))
|
||||
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#define min(x, y) ({ \
|
||||
typeof(x) _min1 = (x); \
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
static const char *alias_key;
|
||||
static char *alias_val;
|
||||
|
||||
static int alias_lookup_cb(const char *k, const char *v, void *cb)
|
||||
static int alias_lookup_cb(const char *k, const char *v, void *cb __used)
|
||||
{
|
||||
if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) {
|
||||
if (!v)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user